s4-torture: No need to disable rpc.spoolss.win test when compiled with MIT kerberos.
[Samba/vl.git] / source4 / torture / rpc / spoolss.c
blob5e6c4c73e46d6010b34313a7c8ec17aed8c7c790
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Stefan Metzmacher 2005
7 Copyright (C) Jelmer Vernooij 2007
8 Copyright (C) Guenther Deschner 2009-2011,2013
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "libcli/smb2/smb2.h"
39 #include "libcli/smb2/smb2_calls.h"
40 #include "lib/cmdline/popt_common.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
45 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
46 #define TORTURE_PRINTER "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX "torture_printer_ex"
49 #define TORTURE_DRIVER "torture_driver"
50 #define TORTURE_DRIVER_EX "torture_driver_ex"
51 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
52 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
53 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
54 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
55 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
56 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
57 #define TORTURE_PRINTER_STATIC1 "print1"
59 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
60 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
61 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
62 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
63 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
64 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
66 struct test_spoolss_context {
67 struct dcerpc_pipe *spoolss_pipe;
69 /* server environment */
70 const char *environment;
72 /* print server handle */
73 struct policy_handle server_handle;
75 /* for EnumPorts */
76 uint32_t port_count[3];
77 union spoolss_PortInfo *ports[3];
79 /* for EnumPrinterDrivers */
80 uint32_t driver_count[8];
81 union spoolss_DriverInfo *drivers[8];
83 /* for EnumMonitors */
84 uint32_t monitor_count[3];
85 union spoolss_MonitorInfo *monitors[3];
87 /* for EnumPrintProcessors */
88 uint32_t print_processor_count[2];
89 union spoolss_PrintProcessorInfo *print_processors[2];
91 /* for EnumPrinters */
92 uint32_t printer_count[6];
93 union spoolss_PrinterInfo *printers[6];
96 struct torture_driver_context {
97 struct {
98 const char *driver_directory;
99 const char *environment;
100 } local;
101 struct {
102 const char *driver_directory;
103 const char *environment;
104 } remote;
105 struct spoolss_AddDriverInfo8 info8;
106 bool ex;
109 struct torture_printer_context {
110 struct dcerpc_pipe *spoolss_pipe;
111 struct spoolss_SetPrinterInfo2 info2;
112 struct torture_driver_context driver;
113 bool ex;
114 bool wellknown;
115 bool added_driver;
116 bool have_driver;
117 struct spoolss_DeviceMode *devmode;
118 struct policy_handle handle;
121 static bool upload_printer_driver(struct torture_context *tctx,
122 const char *server_name,
123 struct torture_driver_context *d);
124 static bool remove_printer_driver(struct torture_context *tctx,
125 const char *server_name,
126 struct torture_driver_context *d);
127 static bool fillup_printserver_info(struct torture_context *tctx,
128 struct dcerpc_pipe *p,
129 struct torture_driver_context *d);
130 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
131 struct dcerpc_binding_handle *b,
132 const char *server_name,
133 struct spoolss_AddDriverInfo8 *r,
134 uint32_t flags,
135 bool ex,
136 const char *remote_driver_dir);
138 #define COMPARE_STRING(tctx, c,r,e) \
139 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
141 /* not every compiler supports __typeof__() */
142 #if (__GNUC__ >= 3)
143 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
144 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
145 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
147 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
148 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
150 } while(0)
151 #else
152 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
153 #endif
155 #define COMPARE_UINT32(tctx, c, r, e) do {\
156 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
157 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
158 } while(0)
160 #define COMPARE_UINT64(tctx, c, r, e) do {\
161 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
162 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
163 } while(0)
166 #define COMPARE_NTTIME(tctx, c, r, e) do {\
167 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
168 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
169 } while(0)
171 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
172 int __i; \
173 if (!c.e && !r.e) { \
174 break; \
176 if (c.e && !r.e) { \
177 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
179 if (!c.e && r.e) { \
180 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
182 for (__i=0;c.e[__i] != NULL; __i++) { \
183 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
185 } while(0)
187 #define CHECK_ALIGN(size, n) do {\
188 if (size % n) {\
189 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
190 size, n, size + n - (size % n));\
192 } while(0)
194 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
196 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
197 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
198 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
199 uint32_t round_size = DO_ROUND(size, align);\
200 if (round_size != needed) {\
201 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
202 CHECK_ALIGN(size, align);\
205 } while(0)
207 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
208 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
209 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
210 uint32_t round_size = DO_ROUND(size, align);\
211 if (round_size != needed) {\
212 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
213 CHECK_ALIGN(size, align);\
216 } while(0)
218 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
219 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
220 uint32_t size = ndr_size_##fn(info, level, 0);\
221 uint32_t round_size = DO_ROUND(size, align);\
222 if (round_size != needed) {\
223 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
224 CHECK_ALIGN(size, align);\
227 } while(0)
229 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
230 const union spoolss_PrinterInfo *i,
231 uint32_t level,
232 union spoolss_SetPrinterInfo *s)
234 switch (level) {
235 case 0:
236 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
237 break;
238 case 2:
239 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
240 s->info2->servername = i->info2.servername;
241 s->info2->printername = i->info2.printername;
242 s->info2->sharename = i->info2.sharename;
243 s->info2->portname = i->info2.portname;
244 s->info2->drivername = i->info2.drivername;
245 s->info2->comment = i->info2.comment;
246 s->info2->location = i->info2.location;
247 s->info2->devmode_ptr = NULL;
248 s->info2->sepfile = i->info2.sepfile;
249 s->info2->printprocessor = i->info2.printprocessor;
250 s->info2->datatype = i->info2.datatype;
251 s->info2->parameters = i->info2.parameters;
252 s->info2->secdesc_ptr = NULL;
253 s->info2->attributes = i->info2.attributes;
254 s->info2->priority = i->info2.priority;
255 s->info2->defaultpriority = i->info2.defaultpriority;
256 s->info2->starttime = i->info2.starttime;
257 s->info2->untiltime = i->info2.untiltime;
258 s->info2->status = i->info2.status;
259 s->info2->cjobs = i->info2.cjobs;
260 s->info2->averageppm = i->info2.averageppm;
261 break;
262 case 3:
263 case 4:
264 case 5:
265 case 6:
266 case 7:
267 case 8:
268 case 9:
269 default:
270 return false;
273 return true;
276 static bool test_OpenPrinter_server(struct torture_context *tctx,
277 struct dcerpc_pipe *p,
278 struct policy_handle *server_handle)
280 NTSTATUS status;
281 struct spoolss_OpenPrinter op;
282 struct dcerpc_binding_handle *b = p->binding_handle;
284 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
285 op.in.datatype = NULL;
286 op.in.devmode_ctr.devmode= NULL;
287 op.in.access_mask = 0;
288 op.out.handle = server_handle;
290 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
292 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
293 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
294 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
296 return true;
299 static bool test_EnumPorts(struct torture_context *tctx,
300 void *private_data)
302 struct test_spoolss_context *ctx =
303 talloc_get_type_abort(private_data, struct test_spoolss_context);
304 struct dcerpc_pipe *p = ctx->spoolss_pipe;
305 struct dcerpc_binding_handle *b = p->binding_handle;
306 NTSTATUS status;
307 struct spoolss_EnumPorts r;
308 uint16_t levels[] = { 1, 2 };
309 int i, j;
311 for (i=0;i<ARRAY_SIZE(levels);i++) {
312 int level = levels[i];
313 DATA_BLOB blob;
314 uint32_t needed;
315 uint32_t count;
316 union spoolss_PortInfo *info;
318 r.in.servername = "";
319 r.in.level = level;
320 r.in.buffer = NULL;
321 r.in.offered = 0;
322 r.out.needed = &needed;
323 r.out.count = &count;
324 r.out.info = &info;
326 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
328 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
329 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
330 if (W_ERROR_IS_OK(r.out.result)) {
331 /* TODO: do some more checks here */
332 continue;
334 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
335 "EnumPorts unexpected return code");
337 blob = data_blob_talloc_zero(ctx, needed);
338 r.in.buffer = &blob;
339 r.in.offered = needed;
341 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
342 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
344 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
346 torture_assert(tctx, info, "EnumPorts returned no info");
348 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
350 ctx->port_count[level] = count;
351 ctx->ports[level] = info;
354 for (i=1;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 int old_level = levels[i-1];
357 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
358 "EnumPorts invalid value");
360 /* if the array sizes are not the same we would maybe segfault in the following code */
362 for (i=0;i<ARRAY_SIZE(levels);i++) {
363 int level = levels[i];
364 for (j=0;j<ctx->port_count[level];j++) {
365 union spoolss_PortInfo *cur = &ctx->ports[level][j];
366 union spoolss_PortInfo *ref = &ctx->ports[2][j];
367 switch (level) {
368 case 1:
369 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
370 break;
371 case 2:
372 /* level 2 is our reference, and it makes no sense to compare it to itself */
373 break;
378 return true;
381 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
382 void *private_data)
384 struct test_spoolss_context *ctx =
385 talloc_get_type_abort(private_data, struct test_spoolss_context);
387 NTSTATUS status;
388 struct dcerpc_pipe *p = ctx->spoolss_pipe;
389 struct dcerpc_binding_handle *b = p->binding_handle;
390 struct spoolss_GetPrintProcessorDirectory r;
391 struct {
392 uint16_t level;
393 const char *server;
394 } levels[] = {{
395 .level = 1,
396 .server = NULL
398 .level = 1,
399 .server = ""
401 .level = 78,
402 .server = ""
404 .level = 1,
405 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
407 .level = 1024,
408 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
411 int i;
412 uint32_t needed;
414 for (i=0;i<ARRAY_SIZE(levels);i++) {
415 int level = levels[i].level;
416 DATA_BLOB blob;
418 r.in.server = levels[i].server;
419 r.in.environment = ctx->environment;
420 r.in.level = level;
421 r.in.buffer = NULL;
422 r.in.offered = 0;
423 r.out.needed = &needed;
425 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
427 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
428 torture_assert_ntstatus_ok(tctx, status,
429 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
430 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
431 "GetPrintProcessorDirectory unexpected return code");
433 blob = data_blob_talloc_zero(tctx, needed);
434 r.in.buffer = &blob;
435 r.in.offered = needed;
437 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
438 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
440 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
442 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
445 return true;
449 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
450 void *private_data)
452 struct test_spoolss_context *ctx =
453 talloc_get_type_abort(private_data, struct test_spoolss_context);
455 NTSTATUS status;
456 struct dcerpc_pipe *p = ctx->spoolss_pipe;
457 struct dcerpc_binding_handle *b = p->binding_handle;
458 struct spoolss_GetPrinterDriverDirectory r;
459 struct {
460 uint16_t level;
461 const char *server;
462 } levels[] = {{
463 .level = 1,
464 .server = NULL
466 .level = 1,
467 .server = ""
469 .level = 78,
470 .server = ""
472 .level = 1,
473 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
475 .level = 1024,
476 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
479 int i;
480 uint32_t needed;
482 for (i=0;i<ARRAY_SIZE(levels);i++) {
483 int level = levels[i].level;
484 DATA_BLOB blob;
486 r.in.server = levels[i].server;
487 r.in.environment = ctx->environment;
488 r.in.level = level;
489 r.in.buffer = NULL;
490 r.in.offered = 0;
491 r.out.needed = &needed;
493 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
495 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
496 torture_assert_ntstatus_ok(tctx, status,
497 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
498 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
499 "GetPrinterDriverDirectory unexpected return code");
501 blob = data_blob_talloc_zero(tctx, needed);
502 r.in.buffer = &blob;
503 r.in.offered = needed;
505 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
506 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
508 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
510 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
513 return true;
516 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
517 struct dcerpc_binding_handle *b,
518 const char *server_name,
519 const char *environment,
520 uint32_t level,
521 uint32_t *count_p,
522 union spoolss_DriverInfo **info_p)
524 struct spoolss_EnumPrinterDrivers r;
525 uint32_t needed;
526 uint32_t count;
527 union spoolss_DriverInfo *info;
529 r.in.server = server_name;
530 r.in.environment = environment;
531 r.in.level = level;
532 r.in.buffer = NULL;
533 r.in.offered = 0;
534 r.out.needed = &needed;
535 r.out.count = &count;
536 r.out.info = &info;
538 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
539 r.in.environment, r.in.level);
541 torture_assert_ntstatus_ok(tctx,
542 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
543 "EnumPrinterDrivers failed");
544 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
545 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
546 r.in.buffer = &blob;
547 r.in.offered = needed;
549 torture_assert_ntstatus_ok(tctx,
550 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
551 "EnumPrinterDrivers failed");
554 torture_assert_werr_ok(tctx, r.out.result,
555 "EnumPrinterDrivers failed");
557 if (count_p) {
558 *count_p = count;
560 if (info_p) {
561 *info_p = info;
564 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
566 return true;
570 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
571 struct dcerpc_binding_handle *b,
572 const char *server_name,
573 const char *environment,
574 uint32_t level,
575 const char *driver_name,
576 union spoolss_DriverInfo *info_p)
578 uint32_t count;
579 union spoolss_DriverInfo *info;
580 int i;
581 const char *environment_ret = NULL;
583 torture_assert(tctx,
584 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
585 "failed to enumerate printer drivers");
587 for (i=0; i < count; i++) {
588 const char *driver_name_ret;
589 switch (level) {
590 case 1:
591 driver_name_ret = info[i].info1.driver_name;
592 break;
593 case 2:
594 driver_name_ret = info[i].info2.driver_name;
595 environment_ret = info[i].info2.architecture;
596 break;
597 case 3:
598 driver_name_ret = info[i].info3.driver_name;
599 environment_ret = info[i].info3.architecture;
600 break;
601 case 4:
602 driver_name_ret = info[i].info4.driver_name;
603 environment_ret = info[i].info4.architecture;
604 break;
605 case 5:
606 driver_name_ret = info[i].info5.driver_name;
607 environment_ret = info[i].info5.architecture;
608 break;
609 case 6:
610 driver_name_ret = info[i].info6.driver_name;
611 environment_ret = info[i].info6.architecture;
612 break;
613 case 7:
614 driver_name_ret = info[i].info7.driver_name;
615 break;
616 case 8:
617 driver_name_ret = info[i].info8.driver_name;
618 environment_ret = info[i].info8.architecture;
619 break;
620 default:
621 break;
623 if (environment_ret) {
624 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
626 if (strequal(driver_name, driver_name_ret)) {
627 if (info_p) {
628 *info_p = info[i];
630 return true;
634 return false;
637 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
638 void *private_data)
640 struct test_spoolss_context *ctx =
641 talloc_get_type_abort(private_data, struct test_spoolss_context);
642 struct dcerpc_pipe *p = ctx->spoolss_pipe;
643 struct dcerpc_binding_handle *b = p->binding_handle;
644 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
645 int i, j, a;
647 /* FIXME: gd, come back and fix "" as server, and handle
648 * priority of returned error codes in torture test and samba 3
649 * server */
650 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
651 const char *environments[2];
653 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
654 environments[1] = ctx->environment;
656 for (a=0;a<ARRAY_SIZE(environments);a++) {
658 for (i=0;i<ARRAY_SIZE(levels);i++) {
659 int level = levels[i];
660 uint32_t count;
661 union spoolss_DriverInfo *info;
663 torture_assert(tctx,
664 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
665 "failed to enumerate drivers");
667 ctx->driver_count[level] = count;
668 ctx->drivers[level] = info;
671 for (i=1;i<ARRAY_SIZE(levels);i++) {
672 int level = levels[i];
673 int old_level = levels[i-1];
675 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
676 "EnumPrinterDrivers invalid value");
679 for (i=0;i<ARRAY_SIZE(levels);i++) {
680 int level = levels[i];
682 for (j=0;j<ctx->driver_count[level - 1];j++) {
683 union spoolss_DriverInfo *cur = &ctx->drivers[level - 1][j];
684 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
686 switch (level) {
687 case 1:
688 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
689 break;
690 case 2:
691 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
692 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
693 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
694 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
695 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
696 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
697 break;
698 case 3:
699 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
704 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
705 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
706 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
707 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
708 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
709 break;
710 case 4:
711 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
716 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
717 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
718 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
719 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
720 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
721 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
722 break;
723 case 5:
724 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
725 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
726 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
727 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
728 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
729 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
730 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
731 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
732 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
733 break;
734 case 6:
735 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
740 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
741 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
742 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
745 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
746 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
747 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
748 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
749 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
750 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
751 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
752 break;
753 case 8:
754 /* level 8 is our reference, and it makes no sense to compare it to itself */
755 break;
761 return true;
764 static bool test_EnumMonitors(struct torture_context *tctx,
765 void *private_data)
767 struct test_spoolss_context *ctx =
768 talloc_get_type_abort(private_data, struct test_spoolss_context);
769 struct dcerpc_pipe *p = ctx->spoolss_pipe;
770 struct dcerpc_binding_handle *b = p->binding_handle;
771 NTSTATUS status;
772 struct spoolss_EnumMonitors r;
773 uint16_t levels[] = { 1, 2 };
774 int i, j;
776 for (i=0;i<ARRAY_SIZE(levels);i++) {
777 int level = levels[i];
778 DATA_BLOB blob;
779 uint32_t needed;
780 uint32_t count;
781 union spoolss_MonitorInfo *info;
783 r.in.servername = "";
784 r.in.level = level;
785 r.in.buffer = NULL;
786 r.in.offered = 0;
787 r.out.needed = &needed;
788 r.out.count = &count;
789 r.out.info = &info;
791 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
793 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
794 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
795 if (W_ERROR_IS_OK(r.out.result)) {
796 /* TODO: do some more checks here */
797 continue;
799 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
800 "EnumMonitors failed");
802 blob = data_blob_talloc_zero(ctx, needed);
803 r.in.buffer = &blob;
804 r.in.offered = needed;
806 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
807 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
809 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
811 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
813 ctx->monitor_count[level] = count;
814 ctx->monitors[level] = info;
817 for (i=1;i<ARRAY_SIZE(levels);i++) {
818 int level = levels[i];
819 int old_level = levels[i-1];
820 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
821 "EnumMonitors invalid value");
824 for (i=0;i<ARRAY_SIZE(levels);i++) {
825 int level = levels[i];
826 for (j=0;j<ctx->monitor_count[level];j++) {
827 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
828 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
829 switch (level) {
830 case 1:
831 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
832 break;
833 case 2:
834 /* level 2 is our reference, and it makes no sense to compare it to itself */
835 break;
840 return true;
843 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
844 struct dcerpc_binding_handle *b,
845 const char *environment,
846 uint32_t level,
847 uint32_t *count_p,
848 union spoolss_PrintProcessorInfo **info_p,
849 WERROR expected_result)
851 struct spoolss_EnumPrintProcessors r;
852 DATA_BLOB blob;
853 uint32_t needed;
854 uint32_t count;
855 union spoolss_PrintProcessorInfo *info;
857 r.in.servername = "";
858 r.in.environment = environment;
859 r.in.level = level;
860 r.in.buffer = NULL;
861 r.in.offered = 0;
862 r.out.needed = &needed;
863 r.out.count = &count;
864 r.out.info = &info;
866 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
867 r.in.environment, r.in.level);
869 torture_assert_ntstatus_ok(tctx,
870 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
871 "EnumPrintProcessors failed");
872 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
873 blob = data_blob_talloc_zero(tctx, needed);
874 r.in.buffer = &blob;
875 r.in.offered = needed;
876 torture_assert_ntstatus_ok(tctx,
877 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
878 "EnumPrintProcessors failed");
880 torture_assert_werr_equal(tctx, r.out.result, expected_result,
881 "EnumPrintProcessors failed");
883 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
885 if (count_p) {
886 *count_p = count;
888 if (info_p) {
889 *info_p = info;
892 return true;
895 static bool test_EnumPrintProcessors(struct torture_context *tctx,
896 void *private_data)
898 struct test_spoolss_context *ctx =
899 talloc_get_type_abort(private_data, struct test_spoolss_context);
901 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
902 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
903 int i;
904 struct dcerpc_pipe *p = ctx->spoolss_pipe;
905 struct dcerpc_binding_handle *b = p->binding_handle;
907 torture_assert(tctx,
908 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
909 "test_EnumPrintProcessors_level failed");
911 for (i=0;i<ARRAY_SIZE(levels);i++) {
912 union spoolss_PrintProcessorInfo *info;
913 uint32_t count;
914 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
916 torture_assert(tctx,
917 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
918 "test_EnumPrintProcessors_level failed");
921 return true;
924 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
925 struct dcerpc_binding_handle *b,
926 const char *print_processor_name,
927 uint32_t level,
928 uint32_t *count_p,
929 union spoolss_PrintProcDataTypesInfo **info_p,
930 WERROR expected_result)
932 struct spoolss_EnumPrintProcDataTypes r;
933 DATA_BLOB blob;
934 uint32_t needed;
935 uint32_t count;
936 union spoolss_PrintProcDataTypesInfo *info;
938 r.in.servername = "";
939 r.in.print_processor_name = print_processor_name;
940 r.in.level = level;
941 r.in.buffer = NULL;
942 r.in.offered = 0;
943 r.out.needed = &needed;
944 r.out.count = &count;
945 r.out.info = &info;
947 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
948 r.in.print_processor_name, r.in.level);
950 torture_assert_ntstatus_ok(tctx,
951 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
952 "EnumPrintProcDataTypes failed");
953 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
954 blob = data_blob_talloc_zero(tctx, needed);
955 r.in.buffer = &blob;
956 r.in.offered = needed;
957 torture_assert_ntstatus_ok(tctx,
958 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
959 "EnumPrintProcDataTypes failed");
961 torture_assert_werr_equal(tctx, r.out.result, expected_result,
962 "EnumPrintProcDataTypes failed");
964 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
966 if (count_p) {
967 *count_p = count;
969 if (info_p) {
970 *info_p = info;
973 return true;
976 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
977 void *private_data)
979 struct test_spoolss_context *ctx =
980 talloc_get_type_abort(private_data, struct test_spoolss_context);
982 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
983 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
984 int i;
985 struct dcerpc_pipe *p = ctx->spoolss_pipe;
986 struct dcerpc_binding_handle *b = p->binding_handle;
988 torture_assert(tctx,
989 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
990 "test_EnumPrintProcDataTypes_level failed");
992 torture_assert(tctx,
993 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
994 "test_EnumPrintProcDataTypes_level failed");
996 for (i=0;i<ARRAY_SIZE(levels);i++) {
997 int level = levels[i];
998 uint32_t count;
999 union spoolss_PrintProcDataTypesInfo *info;
1000 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1002 torture_assert(tctx,
1003 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1004 "test_EnumPrintProcDataTypes_level failed");
1008 union spoolss_PrintProcessorInfo *info;
1009 uint32_t count;
1011 torture_assert(tctx,
1012 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1013 "test_EnumPrintProcessors_level failed");
1015 for (i=0; i < count; i++) {
1016 torture_assert(tctx,
1017 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1018 "test_EnumPrintProcDataTypes_level failed");
1023 return true;
1026 static bool test_EnumPrinters(struct torture_context *tctx,
1027 void *private_data)
1029 struct test_spoolss_context *ctx =
1030 talloc_get_type_abort(private_data, struct test_spoolss_context);
1031 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1032 struct dcerpc_binding_handle *b = p->binding_handle;
1033 struct spoolss_EnumPrinters r;
1034 NTSTATUS status;
1035 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1036 int i, j;
1038 for (i=0;i<ARRAY_SIZE(levels);i++) {
1039 int level = levels[i];
1040 DATA_BLOB blob;
1041 uint32_t needed;
1042 uint32_t count;
1043 union spoolss_PrinterInfo *info;
1045 r.in.flags = PRINTER_ENUM_LOCAL;
1046 r.in.server = "";
1047 r.in.level = level;
1048 r.in.buffer = NULL;
1049 r.in.offered = 0;
1050 r.out.needed = &needed;
1051 r.out.count = &count;
1052 r.out.info = &info;
1054 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1056 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1057 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1058 if (W_ERROR_IS_OK(r.out.result)) {
1059 /* TODO: do some more checks here */
1060 continue;
1062 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1063 "EnumPrinters unexpected return code");
1065 blob = data_blob_talloc_zero(ctx, needed);
1066 r.in.buffer = &blob;
1067 r.in.offered = needed;
1069 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1070 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1072 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1074 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1076 ctx->printer_count[level] = count;
1077 ctx->printers[level] = info;
1080 for (i=1;i<ARRAY_SIZE(levels);i++) {
1081 int level = levels[i];
1082 int old_level = levels[i-1];
1083 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1084 "EnumPrinters invalid value");
1087 for (i=0;i<ARRAY_SIZE(levels);i++) {
1088 int level = levels[i];
1089 for (j=0;j<ctx->printer_count[level];j++) {
1090 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1091 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1092 switch (level) {
1093 case 0:
1094 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1095 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1097 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1099 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1112 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1113 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1116 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1117 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1118 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1119 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1120 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1121 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1122 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1123 break;
1124 case 1:
1125 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1126 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1127 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1128 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1129 break;
1130 case 2:
1131 /* level 2 is our reference, and it makes no sense to compare it to itself */
1132 break;
1133 case 4:
1134 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1135 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1136 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1137 break;
1138 case 5:
1139 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1140 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1141 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1142 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1143 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1144 break;
1149 /* TODO:
1150 * - verify that the port of a printer was in the list returned by EnumPorts
1153 return true;
1156 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1157 struct dcerpc_binding_handle *b,
1158 struct policy_handle *handle,
1159 const char *driver_name,
1160 const char *environment);
1162 bool test_GetPrinter_level(struct torture_context *tctx,
1163 struct dcerpc_binding_handle *b,
1164 struct policy_handle *handle,
1165 uint32_t level,
1166 union spoolss_PrinterInfo *info)
1168 struct spoolss_GetPrinter r;
1169 uint32_t needed;
1171 r.in.handle = handle;
1172 r.in.level = level;
1173 r.in.buffer = NULL;
1174 r.in.offered = 0;
1175 r.out.needed = &needed;
1177 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1179 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1180 "GetPrinter failed");
1182 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1183 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1184 r.in.buffer = &blob;
1185 r.in.offered = needed;
1187 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1188 "GetPrinter failed");
1191 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1193 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1195 if (info && r.out.info) {
1196 *info = *r.out.info;
1199 return true;
1203 static bool test_GetPrinter(struct torture_context *tctx,
1204 struct dcerpc_binding_handle *b,
1205 struct policy_handle *handle,
1206 const char *environment)
1208 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1209 int i;
1211 for (i=0;i<ARRAY_SIZE(levels);i++) {
1213 union spoolss_PrinterInfo info;
1215 ZERO_STRUCT(info);
1217 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1218 "failed to call GetPrinter");
1220 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1221 torture_assert(tctx,
1222 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1223 "failed to call test_GetPrinterDriver2");
1227 return true;
1230 static bool test_SetPrinter(struct torture_context *tctx,
1231 struct dcerpc_binding_handle *b,
1232 struct policy_handle *handle,
1233 struct spoolss_SetPrinterInfoCtr *info_ctr,
1234 struct spoolss_DevmodeContainer *devmode_ctr,
1235 struct sec_desc_buf *secdesc_ctr,
1236 enum spoolss_PrinterControl command)
1238 struct spoolss_SetPrinter r;
1240 r.in.handle = handle;
1241 r.in.info_ctr = info_ctr;
1242 r.in.devmode_ctr = devmode_ctr;
1243 r.in.secdesc_ctr = secdesc_ctr;
1244 r.in.command = command;
1246 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1248 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1249 "failed to call SetPrinter");
1250 torture_assert_werr_ok(tctx, r.out.result,
1251 "failed to call SetPrinter");
1253 return true;
1256 static bool test_SetPrinter_errors(struct torture_context *tctx,
1257 struct dcerpc_binding_handle *b,
1258 struct policy_handle *handle)
1260 struct spoolss_SetPrinter r;
1261 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1262 int i;
1264 struct spoolss_SetPrinterInfoCtr info_ctr;
1265 struct spoolss_DevmodeContainer devmode_ctr;
1266 struct sec_desc_buf secdesc_ctr;
1268 info_ctr.level = 0;
1269 info_ctr.info.info0 = NULL;
1271 ZERO_STRUCT(devmode_ctr);
1272 ZERO_STRUCT(secdesc_ctr);
1274 r.in.handle = handle;
1275 r.in.info_ctr = &info_ctr;
1276 r.in.devmode_ctr = &devmode_ctr;
1277 r.in.secdesc_ctr = &secdesc_ctr;
1278 r.in.command = 0;
1280 torture_comment(tctx, "Testing SetPrinter all zero\n");
1282 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1283 "failed to call SetPrinter");
1284 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1285 "failed to call SetPrinter");
1287 again:
1288 for (i=0; i < ARRAY_SIZE(levels); i++) {
1290 struct spoolss_SetPrinterInfo0 info0;
1291 struct spoolss_SetPrinterInfo1 info1;
1292 struct spoolss_SetPrinterInfo2 info2;
1293 struct spoolss_SetPrinterInfo3 info3;
1294 struct spoolss_SetPrinterInfo4 info4;
1295 struct spoolss_SetPrinterInfo5 info5;
1296 struct spoolss_SetPrinterInfo6 info6;
1297 struct spoolss_SetPrinterInfo7 info7;
1298 struct spoolss_SetPrinterInfo8 info8;
1299 struct spoolss_SetPrinterInfo9 info9;
1302 info_ctr.level = levels[i];
1303 switch (levels[i]) {
1304 case 0:
1305 ZERO_STRUCT(info0);
1306 info_ctr.info.info0 = &info0;
1307 break;
1308 case 1:
1309 ZERO_STRUCT(info1);
1310 info_ctr.info.info1 = &info1;
1311 break;
1312 case 2:
1313 ZERO_STRUCT(info2);
1314 info_ctr.info.info2 = &info2;
1315 break;
1316 case 3:
1317 ZERO_STRUCT(info3);
1318 info_ctr.info.info3 = &info3;
1319 break;
1320 case 4:
1321 ZERO_STRUCT(info4);
1322 info_ctr.info.info4 = &info4;
1323 break;
1324 case 5:
1325 ZERO_STRUCT(info5);
1326 info_ctr.info.info5 = &info5;
1327 break;
1328 case 6:
1329 ZERO_STRUCT(info6);
1330 info_ctr.info.info6 = &info6;
1331 break;
1332 case 7:
1333 ZERO_STRUCT(info7);
1334 info_ctr.info.info7 = &info7;
1335 break;
1336 case 8:
1337 ZERO_STRUCT(info8);
1338 info_ctr.info.info8 = &info8;
1339 break;
1340 case 9:
1341 ZERO_STRUCT(info9);
1342 info_ctr.info.info9 = &info9;
1343 break;
1346 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1347 info_ctr.level, r.in.command);
1349 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1350 "failed to call SetPrinter");
1352 switch (r.in.command) {
1353 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1354 /* is ignored for all levels other then 0 */
1355 if (info_ctr.level > 0) {
1356 /* ignored then */
1357 break;
1359 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1360 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1361 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1362 if (info_ctr.level > 0) {
1363 /* is invalid for all levels other then 0 */
1364 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1365 "unexpected error code returned");
1366 continue;
1367 } else {
1368 torture_assert_werr_ok(tctx, r.out.result,
1369 "failed to call SetPrinter with non 0 command");
1370 continue;
1372 break;
1374 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1375 /* FIXME: gd needs further investigation */
1376 default:
1377 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1378 "unexpected error code returned");
1379 continue;
1382 switch (info_ctr.level) {
1383 case 1:
1384 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1385 "unexpected error code returned");
1386 break;
1387 case 2:
1388 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1389 "unexpected error code returned");
1390 break;
1391 case 3:
1392 case 4:
1393 case 5:
1394 case 7:
1395 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1396 "unexpected error code returned");
1397 break;
1398 case 9:
1399 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1400 "unexpected error code returned");
1401 break;
1402 default:
1403 torture_assert_werr_ok(tctx, r.out.result,
1404 "failed to call SetPrinter");
1405 break;
1409 if (r.in.command < 5) {
1410 r.in.command++;
1411 goto again;
1414 return true;
1417 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1419 if ((r->level == 2) && (r->info.info2)) {
1420 r->info.info2->secdesc_ptr = NULL;
1421 r->info.info2->devmode_ptr = NULL;
1425 static bool test_PrinterInfo(struct torture_context *tctx,
1426 struct dcerpc_binding_handle *b,
1427 struct policy_handle *handle)
1429 NTSTATUS status;
1430 struct spoolss_SetPrinter s;
1431 struct spoolss_GetPrinter q;
1432 struct spoolss_GetPrinter q0;
1433 struct spoolss_SetPrinterInfoCtr info_ctr;
1434 union spoolss_PrinterInfo info;
1435 struct spoolss_DevmodeContainer devmode_ctr;
1436 struct sec_desc_buf secdesc_ctr;
1437 uint32_t needed;
1438 bool ret = true;
1439 int i;
1441 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1443 uint32_t status_list[] = {
1444 /* these do not stick
1445 PRINTER_STATUS_PAUSED,
1446 PRINTER_STATUS_ERROR,
1447 PRINTER_STATUS_PENDING_DELETION, */
1448 PRINTER_STATUS_PAPER_JAM,
1449 PRINTER_STATUS_PAPER_OUT,
1450 PRINTER_STATUS_MANUAL_FEED,
1451 PRINTER_STATUS_PAPER_PROBLEM,
1452 PRINTER_STATUS_OFFLINE,
1453 PRINTER_STATUS_IO_ACTIVE,
1454 PRINTER_STATUS_BUSY,
1455 PRINTER_STATUS_PRINTING,
1456 PRINTER_STATUS_OUTPUT_BIN_FULL,
1457 PRINTER_STATUS_NOT_AVAILABLE,
1458 PRINTER_STATUS_WAITING,
1459 PRINTER_STATUS_PROCESSING,
1460 PRINTER_STATUS_INITIALIZING,
1461 PRINTER_STATUS_WARMING_UP,
1462 PRINTER_STATUS_TONER_LOW,
1463 PRINTER_STATUS_NO_TONER,
1464 PRINTER_STATUS_PAGE_PUNT,
1465 PRINTER_STATUS_USER_INTERVENTION,
1466 PRINTER_STATUS_OUT_OF_MEMORY,
1467 PRINTER_STATUS_DOOR_OPEN,
1468 PRINTER_STATUS_SERVER_UNKNOWN,
1469 PRINTER_STATUS_POWER_SAVE,
1470 /* these do not stick
1471 0x02000000,
1472 0x04000000,
1473 0x08000000,
1474 0x10000000,
1475 0x20000000,
1476 0x40000000,
1477 0x80000000 */
1479 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1480 uint32_t attribute_list[] = {
1481 PRINTER_ATTRIBUTE_QUEUED,
1482 /* fails with WERR_INVALID_DATATYPE:
1483 PRINTER_ATTRIBUTE_DIRECT, */
1484 /* does not stick
1485 PRINTER_ATTRIBUTE_DEFAULT, */
1486 PRINTER_ATTRIBUTE_SHARED,
1487 /* does not stick
1488 PRINTER_ATTRIBUTE_NETWORK, */
1489 PRINTER_ATTRIBUTE_HIDDEN,
1490 PRINTER_ATTRIBUTE_LOCAL,
1491 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1492 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1493 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1494 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1495 /* does not stick
1496 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1497 /* fails with WERR_INVALID_DATATYPE:
1498 PRINTER_ATTRIBUTE_RAW_ONLY, */
1499 /* these do not stick
1500 PRINTER_ATTRIBUTE_PUBLISHED,
1501 PRINTER_ATTRIBUTE_FAX,
1502 PRINTER_ATTRIBUTE_TS,
1503 0x00010000,
1504 0x00020000,
1505 0x00040000,
1506 0x00080000,
1507 0x00100000,
1508 0x00200000,
1509 0x00400000,
1510 0x00800000,
1511 0x01000000,
1512 0x02000000,
1513 0x04000000,
1514 0x08000000,
1515 0x10000000,
1516 0x20000000,
1517 0x40000000,
1518 0x80000000 */
1521 ZERO_STRUCT(devmode_ctr);
1522 ZERO_STRUCT(secdesc_ctr);
1524 s.in.handle = handle;
1525 s.in.command = 0;
1526 s.in.info_ctr = &info_ctr;
1527 s.in.devmode_ctr = &devmode_ctr;
1528 s.in.secdesc_ctr = &secdesc_ctr;
1530 q.in.handle = handle;
1531 q.out.info = &info;
1532 q0 = q;
1534 #define TESTGETCALL(call, r) \
1535 r.in.buffer = NULL; \
1536 r.in.offered = 0;\
1537 r.out.needed = &needed; \
1538 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1539 if (!NT_STATUS_IS_OK(status)) { \
1540 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1541 r.in.level, nt_errstr(status), __location__); \
1542 ret = false; \
1543 break; \
1545 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1546 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1547 r.in.buffer = &blob; \
1548 r.in.offered = needed; \
1550 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1551 if (!NT_STATUS_IS_OK(status)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, nt_errstr(status), __location__); \
1554 ret = false; \
1555 break; \
1557 if (!W_ERROR_IS_OK(r.out.result)) { \
1558 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1559 r.in.level, win_errstr(r.out.result), __location__); \
1560 ret = false; \
1561 break; \
1565 #define TESTSETCALL_EXP(call, r, err) \
1566 clear_info2(&info_ctr);\
1567 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1568 if (!NT_STATUS_IS_OK(status)) { \
1569 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1570 r.in.info_ctr->level, nt_errstr(status), __location__); \
1571 ret = false; \
1572 break; \
1574 if (!W_ERROR_IS_OK(err)) { \
1575 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1576 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1577 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1578 ret = false; \
1580 break; \
1582 if (!W_ERROR_IS_OK(r.out.result)) { \
1583 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1584 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1585 ret = false; \
1586 break; \
1589 #define TESTSETCALL(call, r) \
1590 TESTSETCALL_EXP(call, r, WERR_OK)
1592 #define STRING_EQUAL(s1, s2, field) \
1593 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1594 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1595 #field, s2, __location__); \
1596 ret = false; \
1597 break; \
1600 #define MEM_EQUAL(s1, s2, length, field) \
1601 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1602 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1603 #field, (const char *)s2, __location__); \
1604 ret = false; \
1605 break; \
1608 #define INT_EQUAL(i1, i2, field) \
1609 if (i1 != i2) { \
1610 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1611 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1612 ret = false; \
1613 break; \
1616 #define SD_EQUAL(sd1, sd2, field) \
1617 if (!security_descriptor_equal(sd1, sd2)) { \
1618 torture_comment(tctx, "Failed to set %s (%s)\n", \
1619 #field, __location__); \
1620 ret = false; \
1621 break; \
1624 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1625 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626 q.in.level = lvl1; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.level = lvl1; \
1629 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630 info_ctr.info.info ## lvl1->field1 = value;\
1631 TESTSETCALL_EXP(SetPrinter, s, err) \
1632 info_ctr.info.info ## lvl1->field1 = ""; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl1->field1 = value; \
1635 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1636 q.in.level = lvl2; \
1637 TESTGETCALL(GetPrinter, q) \
1638 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1640 } while (0)
1642 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1643 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1644 } while (0);
1646 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1647 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1648 q.in.level = lvl1; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.level = lvl1; \
1651 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1652 info_ctr.info.info ## lvl1->field1 = value; \
1653 TESTSETCALL(SetPrinter, s) \
1654 info_ctr.info.info ## lvl1->field1 = 0; \
1655 TESTGETCALL(GetPrinter, q) \
1656 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1657 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1658 q.in.level = lvl2; \
1659 TESTGETCALL(GetPrinter, q) \
1660 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1661 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1662 } while (0)
1664 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1665 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1666 } while (0)
1668 q0.in.level = 0;
1669 do { TESTGETCALL(GetPrinter, q0) } while (0);
1671 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1672 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1674 /* level 0 printername does not stick */
1675 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1676 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1677 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1680 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1681 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1682 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1685 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1686 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1687 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1691 /* servername can be set but does not stick
1692 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1693 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1697 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1698 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1703 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1704 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1705 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1706 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1707 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1708 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1709 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1710 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1711 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1712 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1714 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1715 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1716 attribute_list[i],
1717 (attribute_list[i] | default_attribute)
1718 ); */
1719 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1720 attribute_list[i],
1721 (attribute_list[i] | default_attribute)
1723 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1724 attribute_list[i],
1725 (attribute_list[i] | default_attribute)
1727 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1728 attribute_list[i],
1729 (attribute_list[i] | default_attribute)
1731 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1732 attribute_list[i],
1733 (attribute_list[i] | default_attribute)
1734 ); */
1735 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1736 attribute_list[i],
1737 (attribute_list[i] | default_attribute)
1739 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1740 attribute_list[i],
1741 (attribute_list[i] | default_attribute)
1743 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1744 attribute_list[i],
1745 (attribute_list[i] | default_attribute)
1747 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1748 attribute_list[i],
1749 (attribute_list[i] | default_attribute)
1750 ); */
1751 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1752 attribute_list[i],
1753 (attribute_list[i] | default_attribute)
1755 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1756 attribute_list[i],
1757 (attribute_list[i] | default_attribute)
1759 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1760 attribute_list[i],
1761 (attribute_list[i] | default_attribute)
1765 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1766 /* level 2 sets do not stick
1767 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1770 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1775 /* priorities need to be between 0 and 99
1776 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1777 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1780 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1781 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1784 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1786 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1787 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1789 /* does not stick
1790 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1791 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1793 /* does not stick
1794 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1795 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1797 /* FIXME: gd also test devmode and secdesc behavior */
1800 /* verify composition of level 1 description field */
1801 const char *description;
1802 const char *tmp;
1804 q0.in.level = 1;
1805 do { TESTGETCALL(GetPrinter, q0) } while (0);
1807 description = talloc_strdup(tctx, q0.out.info->info1.description);
1809 q0.in.level = 2;
1810 do { TESTGETCALL(GetPrinter, q0) } while (0);
1812 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1813 q0.out.info->info2.printername,
1814 q0.out.info->info2.drivername,
1815 q0.out.info->info2.location);
1817 do { STRING_EQUAL(description, tmp, "description")} while (0);
1820 return ret;
1823 static bool test_security_descriptor_equal(struct torture_context *tctx,
1824 const struct security_descriptor *sd1,
1825 const struct security_descriptor *sd2)
1827 if (sd1 == sd2) {
1828 return true;
1831 if (!sd1 || !sd2) {
1832 torture_comment(tctx, "%s\n", __location__);
1833 return false;
1836 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1837 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1839 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1840 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1842 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1843 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1846 return false;
1848 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1849 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1850 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1851 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1852 return false;
1855 return true;
1858 static bool test_sd_set_level(struct torture_context *tctx,
1859 struct dcerpc_binding_handle *b,
1860 struct policy_handle *handle,
1861 uint32_t level,
1862 struct security_descriptor *sd)
1864 struct spoolss_SetPrinterInfoCtr info_ctr;
1865 struct spoolss_DevmodeContainer devmode_ctr;
1866 struct sec_desc_buf secdesc_ctr;
1867 union spoolss_SetPrinterInfo sinfo;
1869 ZERO_STRUCT(devmode_ctr);
1870 ZERO_STRUCT(secdesc_ctr);
1872 switch (level) {
1873 case 2: {
1874 union spoolss_PrinterInfo info;
1875 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1876 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1878 info_ctr.level = 2;
1879 info_ctr.info = sinfo;
1881 break;
1883 case 3: {
1884 struct spoolss_SetPrinterInfo3 info3;
1886 info3.sec_desc_ptr = NULL;
1888 info_ctr.level = 3;
1889 info_ctr.info.info3 = &info3;
1891 break;
1893 default:
1894 return false;
1897 secdesc_ctr.sd = sd;
1899 torture_assert(tctx,
1900 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1902 return true;
1905 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1906 struct dcerpc_binding_handle *b,
1907 struct policy_handle *handle)
1909 union spoolss_PrinterInfo info;
1910 struct security_descriptor *sd1, *sd2;
1911 int i;
1913 /* just compare level 2 and level 3 */
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1917 sd1 = info.info2.secdesc;
1919 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1921 sd2 = info.info3.secdesc;
1923 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1924 "SD level 2 != SD level 3");
1927 /* query level 2, set level 2, query level 2 */
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd1 = info.info2.secdesc;
1933 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1935 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1937 sd2 = info.info2.secdesc;
1938 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1939 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1940 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1943 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1944 "SD level 2 != SD level 2 after SD has been set via level 2");
1947 /* query level 2, set level 3, query level 2 */
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd1 = info.info2.secdesc;
1953 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1955 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1957 sd2 = info.info2.secdesc;
1959 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1960 "SD level 2 != SD level 2 after SD has been set via level 3");
1962 /* set modified sd level 3, query level 2 */
1964 for (i=0; i < 93; i++) {
1965 struct security_ace a;
1966 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1967 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1968 a.flags = 0;
1969 a.size = 0; /* autogenerated */
1970 a.access_mask = 0;
1971 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1972 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1975 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1977 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1978 sd2 = info.info2.secdesc;
1980 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1981 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1982 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1985 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1986 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1989 return true;
1993 * wrapper call that saves original sd, runs tests, and restores sd
1996 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1997 struct dcerpc_binding_handle *b,
1998 struct policy_handle *handle)
2000 union spoolss_PrinterInfo info;
2001 struct security_descriptor *sd;
2002 bool ret = true;
2004 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2006 /* save original sd */
2008 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2009 "failed to get initial security descriptor");
2011 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2013 /* run tests */
2015 ret = test_PrinterInfo_SDs(tctx, b, handle);
2017 /* restore original sd */
2019 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2020 "failed to restore initial security descriptor");
2022 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2023 ret ? "succeeded" : "failed");
2026 return ret;
2029 static bool test_devmode_set_level(struct torture_context *tctx,
2030 struct dcerpc_binding_handle *b,
2031 struct policy_handle *handle,
2032 uint32_t level,
2033 struct spoolss_DeviceMode *devmode)
2035 struct spoolss_SetPrinterInfoCtr info_ctr;
2036 struct spoolss_DevmodeContainer devmode_ctr;
2037 struct sec_desc_buf secdesc_ctr;
2038 union spoolss_SetPrinterInfo sinfo;
2040 ZERO_STRUCT(devmode_ctr);
2041 ZERO_STRUCT(secdesc_ctr);
2043 switch (level) {
2044 case 2: {
2045 union spoolss_PrinterInfo info;
2046 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2047 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2049 info_ctr.level = 2;
2050 info_ctr.info = sinfo;
2052 break;
2054 case 8: {
2055 struct spoolss_SetPrinterInfo8 info8;
2057 info8.devmode_ptr = NULL;
2059 info_ctr.level = 8;
2060 info_ctr.info.info8 = &info8;
2062 break;
2064 default:
2065 return false;
2068 devmode_ctr.devmode = devmode;
2070 torture_assert(tctx,
2071 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2073 return true;
2077 static bool test_devicemode_equal(struct torture_context *tctx,
2078 const struct spoolss_DeviceMode *d1,
2079 const struct spoolss_DeviceMode *d2)
2081 if (d1 == d2) {
2082 return true;
2085 if (!d1 || !d2) {
2086 torture_comment(tctx, "%s\n", __location__);
2087 return false;
2089 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2090 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2091 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2092 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2093 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2094 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2095 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2096 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2097 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2098 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2099 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2100 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2101 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2102 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2103 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2104 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2105 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2106 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2107 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2108 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2109 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2110 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2111 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2112 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2113 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2114 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2115 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2116 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2117 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2118 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2119 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2121 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2122 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2123 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2125 return true;
2128 static bool test_devicemode_full(struct torture_context *tctx,
2129 struct dcerpc_binding_handle *b,
2130 struct policy_handle *handle)
2132 struct spoolss_SetPrinter s;
2133 struct spoolss_GetPrinter q;
2134 struct spoolss_GetPrinter q0;
2135 struct spoolss_SetPrinterInfoCtr info_ctr;
2136 struct spoolss_SetPrinterInfo8 info8;
2137 union spoolss_PrinterInfo info;
2138 struct spoolss_DevmodeContainer devmode_ctr;
2139 struct sec_desc_buf secdesc_ctr;
2140 uint32_t needed;
2141 bool ret = true;
2142 NTSTATUS status;
2144 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2145 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2146 q.in.level = lvl1; \
2147 TESTGETCALL(GetPrinter, q) \
2148 info_ctr.level = lvl1; \
2149 if (lvl1 == 2) {\
2150 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2151 } else if (lvl1 == 8) {\
2152 info_ctr.info.info ## lvl1 = &info8; \
2154 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2155 devmode_ctr.devmode->field1 = value; \
2156 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2157 if (W_ERROR_IS_OK(expected_result)) { \
2158 TESTGETCALL(GetPrinter, q) \
2159 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2160 q.in.level = lvl2; \
2161 TESTGETCALL(GetPrinter, q) \
2162 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2164 } while (0)
2166 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2167 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2168 } while (0)
2170 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2171 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2172 } while (0)
2174 ZERO_STRUCT(devmode_ctr);
2175 ZERO_STRUCT(secdesc_ctr);
2176 ZERO_STRUCT(info8);
2178 s.in.handle = handle;
2179 s.in.command = 0;
2180 s.in.info_ctr = &info_ctr;
2181 s.in.devmode_ctr = &devmode_ctr;
2182 s.in.secdesc_ctr = &secdesc_ctr;
2184 q.in.handle = handle;
2185 q.out.info = &info;
2186 q0 = q;
2188 #if 0
2189 const char *devicename;/* [charset(UTF16)] */
2190 enum spoolss_DeviceModeSpecVersion specversion;
2191 uint16_t driverversion;
2192 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2193 uint32_t fields;
2194 #endif
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2199 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2201 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2202 torture_assert(tctx,
2203 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2204 "failed to set devmode");
2206 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2207 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2209 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2210 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2211 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2212 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2213 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2214 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2215 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2216 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2217 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2218 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2219 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2220 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2221 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2222 #if 0
2223 const char *formname;/* [charset(UTF16)] */
2224 #endif
2225 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2226 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2227 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2228 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2229 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2230 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2231 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2232 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2233 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2234 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2237 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2238 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2240 return ret;
2243 static bool call_OpenPrinterEx(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 const char *name,
2246 struct spoolss_DeviceMode *devmode,
2247 struct policy_handle *handle);
2249 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2250 struct dcerpc_pipe *p,
2251 struct policy_handle *handle,
2252 const char *name)
2254 union spoolss_PrinterInfo info;
2255 struct spoolss_DeviceMode *devmode;
2256 struct spoolss_DeviceMode *devmode2;
2257 struct policy_handle handle_devmode;
2258 struct dcerpc_binding_handle *b = p->binding_handle;
2260 /* simply compare level8 and level2 devmode */
2262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264 devmode = info.info8.devmode;
2266 if (devmode && devmode->size == 0) {
2267 torture_fail(tctx,
2268 "devmode of zero size!");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2273 devmode2 = info.info2.devmode;
2275 if (devmode2 && devmode2->size == 0) {
2276 torture_fail(tctx,
2277 "devmode of zero size!");
2280 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2281 "DM level 8 != DM level 2");
2284 /* set devicemode level 8 and see if it persists */
2286 devmode->copies = 93;
2287 devmode->formname = talloc_strdup(tctx, "Legal");
2289 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2291 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2293 devmode2 = info.info8.devmode;
2295 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2296 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2298 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2300 devmode2 = info.info2.devmode;
2302 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2303 "modified DM level 8 != DM level 2");
2306 /* set devicemode level 2 and see if it persists */
2308 devmode->copies = 39;
2309 devmode->formname = talloc_strdup(tctx, "Executive");
2311 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2313 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2315 devmode2 = info.info8.devmode;
2317 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2318 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2320 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2322 devmode2 = info.info2.devmode;
2324 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2325 "modified DM level 8 != DM level 2");
2328 /* check every single bit in public part of devicemode */
2330 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2331 "failed to set every single devicemode component");
2334 /* change formname upon open and see if it persists in getprinter calls */
2336 devmode->formname = talloc_strdup(tctx, "A4");
2337 devmode->copies = 42;
2339 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2340 "failed to open printer handle");
2342 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2344 devmode2 = info.info8.devmode;
2346 if (strequal(devmode->devicename, devmode2->devicename)) {
2347 torture_warning(tctx, "devicenames are the same\n");
2348 } else {
2349 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2350 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2353 if (strequal(devmode->formname, devmode2->formname)) {
2354 torture_warning(tctx, "formname are the same\n");
2355 } else {
2356 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2357 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2360 if (devmode->copies == devmode2->copies) {
2361 torture_warning(tctx, "copies are the same\n");
2362 } else {
2363 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2364 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2367 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2369 devmode2 = info.info2.devmode;
2371 if (strequal(devmode->devicename, devmode2->devicename)) {
2372 torture_warning(tctx, "devicenames are the same\n");
2373 } else {
2374 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2375 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2378 if (strequal(devmode->formname, devmode2->formname)) {
2379 torture_warning(tctx, "formname is the same\n");
2380 } else {
2381 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2382 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2385 if (devmode->copies == devmode2->copies) {
2386 torture_warning(tctx, "copies are the same\n");
2387 } else {
2388 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2389 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2392 test_ClosePrinter(tctx, b, &handle_devmode);
2394 return true;
2398 * wrapper call that saves original devmode, runs tests, and restores devmode
2401 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2402 struct dcerpc_pipe *p,
2403 struct policy_handle *handle,
2404 const char *name,
2405 struct spoolss_DeviceMode *addprinter_devmode)
2407 union spoolss_PrinterInfo info;
2408 struct spoolss_DeviceMode *devmode;
2409 bool ret = true;
2410 struct dcerpc_binding_handle *b = p->binding_handle;
2412 torture_comment(tctx, "Testing Printer Devicemodes\n");
2414 /* save original devmode */
2416 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2417 "failed to get initial global devicemode");
2419 devmode = info.info8.devmode;
2421 if (devmode && devmode->size == 0) {
2422 torture_fail(tctx,
2423 "devmode of zero size!");
2426 if (addprinter_devmode) {
2427 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2428 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2432 /* run tests */
2434 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2436 /* restore original devmode */
2438 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2439 "failed to restore initial global device mode");
2441 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2442 ret ? "succeeded" : "failed");
2445 return ret;
2448 bool test_ClosePrinter(struct torture_context *tctx,
2449 struct dcerpc_binding_handle *b,
2450 struct policy_handle *handle)
2452 NTSTATUS status;
2453 struct spoolss_ClosePrinter r;
2455 r.in.handle = handle;
2456 r.out.handle = handle;
2458 torture_comment(tctx, "Testing ClosePrinter\n");
2460 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2464 return true;
2467 static bool test_GetForm_args(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 const char *form_name,
2471 uint32_t level,
2472 union spoolss_FormInfo *info_p)
2474 NTSTATUS status;
2475 struct spoolss_GetForm r;
2476 uint32_t needed;
2478 r.in.handle = handle;
2479 r.in.form_name = form_name;
2480 r.in.level = level;
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2485 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2487 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2488 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2492 r.in.buffer = &blob;
2493 r.in.offered = needed;
2494 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 torture_assert(tctx, r.out.info, "No form info returned");
2502 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2504 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2506 if (info_p) {
2507 *info_p = *r.out.info;
2510 return true;
2513 static bool test_GetForm(struct torture_context *tctx,
2514 struct dcerpc_binding_handle *b,
2515 struct policy_handle *handle,
2516 const char *form_name,
2517 uint32_t level)
2519 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2522 static bool test_EnumForms(struct torture_context *tctx,
2523 struct dcerpc_binding_handle *b,
2524 struct policy_handle *handle,
2525 bool print_server,
2526 uint32_t level,
2527 uint32_t *count_p,
2528 union spoolss_FormInfo **info_p)
2530 struct spoolss_EnumForms r;
2531 uint32_t needed;
2532 uint32_t count;
2533 union spoolss_FormInfo *info;
2535 r.in.handle = handle;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2540 r.out.count = &count;
2541 r.out.info = &info;
2543 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2545 torture_assert_ntstatus_ok(tctx,
2546 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2547 "EnumForms failed");
2549 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2550 torture_skip(tctx, "EnumForms level 2 not supported");
2553 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2554 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2557 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2558 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2559 r.in.buffer = &blob;
2560 r.in.offered = needed;
2562 torture_assert_ntstatus_ok(tctx,
2563 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2564 "EnumForms failed");
2566 torture_assert(tctx, info, "No forms returned");
2569 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2571 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2573 if (info_p) {
2574 *info_p = info;
2576 if (count_p) {
2577 *count_p = count;
2580 return true;
2583 static bool test_EnumForms_all(struct torture_context *tctx,
2584 struct dcerpc_binding_handle *b,
2585 struct policy_handle *handle,
2586 bool print_server)
2588 uint32_t levels[] = { 1, 2 };
2589 int i, j;
2591 for (i=0; i<ARRAY_SIZE(levels); i++) {
2593 uint32_t count = 0;
2594 union spoolss_FormInfo *info = NULL;
2596 torture_assert(tctx,
2597 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2598 "failed to enum forms");
2600 for (j = 0; j < count; j++) {
2601 if (!print_server) {
2602 torture_assert(tctx,
2603 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2604 "failed to get form");
2609 return true;
2612 static bool test_EnumForms_find_one(struct torture_context *tctx,
2613 struct dcerpc_binding_handle *b,
2614 struct policy_handle *handle,
2615 bool print_server,
2616 const char *form_name)
2618 union spoolss_FormInfo *info;
2619 uint32_t count;
2620 bool found = false;
2621 int i;
2623 torture_assert(tctx,
2624 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2625 "failed to enumerate forms");
2627 for (i=0; i<count; i++) {
2628 if (strequal(form_name, info[i].info1.form_name)) {
2629 found = true;
2630 break;
2634 return found;
2637 static bool test_DeleteForm(struct torture_context *tctx,
2638 struct dcerpc_binding_handle *b,
2639 struct policy_handle *handle,
2640 const char *form_name,
2641 WERROR expected_result)
2643 struct spoolss_DeleteForm r;
2645 r.in.handle = handle;
2646 r.in.form_name = form_name;
2648 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2650 torture_assert_ntstatus_ok(tctx,
2651 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2652 "DeleteForm failed");
2653 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2654 "DeleteForm gave unexpected result");
2655 if (W_ERROR_IS_OK(r.out.result)) {
2656 torture_assert_ntstatus_ok(tctx,
2657 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2658 "2nd DeleteForm failed");
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2660 "2nd DeleteForm failed");
2663 return true;
2666 static bool test_AddForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 uint32_t level,
2670 union spoolss_AddFormInfo *info,
2671 WERROR expected_result)
2673 struct spoolss_AddForm r;
2674 struct spoolss_AddFormInfoCtr info_ctr;
2676 info_ctr.level = level;
2677 info_ctr.info = *info;
2679 if (level != 1) {
2680 torture_skip(tctx, "only level 1 supported");
2683 r.in.handle = handle;
2684 r.in.info_ctr = &info_ctr;
2686 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2687 r.in.info_ctr->info.info1->form_name, level,
2688 r.in.info_ctr->info.info1->flags);
2690 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2691 "AddForm failed");
2692 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2693 "AddForm gave unexpected result");
2695 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2696 "2nd AddForm failed");
2697 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2698 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2699 "2nd AddForm gave unexpected result");
2700 } else {
2701 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2702 "2nd AddForm gave unexpected result");
2705 return true;
2708 static bool test_SetForm(struct torture_context *tctx,
2709 struct dcerpc_binding_handle *b,
2710 struct policy_handle *handle,
2711 const char *form_name,
2712 uint32_t level,
2713 union spoolss_AddFormInfo *info)
2715 struct spoolss_SetForm r;
2716 struct spoolss_AddFormInfoCtr info_ctr;
2718 info_ctr.level = level;
2719 info_ctr.info = *info;
2721 r.in.handle = handle;
2722 r.in.form_name = form_name;
2723 r.in.info_ctr = &info_ctr;
2725 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2726 form_name, level);
2728 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2729 "SetForm failed");
2731 torture_assert_werr_ok(tctx, r.out.result,
2732 "SetForm failed");
2734 return true;
2737 static bool test_GetForm_winreg(struct torture_context *tctx,
2738 struct dcerpc_binding_handle *b,
2739 struct policy_handle *handle,
2740 const char *key_name,
2741 const char *form_name,
2742 enum winreg_Type *w_type,
2743 uint32_t *w_size,
2744 uint32_t *w_length,
2745 uint8_t **w_data);
2747 static bool test_Forms_args(struct torture_context *tctx,
2748 struct dcerpc_binding_handle *b,
2749 struct policy_handle *handle,
2750 bool print_server,
2751 const char *printer_name,
2752 struct dcerpc_binding_handle *winreg_handle,
2753 struct policy_handle *hive_handle,
2754 const char *form_name,
2755 struct spoolss_AddFormInfo1 *info1,
2756 WERROR expected_add_result,
2757 WERROR expected_delete_result)
2759 union spoolss_FormInfo info;
2760 union spoolss_AddFormInfo add_info;
2762 enum winreg_Type w_type;
2763 uint32_t w_size;
2764 uint32_t w_length;
2765 uint8_t *w_data;
2767 add_info.info1 = info1;
2769 torture_assert(tctx,
2770 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2771 "failed to add form");
2773 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2775 struct spoolss_FormInfo1 i1;
2777 torture_assert(tctx,
2778 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2779 "failed to get form via winreg");
2781 i1.size.width = IVAL(w_data, 0);
2782 i1.size.height = IVAL(w_data, 4);
2783 i1.area.left = IVAL(w_data, 8);
2784 i1.area.top = IVAL(w_data, 12);
2785 i1.area.right = IVAL(w_data, 16);
2786 i1.area.bottom = IVAL(w_data, 20);
2787 /* skip index here */
2788 i1.flags = IVAL(w_data, 28);
2790 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2791 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2792 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2793 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2794 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2795 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2796 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2797 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2798 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2799 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2802 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2803 torture_assert(tctx,
2804 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2805 "failed to get added form");
2807 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2808 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2809 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2810 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2811 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2812 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2813 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2815 if (winreg_handle && hive_handle) {
2817 struct spoolss_FormInfo1 i1;
2819 i1.size.width = IVAL(w_data, 0);
2820 i1.size.height = IVAL(w_data, 4);
2821 i1.area.left = IVAL(w_data, 8);
2822 i1.area.top = IVAL(w_data, 12);
2823 i1.area.right = IVAL(w_data, 16);
2824 i1.area.bottom = IVAL(w_data, 20);
2825 /* skip index here */
2826 i1.flags = IVAL(w_data, 28);
2828 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2829 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2830 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2831 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2832 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2833 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2834 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2837 add_info.info1->size.width = 1234;
2839 torture_assert(tctx,
2840 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2841 "failed to set form");
2842 torture_assert(tctx,
2843 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2844 "failed to get setted form");
2846 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2849 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2850 torture_assert(tctx,
2851 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2852 "Newly added form not found in enum call");
2855 torture_assert(tctx,
2856 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2857 "failed to delete form");
2859 return true;
2862 static bool test_Forms(struct torture_context *tctx,
2863 struct dcerpc_binding_handle *b,
2864 struct policy_handle *handle,
2865 bool print_server,
2866 const char *printer_name,
2867 struct dcerpc_binding_handle *winreg_handle,
2868 struct policy_handle *hive_handle)
2870 const struct spoolss_FormSize size = {
2871 .width = 50,
2872 .height = 25
2874 const struct spoolss_FormArea area = {
2875 .left = 5,
2876 .top = 10,
2877 .right = 45,
2878 .bottom = 15
2880 int i;
2882 struct {
2883 struct spoolss_AddFormInfo1 info1;
2884 WERROR expected_add_result;
2885 WERROR expected_delete_result;
2886 } forms[] = {
2888 .info1 = {
2889 .flags = SPOOLSS_FORM_USER,
2890 .form_name = "testform_user",
2891 .size = size,
2892 .area = area,
2894 .expected_add_result = WERR_OK,
2895 .expected_delete_result = WERR_OK
2898 weird, we can add a builtin form but we can never remove it
2899 again - gd
2902 .info1 = {
2903 .flags = SPOOLSS_FORM_BUILTIN,
2904 .form_name = "testform_builtin",
2905 .size = size,
2906 .area = area,
2908 .expected_add_result = WERR_OK,
2909 .expected_delete_result = WERR_INVALID_PARAM,
2913 .info1 = {
2914 .flags = SPOOLSS_FORM_PRINTER,
2915 .form_name = "testform_printer",
2916 .size = size,
2917 .area = area,
2919 .expected_add_result = WERR_OK,
2920 .expected_delete_result = WERR_OK
2923 .info1 = {
2924 .flags = SPOOLSS_FORM_USER,
2925 .form_name = "Letter",
2926 .size = size,
2927 .area = area,
2929 .expected_add_result = WERR_FILE_EXISTS,
2930 .expected_delete_result = WERR_INVALID_PARAM
2933 .info1 = {
2934 .flags = SPOOLSS_FORM_BUILTIN,
2935 .form_name = "Letter",
2936 .size = size,
2937 .area = area,
2939 .expected_add_result = WERR_FILE_EXISTS,
2940 .expected_delete_result = WERR_INVALID_PARAM
2943 .info1 = {
2944 .flags = SPOOLSS_FORM_PRINTER,
2945 .form_name = "Letter",
2946 .size = size,
2947 .area = area,
2949 .expected_add_result = WERR_FILE_EXISTS,
2950 .expected_delete_result = WERR_INVALID_PARAM
2953 .info1 = {
2954 .flags = 12345,
2955 .form_name = "invalid_flags",
2956 .size = size,
2957 .area = area,
2959 .expected_add_result = WERR_INVALID_PARAM,
2960 .expected_delete_result = WERR_INVALID_FORM_NAME
2965 for (i=0; i < ARRAY_SIZE(forms); i++) {
2966 torture_assert(tctx,
2967 test_Forms_args(tctx, b, handle, print_server, printer_name,
2968 winreg_handle, hive_handle,
2969 forms[i].info1.form_name,
2970 &forms[i].info1,
2971 forms[i].expected_add_result,
2972 forms[i].expected_delete_result),
2973 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2976 return true;
2979 static bool test_EnumPorts_old(struct torture_context *tctx,
2980 void *private_data)
2982 struct test_spoolss_context *ctx =
2983 talloc_get_type_abort(private_data, struct test_spoolss_context);
2985 NTSTATUS status;
2986 struct spoolss_EnumPorts r;
2987 uint32_t needed;
2988 uint32_t count;
2989 union spoolss_PortInfo *info;
2990 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2991 struct dcerpc_binding_handle *b = p->binding_handle;
2993 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2994 dcerpc_server_name(p));
2995 r.in.level = 2;
2996 r.in.buffer = NULL;
2997 r.in.offered = 0;
2998 r.out.needed = &needed;
2999 r.out.count = &count;
3000 r.out.info = &info;
3002 torture_comment(tctx, "Testing EnumPorts\n");
3004 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3006 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3008 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3009 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3010 r.in.buffer = &blob;
3011 r.in.offered = needed;
3013 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3014 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3015 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3017 torture_assert(tctx, info, "No ports returned");
3020 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3022 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3024 return true;
3027 static bool test_AddPort(struct torture_context *tctx,
3028 void *private_data)
3030 struct test_spoolss_context *ctx =
3031 talloc_get_type_abort(private_data, struct test_spoolss_context);
3033 NTSTATUS status;
3034 struct spoolss_AddPort r;
3035 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3036 struct dcerpc_binding_handle *b = p->binding_handle;
3038 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3039 dcerpc_server_name(p));
3040 r.in.unknown = 0;
3041 r.in.monitor_name = "foo";
3043 torture_comment(tctx, "Testing AddPort\n");
3045 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3047 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3049 /* win2k3 returns WERR_NOT_SUPPORTED */
3051 #if 0
3053 if (!W_ERROR_IS_OK(r.out.result)) {
3054 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3055 return false;
3058 #endif
3060 return true;
3063 static bool test_GetJob_args(struct torture_context *tctx,
3064 struct dcerpc_binding_handle *b,
3065 struct policy_handle *handle,
3066 uint32_t job_id,
3067 uint32_t level,
3068 union spoolss_JobInfo *info_p)
3070 NTSTATUS status;
3071 struct spoolss_GetJob r;
3072 union spoolss_JobInfo info;
3073 uint32_t needed;
3075 r.in.handle = handle;
3076 r.in.job_id = job_id;
3077 r.in.level = level;
3078 r.in.buffer = NULL;
3079 r.in.offered = 0;
3080 r.out.needed = &needed;
3081 r.out.info = &info;
3083 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3085 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3086 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3087 if (level == 0) {
3088 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3091 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3092 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3093 r.in.buffer = &blob;
3094 r.in.offered = needed;
3096 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3097 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3100 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3101 torture_assert(tctx, r.out.info, "No job info returned");
3103 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3105 if (info_p) {
3106 *info_p = *r.out.info;
3109 return true;
3112 static bool test_GetJob(struct torture_context *tctx,
3113 struct dcerpc_binding_handle *b,
3114 struct policy_handle *handle,
3115 uint32_t job_id)
3117 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3118 uint32_t i;
3120 for (i=0; i < ARRAY_SIZE(levels); i++) {
3121 torture_assert(tctx,
3122 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3123 "GetJob failed");
3126 return true;
3129 static bool test_SetJob(struct torture_context *tctx,
3130 struct dcerpc_binding_handle *b,
3131 struct policy_handle *handle,
3132 uint32_t job_id,
3133 struct spoolss_JobInfoContainer *ctr,
3134 enum spoolss_JobControl command)
3136 NTSTATUS status;
3137 struct spoolss_SetJob r;
3139 r.in.handle = handle;
3140 r.in.job_id = job_id;
3141 r.in.ctr = ctr;
3142 r.in.command = command;
3144 switch (command) {
3145 case SPOOLSS_JOB_CONTROL_PAUSE:
3146 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3147 break;
3148 case SPOOLSS_JOB_CONTROL_RESUME:
3149 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3150 break;
3151 case SPOOLSS_JOB_CONTROL_CANCEL:
3152 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3153 break;
3154 case SPOOLSS_JOB_CONTROL_RESTART:
3155 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3156 break;
3157 case SPOOLSS_JOB_CONTROL_DELETE:
3158 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3159 break;
3160 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3161 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3162 break;
3163 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3164 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3165 break;
3166 case SPOOLSS_JOB_CONTROL_RETAIN:
3167 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3168 break;
3169 case SPOOLSS_JOB_CONTROL_RELEASE:
3170 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3171 break;
3172 default:
3173 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3174 break;
3177 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3178 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3179 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3181 return true;
3184 static bool test_AddJob(struct torture_context *tctx,
3185 struct dcerpc_binding_handle *b,
3186 struct policy_handle *handle)
3188 NTSTATUS status;
3189 struct spoolss_AddJob r;
3190 uint32_t needed;
3192 r.in.level = 0;
3193 r.in.handle = handle;
3194 r.in.offered = 0;
3195 r.out.needed = &needed;
3196 r.in.buffer = r.out.buffer = NULL;
3198 torture_comment(tctx, "Testing AddJob\n");
3200 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3201 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3202 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3204 r.in.level = 1;
3206 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3207 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3208 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3210 return true;
3214 static bool test_EnumJobs_args(struct torture_context *tctx,
3215 struct dcerpc_binding_handle *b,
3216 struct policy_handle *handle,
3217 uint32_t level,
3218 uint32_t *count_p,
3219 union spoolss_JobInfo **info_p)
3221 NTSTATUS status;
3222 struct spoolss_EnumJobs r;
3223 uint32_t needed;
3224 uint32_t count;
3225 union spoolss_JobInfo *info;
3227 r.in.handle = handle;
3228 r.in.firstjob = 0;
3229 r.in.numjobs = 0xffffffff;
3230 r.in.level = level;
3231 r.in.buffer = NULL;
3232 r.in.offered = 0;
3233 r.out.needed = &needed;
3234 r.out.count = &count;
3235 r.out.info = &info;
3237 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3239 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3241 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3243 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3244 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3245 r.in.buffer = &blob;
3246 r.in.offered = needed;
3248 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3250 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3251 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3252 torture_assert(tctx, info, "No jobs returned");
3254 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3256 } else {
3257 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3260 if (count_p) {
3261 *count_p = count;
3263 if (info_p) {
3264 *info_p = info;
3267 return true;
3270 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3271 struct dcerpc_binding_handle *b,
3272 struct policy_handle *handle,
3273 uint32_t job_id)
3275 struct spoolss_RpcEnumJobNamedProperties r;
3276 uint32_t pcProperties = 0;
3277 struct RPC_PrintNamedProperty *ppProperties = NULL;
3279 r.in.hPrinter = handle;
3280 r.in.JobId = job_id;
3281 r.out.pcProperties = &pcProperties;
3282 r.out.ppProperties = &ppProperties;
3284 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3286 torture_assert_ntstatus_ok(tctx,
3287 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3288 "spoolss_RpcEnumJobNamedProperties failed");
3289 torture_assert_werr_ok(tctx, r.out.result,
3290 "spoolss_RpcEnumJobNamedProperties failed");
3292 return true;
3295 static bool test_JobPropertySet(struct torture_context *tctx,
3296 struct dcerpc_binding_handle *b,
3297 struct policy_handle *handle,
3298 uint32_t job_id,
3299 struct RPC_PrintNamedProperty *property)
3301 struct spoolss_RpcSetJobNamedProperty r;
3303 r.in.hPrinter = handle;
3304 r.in.JobId = job_id;
3305 r.in.pProperty = property;
3307 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3308 job_id, property->propertyName,
3309 property->propertyValue.ePropertyType);
3311 torture_assert_ntstatus_ok(tctx,
3312 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3313 "spoolss_RpcSetJobNamedProperty failed");
3314 torture_assert_werr_ok(tctx, r.out.result,
3315 "spoolss_RpcSetJobNamedProperty failed");
3317 return true;
3320 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3321 struct dcerpc_binding_handle *b,
3322 struct policy_handle *handle,
3323 uint32_t job_id,
3324 const char *property_name,
3325 struct RPC_PrintPropertyValue *value)
3327 struct spoolss_RpcGetJobNamedPropertyValue r;
3329 r.in.hPrinter = handle;
3330 r.in.JobId = job_id;
3331 r.in.pszName = property_name;
3332 r.out.pValue = value;
3334 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3335 job_id, property_name);
3337 torture_assert_ntstatus_ok(tctx,
3338 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3339 "spoolss_RpcGetJobNamedPropertyValue failed");
3340 torture_assert_werr_ok(tctx, r.out.result,
3341 "spoolss_RpcGetJobNamedPropertyValue failed");
3343 return true;
3346 static bool test_JobPropertyDelete(struct torture_context *tctx,
3347 struct dcerpc_binding_handle *b,
3348 struct policy_handle *handle,
3349 uint32_t job_id,
3350 const char *property_name)
3352 struct spoolss_RpcDeleteJobNamedProperty r;
3354 r.in.hPrinter = handle;
3355 r.in.JobId = job_id;
3356 r.in.pszName = property_name;
3358 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3359 job_id, property_name);
3361 torture_assert_ntstatus_ok(tctx,
3362 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3363 "spoolss_RpcDeleteJobNamedProperty failed");
3364 torture_assert_werr_ok(tctx, r.out.result,
3365 "spoolss_RpcDeleteJobNamedProperty failed");
3367 return true;
3371 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3372 struct dcerpc_binding_handle *b,
3373 struct policy_handle *handle,
3374 const char *document_name,
3375 uint32_t *job_id)
3377 NTSTATUS status;
3378 struct spoolss_StartDocPrinter s;
3379 struct spoolss_DocumentInfoCtr info_ctr;
3380 struct spoolss_DocumentInfo1 info1;
3381 struct spoolss_StartPagePrinter sp;
3382 struct spoolss_WritePrinter w;
3383 struct spoolss_EndPagePrinter ep;
3384 struct spoolss_EndDocPrinter e;
3385 int i;
3386 uint32_t num_written;
3388 torture_comment(tctx, "Testing StartDocPrinter\n");
3390 s.in.handle = handle;
3391 s.in.info_ctr = &info_ctr;
3392 s.out.job_id = job_id;
3394 info1.document_name = document_name;
3395 info1.output_file = NULL;
3396 info1.datatype = "RAW";
3398 info_ctr.level = 1;
3399 info_ctr.info.info1 = &info1;
3401 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3402 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3403 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3405 for (i=1; i < 4; i++) {
3406 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3408 sp.in.handle = handle;
3410 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3411 torture_assert_ntstatus_ok(tctx, status,
3412 "dcerpc_spoolss_StartPagePrinter failed");
3413 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3415 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3417 w.in.handle = handle;
3418 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3419 w.out.num_written = &num_written;
3421 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3422 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3423 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3425 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3427 ep.in.handle = handle;
3429 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3430 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3431 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3434 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3436 e.in.handle = handle;
3438 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3439 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3440 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3442 return true;
3445 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3446 struct dcerpc_binding_handle *b,
3447 struct policy_handle *handle,
3448 uint32_t num_jobs,
3449 uint32_t *job_ids)
3451 uint32_t count;
3452 union spoolss_JobInfo *info = NULL;
3453 int i;
3455 torture_assert(tctx,
3456 test_AddJob(tctx, b, handle),
3457 "AddJob failed");
3459 torture_assert(tctx,
3460 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3461 "EnumJobs level 1 failed");
3463 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3465 for (i=0; i < num_jobs; i++) {
3466 union spoolss_JobInfo ginfo;
3467 const char *document_name;
3468 const char *new_document_name = "any_other_docname";
3469 struct spoolss_JobInfoContainer ctr;
3470 struct spoolss_SetJobInfo1 info1;
3472 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3474 torture_assert(tctx,
3475 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3476 "failed to call test_GetJob");
3478 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3480 document_name = ginfo.info1.document_name;
3482 info1.job_id = ginfo.info1.job_id;
3483 info1.printer_name = ginfo.info1.printer_name;
3484 info1.server_name = ginfo.info1.server_name;
3485 info1.user_name = ginfo.info1.user_name;
3486 info1.document_name = new_document_name;
3487 info1.data_type = ginfo.info1.data_type;
3488 info1.text_status = ginfo.info1.text_status;
3489 info1.status = ginfo.info1.status;
3490 info1.priority = ginfo.info1.priority;
3491 info1.position = ginfo.info1.position;
3492 info1.total_pages = ginfo.info1.total_pages;
3493 info1.pages_printed = ginfo.info1.pages_printed;
3494 info1.submitted = ginfo.info1.submitted;
3496 ctr.level = 1;
3497 ctr.info.info1 = &info1;
3499 torture_assert(tctx,
3500 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3501 "failed to call test_SetJob level 1");
3503 torture_assert(tctx,
3504 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3505 "failed to call test_GetJob");
3507 if (strequal(ginfo.info1.document_name, document_name)) {
3508 torture_warning(tctx,
3509 "document_name did *NOT* change from '%s' to '%s'\n",
3510 document_name, new_document_name);
3514 for (i=0; i < num_jobs; i++) {
3515 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3516 torture_warning(tctx, "failed to pause printjob\n");
3518 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3519 torture_warning(tctx, "failed to resume printjob\n");
3523 return true;
3526 static bool test_DoPrintTest(struct torture_context *tctx,
3527 struct dcerpc_binding_handle *b,
3528 struct policy_handle *handle)
3530 bool ret = true;
3531 uint32_t num_jobs = 8;
3532 uint32_t *job_ids;
3533 int i;
3535 torture_comment(tctx, "Testing real print operations\n");
3537 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3539 for (i=0; i < num_jobs; i++) {
3540 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3543 for (i=0; i < num_jobs; i++) {
3544 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3547 if (ret == true) {
3548 torture_comment(tctx, "real print operations test succeeded\n\n");
3551 return ret;
3554 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3555 struct dcerpc_binding_handle *b,
3556 struct policy_handle *handle)
3558 bool ret = true;
3559 uint32_t num_jobs = 8;
3560 uint32_t *job_ids;
3561 int i;
3562 torture_comment(tctx, "Testing real print operations (extended)\n");
3564 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3566 for (i=0; i < num_jobs; i++) {
3567 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3570 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3572 for (i=0; i < num_jobs; i++) {
3573 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3576 if (ret == true) {
3577 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3580 return ret;
3583 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3584 struct RPC_PrintPropertyValue *got,
3585 struct RPC_PrintNamedProperty *exp)
3587 torture_assert_int_equal(tctx,
3588 got->ePropertyType,
3589 exp->propertyValue.ePropertyType,
3590 "ePropertyType");
3592 switch (exp->propertyValue.ePropertyType) {
3593 case kRpcPropertyTypeString:
3594 torture_assert_str_equal(tctx,
3595 got->value.propertyString,
3596 exp->propertyValue.value.propertyString,
3597 "propertyString");
3598 break;
3599 case kRpcPropertyTypeInt32:
3600 torture_assert_int_equal(tctx,
3601 got->value.propertyInt32,
3602 exp->propertyValue.value.propertyInt32,
3603 "propertyInt32");
3604 break;
3605 case kRpcPropertyTypeInt64:
3606 torture_assert_u64_equal(tctx,
3607 got->value.propertyInt64,
3608 exp->propertyValue.value.propertyInt64,
3609 "propertyInt64");
3610 break;
3611 case kRpcPropertyTypeByte:
3612 torture_assert_int_equal(tctx,
3613 got->value.propertyByte,
3614 exp->propertyValue.value.propertyByte,
3615 "propertyByte");
3616 break;
3617 case kRpcPropertyTypeBuffer:
3618 torture_assert_int_equal(tctx,
3619 got->value.propertyBlob.cbBuf,
3620 exp->propertyValue.value.propertyBlob.cbBuf,
3621 "propertyBlob.cbBuf");
3622 torture_assert_mem_equal(tctx,
3623 got->value.propertyBlob.pBuf,
3624 exp->propertyValue.value.propertyBlob.pBuf,
3625 exp->propertyValue.value.propertyBlob.cbBuf,
3626 "propertyBlob.pBuf");
3628 break;
3632 return true;
3635 static bool test_JobPrintProperties(struct torture_context *tctx,
3636 struct dcerpc_binding_handle *b,
3637 struct policy_handle *handle,
3638 uint32_t job_id)
3640 struct RPC_PrintNamedProperty in;
3641 struct RPC_PrintPropertyValue out;
3642 int i;
3643 DATA_BLOB blob = data_blob_string_const("blob");
3644 struct {
3645 const char *property_name;
3646 enum RPC_EPrintPropertyType type;
3647 union RPC_PrintPropertyValueUnion value;
3648 WERROR expected_result;
3649 } tests[] = {
3651 .property_name = "torture_property_string",
3652 .type = kRpcPropertyTypeString,
3653 .value.propertyString = "torture_property_value_string",
3655 .property_name = "torture_property_int32",
3656 .type = kRpcPropertyTypeInt32,
3657 .value.propertyInt32 = 42,
3659 .property_name = "torture_property_int64",
3660 .type = kRpcPropertyTypeInt64,
3661 .value.propertyInt64 = 0xaffe,
3663 .property_name = "torture_property_byte",
3664 .type = kRpcPropertyTypeByte,
3665 .value.propertyByte = 0xab,
3667 .property_name = "torture_property_buffer",
3668 .type = kRpcPropertyTypeBuffer,
3669 .value.propertyBlob.cbBuf = blob.length,
3670 .value.propertyBlob.pBuf = blob.data,
3674 torture_assert(tctx,
3675 test_JobPropertiesEnum(tctx, b, handle, job_id),
3676 "failed to enum properties");
3678 for (i=0; i <ARRAY_SIZE(tests); i++) {
3680 in.propertyName = tests[i].property_name;
3681 in.propertyValue.ePropertyType = tests[i].type;
3682 in.propertyValue.value = tests[i].value;
3684 torture_assert(tctx,
3685 test_JobPropertySet(tctx, b, handle, job_id, &in),
3686 "failed to set property");
3688 torture_assert(tctx,
3689 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3690 "failed to get property");
3692 torture_assert(tctx,
3693 test_JobPrintProperties_equal(tctx, &out, &in),
3694 "property unequal");
3696 torture_assert(tctx,
3697 test_JobPropertiesEnum(tctx, b, handle, job_id),
3698 "failed to enum properties");
3700 torture_assert(tctx,
3701 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3702 "failed to delete job property");
3705 torture_assert(tctx,
3706 test_JobPropertiesEnum(tctx, b, handle, job_id),
3707 "failed to enum properties");
3709 return true;
3712 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3713 struct dcerpc_binding_handle *b,
3714 struct policy_handle *handle)
3716 uint32_t num_jobs = 8;
3717 uint32_t *job_ids;
3718 int i;
3719 torture_comment(tctx, "Testing real print operations (properties)\n");
3721 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3723 for (i=0; i < num_jobs; i++) {
3724 torture_assert(tctx,
3725 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3726 "failed to create print job");
3729 for (i=0; i < num_jobs; i++) {
3730 torture_assert(tctx,
3731 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3732 "failed to test job properties");
3736 for (i=0; i < num_jobs; i++) {
3737 torture_assert(tctx,
3738 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3739 "failed to delete printjob");
3742 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3744 return true;
3747 static bool test_PausePrinter(struct torture_context *tctx,
3748 struct dcerpc_binding_handle *b,
3749 struct policy_handle *handle)
3751 NTSTATUS status;
3752 struct spoolss_SetPrinter r;
3753 struct spoolss_SetPrinterInfoCtr info_ctr;
3754 struct spoolss_DevmodeContainer devmode_ctr;
3755 struct sec_desc_buf secdesc_ctr;
3757 info_ctr.level = 0;
3758 info_ctr.info.info0 = NULL;
3760 ZERO_STRUCT(devmode_ctr);
3761 ZERO_STRUCT(secdesc_ctr);
3763 r.in.handle = handle;
3764 r.in.info_ctr = &info_ctr;
3765 r.in.devmode_ctr = &devmode_ctr;
3766 r.in.secdesc_ctr = &secdesc_ctr;
3767 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3769 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3771 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3773 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3775 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3777 return true;
3780 static bool test_ResumePrinter(struct torture_context *tctx,
3781 struct dcerpc_binding_handle *b,
3782 struct policy_handle *handle)
3784 NTSTATUS status;
3785 struct spoolss_SetPrinter r;
3786 struct spoolss_SetPrinterInfoCtr info_ctr;
3787 struct spoolss_DevmodeContainer devmode_ctr;
3788 struct sec_desc_buf secdesc_ctr;
3790 info_ctr.level = 0;
3791 info_ctr.info.info0 = NULL;
3793 ZERO_STRUCT(devmode_ctr);
3794 ZERO_STRUCT(secdesc_ctr);
3796 r.in.handle = handle;
3797 r.in.info_ctr = &info_ctr;
3798 r.in.devmode_ctr = &devmode_ctr;
3799 r.in.secdesc_ctr = &secdesc_ctr;
3800 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3802 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3804 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3806 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3808 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3810 return true;
3813 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3814 struct dcerpc_binding_handle *b,
3815 struct policy_handle *handle,
3816 const char *value_name,
3817 enum winreg_Type *expected_type,
3818 enum winreg_Type *type_p,
3819 uint8_t **data_p,
3820 uint32_t *needed_p)
3822 NTSTATUS status;
3823 struct spoolss_GetPrinterData r;
3824 uint32_t needed;
3825 enum winreg_Type type;
3826 union spoolss_PrinterData data;
3828 r.in.handle = handle;
3829 r.in.value_name = value_name;
3830 r.in.offered = 0;
3831 r.out.needed = &needed;
3832 r.out.type = &type;
3833 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3835 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3837 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3838 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3840 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3841 if (expected_type) {
3842 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3844 r.in.offered = needed;
3845 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3846 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3847 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3850 torture_assert_werr_ok(tctx, r.out.result,
3851 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3853 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3855 if (type_p) {
3856 *type_p = type;
3859 if (data_p) {
3860 *data_p = r.out.data;
3863 if (needed_p) {
3864 *needed_p = needed;
3867 return true;
3870 static bool test_GetPrinterData(struct torture_context *tctx,
3871 struct dcerpc_binding_handle *b,
3872 struct policy_handle *handle,
3873 const char *value_name,
3874 enum winreg_Type *type_p,
3875 uint8_t **data_p,
3876 uint32_t *needed_p)
3878 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3879 NULL, type_p, data_p, needed_p);
3882 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3883 struct dcerpc_pipe *p,
3884 struct policy_handle *handle,
3885 const char *key_name,
3886 const char *value_name,
3887 enum winreg_Type *expected_type,
3888 enum winreg_Type *type_p,
3889 uint8_t **data_p,
3890 uint32_t *needed_p)
3892 NTSTATUS status;
3893 struct spoolss_GetPrinterDataEx r;
3894 enum winreg_Type type;
3895 uint32_t needed;
3896 union spoolss_PrinterData data;
3897 struct dcerpc_binding_handle *b = p->binding_handle;
3899 r.in.handle = handle;
3900 r.in.key_name = key_name;
3901 r.in.value_name = value_name;
3902 r.in.offered = 0;
3903 r.out.type = &type;
3904 r.out.needed = &needed;
3905 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3907 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3908 r.in.key_name, r.in.value_name);
3910 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3913 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3915 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3918 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3919 if (expected_type) {
3920 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3922 r.in.offered = needed;
3923 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3924 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3925 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3928 torture_assert_werr_ok(tctx, r.out.result,
3929 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3931 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3933 if (type_p) {
3934 *type_p = type;
3937 if (data_p) {
3938 *data_p = r.out.data;
3941 if (needed_p) {
3942 *needed_p = needed;
3945 return true;
3948 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3949 struct dcerpc_pipe *p,
3950 struct policy_handle *handle,
3951 const char *key_name,
3952 const char *value_name,
3953 enum winreg_Type *type_p,
3954 uint8_t **data_p,
3955 uint32_t *needed_p)
3957 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3958 NULL, type_p, data_p, needed_p);
3961 static bool test_get_environment(struct torture_context *tctx,
3962 struct dcerpc_binding_handle *b,
3963 struct policy_handle *handle,
3964 const char **architecture)
3966 DATA_BLOB blob;
3967 enum winreg_Type type;
3968 uint8_t *data;
3969 uint32_t needed;
3971 torture_assert(tctx,
3972 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3973 "failed to get Architecture");
3975 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3977 blob = data_blob_const(data, needed);
3978 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3980 return true;
3983 static bool test_GetPrinterData_list(struct torture_context *tctx,
3984 void *private_data)
3986 struct test_spoolss_context *ctx =
3987 talloc_get_type_abort(private_data, struct test_spoolss_context);
3988 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3989 struct dcerpc_binding_handle *b = p->binding_handle;
3990 const char *list[] = {
3991 "W3SvcInstalled",
3992 "BeepEnabled",
3993 "EventLog",
3994 /* "NetPopup", not on w2k8 */
3995 /* "NetPopupToComputer", not on w2k8 */
3996 "MajorVersion",
3997 "MinorVersion",
3998 "DefaultSpoolDirectory",
3999 "Architecture",
4000 "DsPresent",
4001 "OSVersion",
4002 /* "OSVersionEx", not on s3 */
4003 "DNSMachineName"
4005 int i;
4007 for (i=0; i < ARRAY_SIZE(list); i++) {
4008 enum winreg_Type type, type_ex;
4009 uint8_t *data, *data_ex;
4010 uint32_t needed, needed_ex;
4012 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4013 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4014 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4015 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4016 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4017 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4018 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4021 return true;
4024 static bool test_EnumPrinterData(struct torture_context *tctx,
4025 struct dcerpc_pipe *p,
4026 struct policy_handle *handle,
4027 uint32_t enum_index,
4028 uint32_t value_offered,
4029 uint32_t data_offered,
4030 enum winreg_Type *type_p,
4031 uint32_t *value_needed_p,
4032 uint32_t *data_needed_p,
4033 const char **value_name_p,
4034 uint8_t **data_p,
4035 WERROR *result_p)
4037 struct spoolss_EnumPrinterData r;
4038 uint32_t data_needed;
4039 uint32_t value_needed;
4040 enum winreg_Type type;
4041 struct dcerpc_binding_handle *b = p->binding_handle;
4043 r.in.handle = handle;
4044 r.in.enum_index = enum_index;
4045 r.in.value_offered = value_offered;
4046 r.in.data_offered = data_offered;
4047 r.out.data_needed = &data_needed;
4048 r.out.value_needed = &value_needed;
4049 r.out.type = &type;
4050 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4051 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4053 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4055 torture_assert_ntstatus_ok(tctx,
4056 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4057 "EnumPrinterData failed");
4059 if (type_p) {
4060 *type_p = type;
4062 if (value_needed_p) {
4063 *value_needed_p = value_needed;
4065 if (data_needed_p) {
4066 *data_needed_p = data_needed;
4068 if (value_name_p) {
4069 *value_name_p = r.out.value_name;
4071 if (data_p) {
4072 *data_p = r.out.data;
4074 if (result_p) {
4075 *result_p = r.out.result;
4078 return true;
4082 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4083 struct dcerpc_pipe *p,
4084 struct policy_handle *handle)
4086 uint32_t enum_index = 0;
4087 enum winreg_Type type;
4088 uint32_t value_needed;
4089 uint32_t data_needed;
4090 uint8_t *data;
4091 const char *value_name;
4092 WERROR result;
4094 torture_comment(tctx, "Testing EnumPrinterData\n");
4096 do {
4097 torture_assert(tctx,
4098 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4099 &type, &value_needed, &data_needed,
4100 &value_name, &data, &result),
4101 "EnumPrinterData failed");
4103 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4104 break;
4107 torture_assert(tctx,
4108 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4109 &type, &value_needed, &data_needed,
4110 &value_name, &data, &result),
4111 "EnumPrinterData failed");
4113 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4114 break;
4117 enum_index++;
4119 } while (W_ERROR_IS_OK(result));
4121 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4123 return true;
4126 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4127 struct dcerpc_binding_handle *b,
4128 struct policy_handle *handle,
4129 const char *key_name,
4130 uint32_t *count_p,
4131 struct spoolss_PrinterEnumValues **info_p)
4133 struct spoolss_EnumPrinterDataEx r;
4134 struct spoolss_PrinterEnumValues *info;
4135 uint32_t needed;
4136 uint32_t count;
4138 r.in.handle = handle;
4139 r.in.key_name = key_name;
4140 r.in.offered = 0;
4141 r.out.needed = &needed;
4142 r.out.count = &count;
4143 r.out.info = &info;
4145 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4147 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4148 "EnumPrinterDataEx failed");
4149 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4150 r.in.offered = needed;
4151 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4152 "EnumPrinterDataEx failed");
4155 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4157 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4159 if (count_p) {
4160 *count_p = count;
4162 if (info_p) {
4163 *info_p = info;
4166 return true;
4169 static bool test_SetPrinterData(struct torture_context *tctx,
4170 struct dcerpc_binding_handle *b,
4171 struct policy_handle *handle,
4172 const char *value_name,
4173 enum winreg_Type type,
4174 uint8_t *data,
4175 uint32_t offered);
4176 static bool test_DeletePrinterData(struct torture_context *tctx,
4177 struct dcerpc_binding_handle *b,
4178 struct policy_handle *handle,
4179 const char *value_name);
4181 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4182 struct dcerpc_pipe *p,
4183 struct policy_handle *handle)
4185 uint32_t count;
4186 struct spoolss_PrinterEnumValues *info;
4187 int i;
4188 uint32_t value_needed, data_needed;
4189 uint32_t value_offered, data_offered;
4190 WERROR result;
4191 struct dcerpc_binding_handle *b = p->binding_handle;
4193 enum winreg_Type type;
4194 DATA_BLOB blob;
4196 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4198 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4199 type = REG_SZ;
4201 torture_assert(tctx,
4202 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4203 "SetPrinterData failed");
4205 blob = data_blob_string_const("torture_data2");
4207 torture_assert(tctx,
4208 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4209 "SetPrinterData failed");
4211 blob = data_blob_talloc(tctx, NULL, 4);
4212 SIVAL(blob.data, 0, 0x11223344);
4214 torture_assert(tctx,
4215 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4216 "SetPrinterData failed");
4218 torture_assert(tctx,
4219 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4220 "failed to call EnumPrinterDataEx");
4222 /* get the max sizes for value and data */
4224 torture_assert(tctx,
4225 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4226 NULL, &value_needed, &data_needed,
4227 NULL, NULL, &result),
4228 "EnumPrinterData failed");
4229 torture_assert_werr_ok(tctx, result, "unexpected result");
4231 /* check if the reply from the EnumPrinterData really matches max values */
4233 for (i=0; i < count; i++) {
4234 if (info[i].value_name_len > value_needed) {
4235 torture_fail(tctx,
4236 talloc_asprintf(tctx,
4237 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4238 info[i].value_name_len, value_needed));
4240 if (info[i].data_length > data_needed) {
4241 torture_fail(tctx,
4242 talloc_asprintf(tctx,
4243 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4244 info[i].data_length, data_needed));
4248 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4249 * sort or not sort the replies by value name, we should be able to do
4250 * the following entry comparison */
4252 data_offered = data_needed;
4253 value_offered = value_needed;
4255 for (i=0; i < count; i++) {
4257 const char *value_name;
4258 uint8_t *data;
4260 torture_assert(tctx,
4261 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4262 &type, &value_needed, &data_needed,
4263 &value_name, &data, &result),
4264 "EnumPrinterData failed");
4266 if (i -1 == count) {
4267 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4268 "unexpected result");
4269 break;
4270 } else {
4271 torture_assert_werr_ok(tctx, result, "unexpected result");
4274 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4275 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4276 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4277 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4278 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4281 torture_assert(tctx,
4282 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4283 "DeletePrinterData failed");
4284 torture_assert(tctx,
4285 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4286 "DeletePrinterData failed");
4287 torture_assert(tctx,
4288 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4289 "DeletePrinterData failed");
4291 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4293 return true;
4296 static bool test_DeletePrinterData(struct torture_context *tctx,
4297 struct dcerpc_binding_handle *b,
4298 struct policy_handle *handle,
4299 const char *value_name)
4301 NTSTATUS status;
4302 struct spoolss_DeletePrinterData r;
4304 r.in.handle = handle;
4305 r.in.value_name = value_name;
4307 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4308 r.in.value_name);
4310 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4312 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4313 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4315 return true;
4318 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4319 struct dcerpc_binding_handle *b,
4320 struct policy_handle *handle,
4321 const char *key_name,
4322 const char *value_name)
4324 struct spoolss_DeletePrinterDataEx r;
4326 r.in.handle = handle;
4327 r.in.key_name = key_name;
4328 r.in.value_name = value_name;
4330 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4331 r.in.key_name, r.in.value_name);
4333 torture_assert_ntstatus_ok(tctx,
4334 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4335 "DeletePrinterDataEx failed");
4336 torture_assert_werr_ok(tctx, r.out.result,
4337 "DeletePrinterDataEx failed");
4339 return true;
4342 static bool test_DeletePrinterKey(struct torture_context *tctx,
4343 struct dcerpc_binding_handle *b,
4344 struct policy_handle *handle,
4345 const char *key_name)
4347 struct spoolss_DeletePrinterKey r;
4349 r.in.handle = handle;
4350 r.in.key_name = key_name;
4352 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4354 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4355 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4356 return true;
4359 torture_assert_ntstatus_ok(tctx,
4360 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4361 "DeletePrinterKey failed");
4362 torture_assert_werr_ok(tctx, r.out.result,
4363 "DeletePrinterKey failed");
4365 return true;
4368 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4369 struct dcerpc_binding_handle *b,
4370 struct policy_handle *handle)
4372 struct winreg_OpenHKLM r;
4374 r.in.system_name = NULL;
4375 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4376 r.out.handle = handle;
4378 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4380 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4381 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4383 return true;
4386 static void init_winreg_String(struct winreg_String *name, const char *s)
4388 name->name = s;
4389 if (s) {
4390 name->name_len = 2 * (strlen_m(s) + 1);
4391 name->name_size = name->name_len;
4392 } else {
4393 name->name_len = 0;
4394 name->name_size = 0;
4398 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4399 struct dcerpc_binding_handle *b,
4400 struct policy_handle *hive_handle,
4401 const char *keyname,
4402 uint32_t options,
4403 struct policy_handle *key_handle)
4405 struct winreg_OpenKey r;
4407 r.in.parent_handle = hive_handle;
4408 init_winreg_String(&r.in.keyname, keyname);
4409 r.in.options = options;
4410 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4411 r.out.handle = key_handle;
4413 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4415 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4416 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4418 return true;
4421 static bool test_winreg_OpenKey(struct torture_context *tctx,
4422 struct dcerpc_binding_handle *b,
4423 struct policy_handle *hive_handle,
4424 const char *keyname,
4425 struct policy_handle *key_handle)
4427 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4428 REG_OPTION_NON_VOLATILE, key_handle);
4431 static bool test_winreg_CloseKey(struct torture_context *tctx,
4432 struct dcerpc_binding_handle *b,
4433 struct policy_handle *handle)
4435 struct winreg_CloseKey r;
4437 r.in.handle = handle;
4438 r.out.handle = handle;
4440 torture_comment(tctx, "Testing winreg_CloseKey\n");
4442 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4443 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4445 return true;
4448 bool test_winreg_QueryValue(struct torture_context *tctx,
4449 struct dcerpc_binding_handle *b,
4450 struct policy_handle *handle,
4451 const char *value_name,
4452 enum winreg_Type *type_p,
4453 uint32_t *data_size_p,
4454 uint32_t *data_length_p,
4455 uint8_t **data_p)
4457 struct winreg_QueryValue r;
4458 enum winreg_Type type = REG_NONE;
4459 uint32_t data_size = 0;
4460 uint32_t data_length = 0;
4461 struct winreg_String valuename;
4462 uint8_t *data = NULL;
4464 init_winreg_String(&valuename, value_name);
4466 data = talloc_zero_array(tctx, uint8_t, 0);
4468 r.in.handle = handle;
4469 r.in.value_name = &valuename;
4470 r.in.type = &type;
4471 r.in.data_size = &data_size;
4472 r.in.data_length = &data_length;
4473 r.in.data = data;
4474 r.out.type = &type;
4475 r.out.data = data;
4476 r.out.data_size = &data_size;
4477 r.out.data_length = &data_length;
4479 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4481 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4482 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4483 *r.in.data_size = *r.out.data_size;
4484 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4485 r.in.data = data;
4486 r.out.data = data;
4487 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4489 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4491 if (type_p) {
4492 *type_p = *r.out.type;
4494 if (data_size_p) {
4495 *data_size_p = *r.out.data_size;
4497 if (data_length_p) {
4498 *data_length_p = *r.out.data_length;
4500 if (data_p) {
4501 *data_p = r.out.data;
4504 return true;
4507 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4508 struct dcerpc_binding_handle *b,
4509 struct policy_handle *handle,
4510 const char *printer_name,
4511 const char *key_name,
4512 const char *value_name,
4513 enum winreg_Type *w_type,
4514 uint32_t *w_size,
4515 uint32_t *w_length,
4516 uint8_t **w_data)
4518 const char *printer_key;
4519 struct policy_handle key_handle;
4521 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4522 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4524 torture_assert(tctx,
4525 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4527 torture_assert(tctx,
4528 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4530 torture_assert(tctx,
4531 test_winreg_CloseKey(tctx, b, &key_handle), "");
4533 return true;
4536 static bool test_GetForm_winreg(struct torture_context *tctx,
4537 struct dcerpc_binding_handle *b,
4538 struct policy_handle *handle,
4539 const char *key_name,
4540 const char *form_name,
4541 enum winreg_Type *w_type,
4542 uint32_t *w_size,
4543 uint32_t *w_length,
4544 uint8_t **w_data)
4546 struct policy_handle key_handle;
4548 torture_assert(tctx,
4549 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4551 torture_assert(tctx,
4552 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4554 torture_assert(tctx,
4555 test_winreg_CloseKey(tctx, b, &key_handle), "");
4557 return true;
4560 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4561 struct dcerpc_binding_handle *b,
4562 struct policy_handle *handle,
4563 const char *symlink_keyname,
4564 const char *symlink_destination)
4566 /* check if the first key is a symlink to the second key */
4568 enum winreg_Type w_type;
4569 uint32_t w_size;
4570 uint32_t w_length;
4571 uint8_t *w_data;
4572 struct policy_handle key_handle;
4573 DATA_BLOB blob;
4574 const char *str;
4576 if (torture_setting_bool(tctx, "samba3", false)) {
4577 torture_skip(tctx, "skip winreg symlink test against samba");
4580 torture_assert(tctx,
4581 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4582 "failed to open key link");
4584 torture_assert(tctx,
4585 test_winreg_QueryValue(tctx, b, &key_handle,
4586 "SymbolicLinkValue",
4587 &w_type, &w_size, &w_length, &w_data),
4588 "failed to query for 'SymbolicLinkValue' attribute");
4590 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4592 blob = data_blob(w_data, w_size);
4593 str = reg_val_data_string(tctx, REG_SZ, blob);
4595 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4597 torture_assert(tctx,
4598 test_winreg_CloseKey(tctx, b, &key_handle),
4599 "failed to close key link");
4601 return true;
4604 static const char *strip_unc(const char *unc)
4606 char *name;
4608 if (!unc) {
4609 return NULL;
4612 if (unc[0] == '\\' && unc[1] == '\\') {
4613 unc +=2;
4616 name = strchr(unc, '\\');
4617 if (name) {
4618 return name+1;
4621 return unc;
4624 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4625 struct dcerpc_binding_handle *b,
4626 struct policy_handle *handle,
4627 const char *printer_name,
4628 struct dcerpc_binding_handle *winreg_handle,
4629 struct policy_handle *hive_handle)
4631 union spoolss_PrinterInfo info;
4632 const char *keys[] = {
4633 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4634 TOP_LEVEL_PRINT_PRINTERS_KEY
4636 int i;
4637 const char *printername, *sharename;
4639 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4641 torture_assert(tctx,
4642 test_GetPrinter_level(tctx, b, handle, 2, &info),
4643 "failed to get printer info level 2");
4645 printername = strip_unc(info.info2.printername);
4646 sharename = strip_unc(info.info2.sharename);
4648 #define test_sz(wname, iname) \
4649 do {\
4650 DATA_BLOB blob;\
4651 const char *str;\
4652 enum winreg_Type w_type;\
4653 uint32_t w_size;\
4654 uint32_t w_length;\
4655 uint8_t *w_data;\
4656 torture_assert(tctx,\
4657 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4658 &w_type, &w_size, &w_length, &w_data),\
4659 "failed to query winreg");\
4660 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4661 blob = data_blob(w_data, w_size);\
4662 str = reg_val_data_string(tctx, REG_SZ, blob);\
4663 if (w_size == 2 && iname == NULL) {\
4664 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4665 } else {\
4666 torture_assert_str_equal(tctx, str, iname,\
4667 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4669 } while(0);
4671 #define test_dword(wname, iname) \
4672 do {\
4673 uint32_t value;\
4674 enum winreg_Type w_type;\
4675 uint32_t w_size;\
4676 uint32_t w_length;\
4677 uint8_t *w_data;\
4678 torture_assert(tctx,\
4679 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4680 &w_type, &w_size, &w_length, &w_data),\
4681 "failed to query winreg");\
4682 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4683 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4684 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4685 value = IVAL(w_data, 0);\
4686 torture_assert_int_equal(tctx, value, iname,\
4687 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4688 } while(0);
4690 #define test_binary(wname, iname) \
4691 do {\
4692 enum winreg_Type w_type;\
4693 uint32_t w_size;\
4694 uint32_t w_length;\
4695 uint8_t *w_data;\
4696 torture_assert(tctx,\
4697 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4698 &w_type, &w_size, &w_length, &w_data),\
4699 "failed to query winreg");\
4700 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4701 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4702 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4703 "binary unequal");\
4704 } while(0);
4707 #define test_dm(wname, iname) \
4708 do {\
4709 DATA_BLOB blob;\
4710 struct spoolss_DeviceMode dm;\
4711 enum ndr_err_code ndr_err;\
4712 enum winreg_Type w_type;\
4713 uint32_t w_size;\
4714 uint32_t w_length;\
4715 uint8_t *w_data;\
4716 torture_assert(tctx,\
4717 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4718 &w_type, &w_size, &w_length, &w_data),\
4719 "failed to query winreg");\
4720 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4721 blob = data_blob(w_data, w_size);\
4722 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4723 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4724 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4725 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4726 "dm unequal");\
4727 } while(0);
4729 #define test_sd(wname, iname) \
4730 do {\
4731 DATA_BLOB blob;\
4732 struct security_descriptor sd;\
4733 enum ndr_err_code ndr_err;\
4734 enum winreg_Type w_type;\
4735 uint32_t w_size;\
4736 uint32_t w_length;\
4737 uint8_t *w_data;\
4738 torture_assert(tctx,\
4739 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4740 &w_type, &w_size, &w_length, &w_data),\
4741 "failed to query winreg");\
4742 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4743 blob = data_blob(w_data, w_size);\
4744 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4745 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4746 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4747 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4748 "sd unequal");\
4749 } while(0);
4751 #define test_multi_sz(wname, iname) \
4752 do {\
4753 DATA_BLOB blob;\
4754 const char **array;\
4755 enum winreg_Type w_type;\
4756 uint32_t w_size;\
4757 uint32_t w_length;\
4758 uint8_t *w_data;\
4759 int i;\
4760 torture_assert(tctx,\
4761 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4762 &w_type, &w_size, &w_length, &w_data),\
4763 "failed to query winreg");\
4764 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4765 blob = data_blob(w_data, w_size);\
4766 torture_assert(tctx, \
4767 pull_reg_multi_sz(tctx, &blob, &array),\
4768 "failed to pull multi sz");\
4769 for (i=0; array[i] != NULL; i++) {\
4770 torture_assert_str_equal(tctx, array[i], iname[i],\
4771 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4773 } while(0);
4775 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4776 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4777 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4779 torture_warning(tctx, "failed to check for winreg symlink");
4782 for (i=0; i < ARRAY_SIZE(keys); i++) {
4784 const char *printer_key;
4785 struct policy_handle key_handle;
4787 printer_key = talloc_asprintf(tctx, "%s\\%s",
4788 keys[i], printer_name);
4790 torture_assert(tctx,
4791 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4793 test_sz("Name", printername);
4794 test_sz("Share Name", sharename);
4795 test_sz("Port", info.info2.portname);
4796 test_sz("Printer Driver", info.info2.drivername);
4797 test_sz("Description", info.info2.comment);
4798 test_sz("Location", info.info2.location);
4799 test_sz("Separator File", info.info2.sepfile);
4800 test_sz("Print Processor", info.info2.printprocessor);
4801 test_sz("Datatype", info.info2.datatype);
4802 test_sz("Parameters", info.info2.parameters);
4803 /* winreg: 0, spoolss not */
4804 /* test_dword("Attributes", info.info2.attributes); */
4805 test_dword("Priority", info.info2.priority);
4806 test_dword("Default Priority", info.info2.defaultpriority);
4807 /* winreg: 60, spoolss: 0 */
4808 /* test_dword("StartTime", info.info2.starttime); */
4809 /* test_dword("UntilTime", info.info2.untiltime); */
4810 /* winreg != spoolss */
4811 /* test_dword("Status", info.info2.status); */
4812 test_dm("Default DevMode", info.info2.devmode);
4813 test_sd("Security", info.info2.secdesc);
4815 torture_assert(tctx,
4816 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4819 #undef test_dm
4820 #undef test_sd
4822 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4824 return true;
4827 static bool test_PrintProcessors(struct torture_context *tctx,
4828 struct dcerpc_binding_handle *b,
4829 const char *environment,
4830 struct dcerpc_binding_handle *winreg_handle,
4831 struct policy_handle *hive_handle)
4833 union spoolss_PrintProcessorInfo *info;
4834 uint32_t count;
4835 int i;
4837 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4839 torture_assert(tctx,
4840 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4841 "failed to enum print processors level 1");
4843 for (i=0; i < count; i++) {
4845 const char *processor_key;
4846 struct policy_handle key_handle;
4848 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4849 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4850 environment,
4851 info[i].info1.print_processor_name);
4853 torture_assert(tctx,
4854 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4856 /* nothing to check in there so far */
4858 torture_assert(tctx,
4859 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4862 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4864 return true;
4867 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4868 struct dcerpc_binding_handle *b,
4869 struct policy_handle *handle,
4870 const char *driver_name,
4871 const char *architecture,
4872 uint32_t level,
4873 uint32_t client_major_version,
4874 uint32_t client_minor_version,
4875 union spoolss_DriverInfo *info_p,
4876 WERROR *result);
4878 static const char *strip_path(const char *path)
4880 char *p;
4882 if (path == NULL) {
4883 return NULL;
4886 p = strrchr(path, '\\');
4887 if (p) {
4888 return p+1;
4891 return path;
4894 static const char **strip_paths(const char **path_array)
4896 int i;
4898 if (path_array == NULL) {
4899 return NULL;
4902 for (i=0; path_array[i] != NULL; i++) {
4903 path_array[i] = strip_path(path_array[i]);
4906 return path_array;
4909 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4911 time_t t;
4912 struct tm *tm;
4914 if (nt == 0) {
4915 return talloc_strdup(mem_ctx, "01/01/1601");
4918 t = nt_time_to_unix(nt);
4919 tm = localtime(&t);
4921 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4922 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4925 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4927 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4928 (unsigned)((v >> 48) & 0xFFFF),
4929 (unsigned)((v >> 32) & 0xFFFF),
4930 (unsigned)((v >> 16) & 0xFFFF),
4931 (unsigned)(v & 0xFFFF));
4934 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4935 struct dcerpc_binding_handle *b,
4936 struct policy_handle *handle,
4937 const char *printer_name,
4938 const char *driver_name,
4939 const char *environment,
4940 enum spoolss_DriverOSVersion version,
4941 struct dcerpc_binding_handle *winreg_handle,
4942 struct policy_handle *hive_handle,
4943 const char *server_name_slash)
4945 WERROR result;
4946 union spoolss_DriverInfo info;
4947 const char *driver_key;
4948 struct policy_handle key_handle;
4950 const char *driver_path;
4951 const char *data_file;
4952 const char *config_file;
4953 const char *help_file;
4954 const char **dependent_files;
4956 const char *driver_date;
4957 const char *inbox_driver_date;
4959 const char *driver_version;
4960 const char *inbox_driver_version;
4962 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4964 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4965 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4966 environment,
4967 version,
4968 driver_name);
4970 torture_assert(tctx,
4971 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4972 "failed to open driver key");
4974 if (torture_setting_bool(tctx, "samba3", false) ||
4975 torture_setting_bool(tctx, "w2k3", false)) {
4976 goto try_level6;
4979 if (handle) {
4980 torture_assert(tctx,
4981 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4982 "failed to get driver info level 8");
4983 } else {
4984 torture_assert(tctx,
4985 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4986 "failed to get driver info level 8");
4989 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4990 goto try_level6;
4993 driver_path = strip_path(info.info8.driver_path);
4994 data_file = strip_path(info.info8.data_file);
4995 config_file = strip_path(info.info8.config_file);
4996 help_file = strip_path(info.info8.help_file);
4997 dependent_files = strip_paths(info.info8.dependent_files);
4999 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5000 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5002 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5003 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5005 test_sz("Configuration File", config_file);
5006 test_sz("Data File", data_file);
5007 test_sz("Datatype", info.info8.default_datatype);
5008 test_sz("Driver", driver_path);
5009 test_sz("DriverDate", driver_date);
5010 test_sz("DriverVersion", driver_version);
5011 test_sz("HardwareID", info.info8.hardware_id);
5012 test_sz("Help File", help_file);
5013 test_sz("InfPath", info.info8.inf_path);
5014 test_sz("Manufacturer", info.info8.manufacturer_name);
5015 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5016 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5017 test_sz("Monitor", info.info8.monitor_name);
5018 test_sz("OEM URL", info.info8.manufacturer_url);
5019 test_sz("Print Processor", info.info8.print_processor);
5020 test_sz("Provider", info.info8.provider);
5021 test_sz("VendorSetup", info.info8.vendor_setup);
5022 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5023 test_multi_sz("Dependent Files", dependent_files);
5024 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5025 test_multi_sz("Previous Names", info.info8.previous_names);
5026 /* test_dword("Attributes", ?); */
5027 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5028 test_dword("Version", info.info8.version);
5029 /* test_dword("TempDir", ?); */
5031 try_level6:
5033 if (handle) {
5034 torture_assert(tctx,
5035 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5036 "failed to get driver info level 6");
5037 } else {
5038 torture_assert(tctx,
5039 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5040 "failed to get driver info level 6");
5043 driver_path = strip_path(info.info6.driver_path);
5044 data_file = strip_path(info.info6.data_file);
5045 config_file = strip_path(info.info6.config_file);
5046 help_file = strip_path(info.info6.help_file);
5047 dependent_files = strip_paths(info.info6.dependent_files);
5049 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5051 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5053 test_sz("Configuration File", config_file);
5054 test_sz("Data File", data_file);
5055 test_sz("Datatype", info.info6.default_datatype);
5056 test_sz("Driver", driver_path);
5057 if (torture_setting_bool(tctx, "w2k3", false)) {
5058 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5059 push_nttime(blob.data, 0, info.info6.driver_date);
5060 test_binary("DriverDate", blob);
5061 SBVAL(blob.data, 0, info.info6.driver_version);
5062 test_binary("DriverVersion", blob);
5063 } else {
5064 test_sz("DriverDate", driver_date);
5065 test_sz("DriverVersion", driver_version);
5067 test_sz("HardwareID", info.info6.hardware_id);
5068 test_sz("Help File", help_file);
5069 test_sz("Manufacturer", info.info6.manufacturer_name);
5070 test_sz("Monitor", info.info6.monitor_name);
5071 test_sz("OEM URL", info.info6.manufacturer_url);
5072 test_sz("Provider", info.info6.provider);
5073 test_multi_sz("Dependent Files", dependent_files);
5074 test_multi_sz("Previous Names", info.info6.previous_names);
5075 /* test_dword("Attributes", ?); */
5076 test_dword("Version", info.info6.version);
5077 /* test_dword("TempDir", ?); */
5079 if (handle) {
5080 torture_assert(tctx,
5081 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5082 "failed to get driver info level 3");
5083 } else {
5084 torture_assert(tctx,
5085 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5086 "failed to get driver info level 3");
5089 driver_path = strip_path(info.info3.driver_path);
5090 data_file = strip_path(info.info3.data_file);
5091 config_file = strip_path(info.info3.config_file);
5092 help_file = strip_path(info.info3.help_file);
5093 dependent_files = strip_paths(info.info3.dependent_files);
5095 test_sz("Configuration File", config_file);
5096 test_sz("Data File", data_file);
5097 test_sz("Datatype", info.info3.default_datatype);
5098 test_sz("Driver", driver_path);
5099 test_sz("Help File", help_file);
5100 test_sz("Monitor", info.info3.monitor_name);
5101 test_multi_sz("Dependent Files", dependent_files);
5102 /* test_dword("Attributes", ?); */
5103 test_dword("Version", info.info3.version);
5104 /* test_dword("TempDir", ?); */
5107 torture_assert(tctx,
5108 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5110 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5112 return true;
5115 #undef test_sz
5116 #undef test_dword
5118 static bool test_SetPrinterData(struct torture_context *tctx,
5119 struct dcerpc_binding_handle *b,
5120 struct policy_handle *handle,
5121 const char *value_name,
5122 enum winreg_Type type,
5123 uint8_t *data,
5124 uint32_t offered)
5126 struct spoolss_SetPrinterData r;
5128 r.in.handle = handle;
5129 r.in.value_name = value_name;
5130 r.in.type = type;
5131 r.in.data = data;
5132 r.in.offered = offered;
5134 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5135 r.in.value_name);
5137 torture_assert_ntstatus_ok(tctx,
5138 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5139 "SetPrinterData failed");
5140 torture_assert_werr_ok(tctx, r.out.result,
5141 "SetPrinterData failed");
5143 return true;
5146 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5147 struct dcerpc_binding_handle *b,
5148 struct policy_handle *handle,
5149 const char *printer_name,
5150 struct dcerpc_binding_handle *winreg_handle,
5151 struct policy_handle *hive_handle)
5153 const char *values[] = {
5154 "spootyfoot",
5155 "spooty\\foot",
5156 #if 0
5157 /* FIXME: not working with s3 atm. */
5158 "spooty,foot",
5159 "spooty,fo,ot",
5160 #endif
5161 "spooty foot",
5162 #if 0
5163 /* FIXME: not working with s3 atm. */
5164 "spooty\\fo,ot",
5165 "spooty,fo\\ot"
5166 #endif
5168 int i;
5170 for (i=0; i < ARRAY_SIZE(values); i++) {
5172 enum winreg_Type type, expected_type = REG_SZ;
5173 DATA_BLOB blob;
5174 uint8_t *data;
5175 uint32_t needed;
5177 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5178 type = REG_SZ;
5180 torture_assert(tctx,
5181 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5182 "SetPrinterData failed");
5184 torture_assert(tctx,
5185 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5186 "GetPrinterData failed");
5188 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5189 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5190 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5192 if (winreg_handle && hive_handle) {
5194 enum winreg_Type w_type;
5195 uint32_t w_size;
5196 uint32_t w_length;
5197 uint8_t *w_data;
5199 torture_assert(tctx,
5200 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5201 printer_name, "PrinterDriverData", values[i],
5202 &w_type, &w_size, &w_length, &w_data), "");
5204 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5205 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5206 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5207 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5210 torture_assert(tctx,
5211 test_DeletePrinterData(tctx, b, handle, values[i]),
5212 "DeletePrinterData failed");
5215 return true;
5219 static bool test_EnumPrinterKey(struct torture_context *tctx,
5220 struct dcerpc_binding_handle *b,
5221 struct policy_handle *handle,
5222 const char *key_name,
5223 const char ***array);
5225 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5226 struct dcerpc_binding_handle *b,
5227 struct policy_handle *handle,
5228 const char *key_name,
5229 const char *value_name,
5230 enum winreg_Type type,
5231 uint8_t *data,
5232 uint32_t offered)
5234 NTSTATUS status;
5235 struct spoolss_SetPrinterDataEx r;
5237 r.in.handle = handle;
5238 r.in.key_name = key_name;
5239 r.in.value_name = value_name;
5240 r.in.type = type;
5241 r.in.data = data;
5242 r.in.offered = offered;
5244 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5245 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5247 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5249 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5250 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5252 return true;
5255 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5256 struct dcerpc_pipe *p,
5257 struct policy_handle *handle)
5259 struct dcerpc_binding_handle *b = p->binding_handle;
5260 const char *value_name = "dog";
5261 const char *keys[] = {
5262 "torturedataex",
5263 "torture data ex",
5264 "torturedataex_with_subkey\\subkey",
5265 "torturedataex_with_subkey\\subkey:0",
5266 "torturedataex_with_subkey\\subkey:1",
5267 "torturedataex_with_subkey\\subkey\\subsubkey",
5268 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5269 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5270 "torture,data",
5271 "torture,data,ex",
5272 "torture,data\\ex",
5273 "torture\\data,ex",
5274 "torture/data",
5275 "torture/data ex",
5276 "torture/data ex/sub",
5277 "torture//data",
5278 "torture//data ex",
5279 "torture//data ex/sub",
5280 "torture//data ex//sub",
5282 int i;
5284 for (i=0; i < ARRAY_SIZE(keys); i++) {
5286 char *c;
5287 const char *key;
5288 enum winreg_Type type;
5289 DATA_BLOB blob_in, blob_out;
5290 const char **subkeys;
5291 uint32_t ecount;
5292 struct spoolss_PrinterEnumValues *einfo;
5293 uint32_t needed;
5295 blob_in = data_blob_talloc(tctx, NULL, 42);
5297 generate_random_buffer(blob_in.data, blob_in.length);
5299 torture_assert(tctx,
5300 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5301 "failed to call SetPrinterDataEx");
5303 torture_assert(tctx,
5304 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5305 "failed to call GetPrinterDataEx");
5307 blob_out.length = needed;
5308 torture_assert(tctx,
5309 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5310 "failed to call EnumPrinterDataEx");
5312 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5313 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5314 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5316 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5317 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5318 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5319 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5320 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5321 if (einfo[0].data_length > 0) {
5322 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5325 key = talloc_strdup(tctx, keys[i]);
5327 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5328 return false;
5331 c = strchr(key, '\\');
5332 if (c) {
5333 int k;
5335 /* we have subkeys */
5337 *c = 0;
5339 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5340 return false;
5343 for (k=0; subkeys && subkeys[k]; k++) {
5345 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5347 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5348 return false;
5352 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5353 return false;
5356 } else {
5357 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5358 return false;
5363 return true;
5366 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5367 struct dcerpc_pipe *p,
5368 struct policy_handle *handle)
5370 struct dcerpc_binding_handle *b = p->binding_handle;
5371 const char *key = "torturedataex";
5372 const char *values[] = {
5373 "torture_value",
5374 "torture value",
5375 "torture,value",
5376 "torture/value",
5377 "torture\\value",
5378 "torture\\\\value"
5380 int i;
5382 for (i=0; i < ARRAY_SIZE(values); i++) {
5384 enum winreg_Type type;
5385 DATA_BLOB blob_in, blob_out;
5386 uint32_t ecount;
5387 struct spoolss_PrinterEnumValues *einfo;
5388 uint32_t needed;
5390 if (torture_setting_bool(tctx, "samba3", false)) {
5391 char *q;
5392 q = strrchr(values[i], ',');
5393 if (q) {
5394 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5395 values[i]);
5396 continue;
5400 blob_in = data_blob_talloc(tctx, NULL, 42);
5402 generate_random_buffer(blob_in.data, blob_in.length);
5404 torture_assert(tctx,
5405 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5406 "failed to call SetPrinterDataEx");
5408 torture_assert(tctx,
5409 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5410 "failed to call GetPrinterDataEx");
5412 blob_out.length = needed;
5413 torture_assert(tctx,
5414 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5415 "failed to call EnumPrinterDataEx");
5417 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5418 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5419 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5421 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5422 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5423 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5424 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5425 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5426 if (einfo[0].data_length > 0) {
5427 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5430 torture_assert(tctx,
5431 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5432 "failed to call DeletePrinterDataEx");
5435 return true;
5439 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5440 struct dcerpc_pipe *p,
5441 struct policy_handle *handle,
5442 const char *printername,
5443 struct dcerpc_binding_handle *winreg_handle,
5444 struct policy_handle *hive_handle)
5446 struct dcerpc_binding_handle *b = p->binding_handle;
5447 const char *value_name = "dog";
5448 const char *key_name = "torturedataex";
5449 enum winreg_Type types[] = {
5450 REG_SZ,
5451 REG_MULTI_SZ,
5452 REG_DWORD,
5453 REG_BINARY
5455 const char *str = "abcdefghi";
5456 int t, s;
5458 for (t=0; t < ARRAY_SIZE(types); t++) {
5459 for (s=0; s < strlen(str); s++) {
5461 enum winreg_Type type;
5462 const char *string = talloc_strndup(tctx, str, s);
5463 const char *array[2];
5464 DATA_BLOB blob = data_blob_string_const(string);
5465 DATA_BLOB data;
5466 uint8_t *data_out;
5467 uint32_t needed, offered = 0;
5468 uint32_t ecount;
5469 struct spoolss_PrinterEnumValues *einfo;
5471 array[0] = talloc_strdup(tctx, string);
5472 array[1] = NULL;
5474 if (types[t] == REG_DWORD) {
5475 s = 0xffff;
5478 switch (types[t]) {
5479 case REG_BINARY:
5480 data = blob;
5481 offered = blob.length;
5482 break;
5483 case REG_DWORD:
5484 data = data_blob_talloc(tctx, NULL, 4);
5485 SIVAL(data.data, 0, 0x12345678);
5486 offered = 4;
5487 break;
5488 case REG_SZ:
5489 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5490 type = REG_SZ;
5491 offered = data.length;
5492 /*strlen_m_term(data.string)*2;*/
5493 break;
5494 case REG_MULTI_SZ:
5495 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5496 type = REG_MULTI_SZ;
5497 offered = data.length;
5498 break;
5499 default:
5500 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5503 torture_assert(tctx,
5504 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5505 "failed to call SetPrinterDataEx");
5507 torture_assert(tctx,
5508 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5509 "failed to call GetPrinterDataEx");
5511 torture_assert(tctx,
5512 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5513 "failed to call EnumPrinterDataEx");
5515 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5516 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5517 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5519 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5520 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5521 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5522 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5523 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5524 if (einfo[0].data_length > 0) {
5525 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5528 if (winreg_handle && hive_handle) {
5529 enum winreg_Type w_type;
5530 uint32_t w_size;
5531 uint32_t w_length;
5532 uint8_t *w_data;
5534 torture_assert(tctx,
5535 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5536 printername, key_name, value_name,
5537 &w_type, &w_size, &w_length, &w_data), "");
5539 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5540 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5541 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5542 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5545 torture_assert(tctx,
5546 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5547 "failed to call DeletePrinterDataEx");
5551 return true;
5554 static bool test_PrinterData_winreg(struct torture_context *tctx,
5555 struct dcerpc_pipe *p,
5556 struct policy_handle *handle,
5557 const char *printer_name)
5559 struct dcerpc_binding_handle *b = p->binding_handle;
5560 struct dcerpc_pipe *p2;
5561 bool ret = true;
5562 struct policy_handle hive_handle;
5563 struct dcerpc_binding_handle *b2;
5565 torture_assert_ntstatus_ok(tctx,
5566 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5567 "could not open winreg pipe");
5568 b2 = p2->binding_handle;
5570 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5572 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5573 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5575 test_winreg_CloseKey(tctx, b2, &hive_handle);
5577 talloc_free(p2);
5579 return ret;
5582 static bool test_Forms_winreg(struct torture_context *tctx,
5583 struct dcerpc_binding_handle *b,
5584 struct policy_handle *handle,
5585 bool print_server,
5586 const char *printer_name)
5588 struct dcerpc_pipe *p2;
5589 bool ret = true;
5590 struct policy_handle hive_handle;
5591 struct dcerpc_binding_handle *b2;
5593 torture_assert_ntstatus_ok(tctx,
5594 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5595 "could not open winreg pipe");
5596 b2 = p2->binding_handle;
5598 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5600 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5602 test_winreg_CloseKey(tctx, b2, &hive_handle);
5604 talloc_free(p2);
5606 return ret;
5609 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5610 struct dcerpc_pipe *p,
5611 struct policy_handle *handle,
5612 const char *printer_name)
5614 struct dcerpc_binding_handle *b = p->binding_handle;
5615 struct dcerpc_pipe *p2;
5616 bool ret = true;
5617 struct policy_handle hive_handle;
5618 struct dcerpc_binding_handle *b2;
5620 torture_assert_ntstatus_ok(tctx,
5621 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5622 "could not open winreg pipe");
5623 b2 = p2->binding_handle;
5625 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5627 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5629 test_winreg_CloseKey(tctx, b2, &hive_handle);
5631 talloc_free(p2);
5633 return ret;
5636 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5637 struct dcerpc_pipe *p,
5638 struct policy_handle *handle,
5639 const char *printer_name,
5640 const char *driver_name,
5641 const char *environment,
5642 enum spoolss_DriverOSVersion version)
5644 struct dcerpc_binding_handle *b = p->binding_handle;
5645 struct dcerpc_pipe *p2;
5646 bool ret = true;
5647 struct policy_handle hive_handle;
5648 struct dcerpc_binding_handle *b2;
5650 torture_assert_ntstatus_ok(tctx,
5651 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5652 "could not open winreg pipe");
5653 b2 = p2->binding_handle;
5655 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5657 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5659 test_winreg_CloseKey(tctx, b2, &hive_handle);
5661 talloc_free(p2);
5663 return ret;
5666 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5667 struct dcerpc_binding_handle *b,
5668 const char *environment)
5670 struct dcerpc_pipe *p2;
5671 bool ret = true;
5672 struct policy_handle hive_handle;
5673 struct dcerpc_binding_handle *b2;
5675 torture_assert_ntstatus_ok(tctx,
5676 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5677 "could not open winreg pipe");
5678 b2 = p2->binding_handle;
5680 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5682 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5684 test_winreg_CloseKey(tctx, b2, &hive_handle);
5686 talloc_free(p2);
5688 return ret;
5691 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5692 struct dcerpc_pipe *p,
5693 struct policy_handle *handle,
5694 const char *printer_name)
5696 struct spoolss_SetPrinterInfoCtr info_ctr;
5697 struct spoolss_DevmodeContainer devmode_ctr;
5698 struct sec_desc_buf secdesc_ctr;
5699 union spoolss_SetPrinterInfo sinfo;
5700 union spoolss_PrinterInfo info;
5701 struct dcerpc_binding_handle *b = p->binding_handle;
5702 const char *pname;
5704 ZERO_STRUCT(info_ctr);
5705 ZERO_STRUCT(devmode_ctr);
5706 ZERO_STRUCT(secdesc_ctr);
5708 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5710 torture_assert(tctx,
5711 test_GetPrinter_level(tctx, b, handle, 2, &info),
5712 "failed to query Printer level 2");
5714 torture_assert(tctx,
5715 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5716 "failed to convert");
5718 info_ctr.level = 2;
5719 info_ctr.info = sinfo;
5721 #define TEST_SZ(wname, iname) \
5722 do {\
5723 enum winreg_Type type;\
5724 uint8_t *data;\
5725 uint32_t needed;\
5726 DATA_BLOB blob;\
5727 const char *str;\
5728 torture_assert(tctx,\
5729 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5730 "failed to query");\
5731 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5732 blob = data_blob_const(data, needed);\
5733 torture_assert(tctx,\
5734 pull_reg_sz(tctx, &blob, &str),\
5735 "failed to pull REG_SZ");\
5736 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5737 } while(0);
5740 #define TEST_SET_SZ(wname, iname, val) \
5741 do {\
5742 enum winreg_Type type;\
5743 uint8_t *data;\
5744 uint32_t needed;\
5745 DATA_BLOB blob;\
5746 const char *str;\
5747 sinfo.info2->iname = val;\
5748 torture_assert(tctx,\
5749 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5750 "failed to call SetPrinter");\
5751 torture_assert(tctx,\
5752 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5753 "failed to query");\
5754 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5755 blob = data_blob_const(data, needed);\
5756 torture_assert(tctx,\
5757 pull_reg_sz(tctx, &blob, &str),\
5758 "failed to pull REG_SZ");\
5759 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5760 } while(0);
5762 #define TEST_SET_DWORD(wname, iname, val) \
5763 do {\
5764 enum winreg_Type type;\
5765 uint8_t *data;\
5766 uint32_t needed;\
5767 uint32_t value;\
5768 sinfo.info2->iname = val;\
5769 torture_assert(tctx,\
5770 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5771 "failed to call SetPrinter");\
5772 torture_assert(tctx,\
5773 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5774 "failed to query");\
5775 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5776 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5777 value = IVAL(data, 0); \
5778 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5779 } while(0);
5781 TEST_SET_SZ("description", comment, "newval");
5782 TEST_SET_SZ("location", location, "newval");
5783 TEST_SET_SZ("driverName", drivername, "newval");
5784 /* TEST_SET_DWORD("priority", priority, 25); */
5786 torture_assert(tctx,
5787 test_GetPrinter_level(tctx, b, handle, 2, &info),
5788 "failed to query Printer level 2");
5790 TEST_SZ("description", info.info2.comment);
5791 TEST_SZ("driverName", info.info2.drivername);
5792 TEST_SZ("location", info.info2.location);
5794 pname = strrchr(info.info2.printername, '\\');
5795 if (pname == NULL) {
5796 pname = info.info2.printername;
5797 } else {
5798 pname++;
5800 TEST_SZ("printerName", pname);
5801 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5802 /* TEST_SZ("printShareName", info.info2.sharename); */
5804 /* FIXME gd: complete the list */
5806 #undef TEST_SZ
5807 #undef TEST_SET_SZ
5808 #undef TEST_DWORD
5810 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5812 return true;
5815 static bool test_print_processors_winreg(struct torture_context *tctx,
5816 void *private_data)
5818 struct test_spoolss_context *ctx =
5819 talloc_get_type_abort(private_data, struct test_spoolss_context);
5820 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5821 struct dcerpc_binding_handle *b = p->binding_handle;
5823 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5826 static bool test_AddPrintProcessor(struct torture_context *tctx,
5827 struct dcerpc_binding_handle *b,
5828 const char *environment,
5829 const char *path_name,
5830 const char *print_processor_name,
5831 WERROR expected_error)
5833 struct spoolss_AddPrintProcessor r;
5835 r.in.server = NULL;
5836 r.in.architecture = environment;
5837 r.in.path_name = path_name;
5838 r.in.print_processor_name = print_processor_name;
5840 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5841 print_processor_name);
5843 torture_assert_ntstatus_ok(tctx,
5844 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5845 "spoolss_AddPrintProcessor failed");
5846 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5847 "spoolss_AddPrintProcessor failed");
5849 return true;
5852 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5853 struct dcerpc_binding_handle *b,
5854 const char *environment,
5855 const char *print_processor_name,
5856 WERROR expected_error)
5858 struct spoolss_DeletePrintProcessor r;
5860 r.in.server = NULL;
5861 r.in.architecture = environment;
5862 r.in.print_processor_name = print_processor_name;
5864 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5865 print_processor_name);
5867 torture_assert_ntstatus_ok(tctx,
5868 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5869 "spoolss_DeletePrintProcessor failed");
5870 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5871 "spoolss_DeletePrintProcessor failed");
5873 return true;
5876 static bool test_add_print_processor(struct torture_context *tctx,
5877 void *private_data)
5879 struct test_spoolss_context *ctx =
5880 talloc_get_type_abort(private_data, struct test_spoolss_context);
5881 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5882 struct dcerpc_binding_handle *b = p->binding_handle;
5883 int i;
5885 struct {
5886 const char *environment;
5887 const char *path_name;
5888 const char *print_processor_name;
5889 WERROR expected_add_result;
5890 WERROR expected_del_result;
5891 } tests[] = {
5893 .environment = ctx->environment,
5894 .path_name = "",
5895 .print_processor_name = "winprint",
5896 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
5897 .expected_del_result = WERR_CAN_NOT_COMPLETE
5899 .environment = ctx->environment,
5900 .path_name = "",
5901 .print_processor_name = "unknown",
5902 .expected_add_result = WERR_MOD_NOT_FOUND,
5903 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
5907 for (i=0; i < ARRAY_SIZE(tests); i++) {
5908 torture_assert(tctx,
5909 test_AddPrintProcessor(tctx, b,
5910 tests[i].environment,
5911 tests[i].path_name,
5912 tests[i].print_processor_name,
5913 tests[i].expected_add_result),
5914 "add print processor failed");
5915 torture_assert(tctx,
5916 test_DeletePrintProcessor(tctx, b,
5917 tests[i].environment,
5918 tests[i].print_processor_name,
5919 tests[i].expected_del_result),
5920 "delete print processor failed");
5923 return true;
5926 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5927 struct dcerpc_binding_handle *b,
5928 struct policy_handle *handle,
5929 uint32_t *change_id)
5931 enum winreg_Type type;
5932 uint8_t *data;
5933 uint32_t needed;
5935 torture_assert(tctx,
5936 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5937 "failed to call GetPrinterData");
5939 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5940 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5942 *change_id = IVAL(data, 0);
5944 return true;
5947 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5948 struct dcerpc_pipe *p,
5949 struct policy_handle *handle,
5950 uint32_t *change_id)
5952 enum winreg_Type type;
5953 uint8_t *data;
5954 uint32_t needed;
5956 torture_assert(tctx,
5957 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5958 "failed to call GetPrinterData");
5960 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5961 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5963 *change_id = IVAL(data, 0);
5965 return true;
5968 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5969 struct dcerpc_binding_handle *b,
5970 struct policy_handle *handle,
5971 uint32_t *change_id)
5973 union spoolss_PrinterInfo info;
5975 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5976 "failed to query Printer level 0");
5978 *change_id = info.info0.change_id;
5980 return true;
5983 static bool test_ChangeID(struct torture_context *tctx,
5984 struct dcerpc_pipe *p,
5985 struct policy_handle *handle)
5987 uint32_t change_id, change_id_ex, change_id_info;
5988 uint32_t change_id2, change_id_ex2, change_id_info2;
5989 union spoolss_PrinterInfo info;
5990 const char *comment;
5991 struct dcerpc_binding_handle *b = p->binding_handle;
5993 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5995 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5996 "failed to query for ChangeID");
5997 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5998 "failed to query for ChangeID");
5999 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6000 "failed to query for ChangeID");
6002 torture_assert_int_equal(tctx, change_id, change_id_ex,
6003 "change_ids should all be equal");
6004 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6005 "change_ids should all be equal");
6008 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6010 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6011 "failed to query for ChangeID");
6012 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6013 "failed to query Printer level 2");
6014 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6015 "failed to query for ChangeID");
6016 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6017 "failed to query for ChangeID");
6018 torture_assert_int_equal(tctx, change_id, change_id_ex,
6019 "change_id should not have changed");
6020 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6021 "change_id should not have changed");
6024 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6026 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6027 "failed to query for ChangeID");
6028 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6029 "failed to query for ChangeID");
6030 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6031 "failed to query for ChangeID");
6032 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6033 "failed to query Printer level 2");
6034 comment = talloc_strdup(tctx, info.info2.comment);
6037 struct spoolss_SetPrinterInfoCtr info_ctr;
6038 struct spoolss_DevmodeContainer devmode_ctr;
6039 struct sec_desc_buf secdesc_ctr;
6040 union spoolss_SetPrinterInfo sinfo;
6042 ZERO_STRUCT(info_ctr);
6043 ZERO_STRUCT(devmode_ctr);
6044 ZERO_STRUCT(secdesc_ctr);
6047 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6048 sinfo.info2->comment = "torture_comment";
6050 info_ctr.level = 2;
6051 info_ctr.info = sinfo;
6053 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6054 "failed to call SetPrinter");
6056 sinfo.info2->comment = comment;
6058 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6059 "failed to call SetPrinter");
6063 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6064 "failed to query for ChangeID");
6065 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6066 "failed to query for ChangeID");
6067 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6068 "failed to query for ChangeID");
6070 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6071 "change_ids should all be equal");
6072 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6073 "change_ids should all be equal");
6075 torture_assert(tctx, (change_id < change_id2),
6076 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6077 change_id2, change_id));
6078 torture_assert(tctx, (change_id_ex < change_id_ex2),
6079 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6080 change_id_ex2, change_id_ex));
6081 torture_assert(tctx, (change_id_info < change_id_info2),
6082 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6083 change_id_info2, change_id_info));
6085 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6087 return true;
6090 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6091 struct dcerpc_pipe *p,
6092 struct policy_handle *handle)
6094 NTSTATUS status;
6095 struct dcerpc_binding *b;
6096 struct dcerpc_pipe *p2;
6097 struct spoolss_ClosePrinter cp;
6099 /* only makes sense on SMB */
6100 if (p->conn->transport.transport != NCACN_NP) {
6101 return true;
6104 torture_comment(tctx, "Testing close on secondary pipe\n");
6106 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
6107 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
6109 status = dcerpc_secondary_connection(p, &p2, b);
6110 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6112 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6113 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6115 cp.in.handle = handle;
6116 cp.out.handle = handle;
6118 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6119 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6120 "ERROR: Allowed close on secondary connection");
6122 talloc_free(p2);
6124 return true;
6127 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6128 struct dcerpc_binding_handle *b, const char *name)
6130 NTSTATUS status;
6131 struct spoolss_OpenPrinter op;
6132 struct spoolss_OpenPrinterEx opEx;
6133 struct policy_handle handle;
6134 bool ret = true;
6136 op.in.printername = name;
6137 op.in.datatype = NULL;
6138 op.in.devmode_ctr.devmode= NULL;
6139 op.in.access_mask = 0;
6140 op.out.handle = &handle;
6142 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6144 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6145 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6146 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6147 "unexpected result");
6149 if (W_ERROR_IS_OK(op.out.result)) {
6150 ret &=test_ClosePrinter(tctx, b, &handle);
6153 opEx.in.printername = name;
6154 opEx.in.datatype = NULL;
6155 opEx.in.devmode_ctr.devmode = NULL;
6156 opEx.in.access_mask = 0;
6157 opEx.in.userlevel_ctr.level = 1;
6158 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6159 opEx.out.handle = &handle;
6161 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6163 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6164 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6165 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6166 "unexpected result");
6168 if (W_ERROR_IS_OK(opEx.out.result)) {
6169 ret &=test_ClosePrinter(tctx, b, &handle);
6172 return ret;
6175 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6176 void *private_data)
6178 struct test_spoolss_context *ctx =
6179 talloc_get_type_abort(private_data, struct test_spoolss_context);
6181 const char *badnames[] = {
6182 "__INVALID_PRINTER__",
6183 "\\\\__INVALID_HOST__",
6185 "\\\\\\",
6186 "\\\\\\__INVALID_PRINTER__"
6188 const char *badname;
6189 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6190 const char *server_name = dcerpc_server_name(p);
6191 struct dcerpc_binding_handle *b = p->binding_handle;
6192 int i;
6194 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6195 torture_assert(tctx,
6196 test_OpenPrinter_badname(tctx, b, badnames[i]),
6197 "");
6200 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6201 torture_assert(tctx,
6202 test_OpenPrinter_badname(tctx, b, badname),
6203 "");
6205 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6206 torture_assert(tctx,
6207 test_OpenPrinter_badname(tctx, b, badname),
6208 "");
6210 return true;
6213 static bool test_OpenPrinter(struct torture_context *tctx,
6214 struct dcerpc_pipe *p,
6215 const char *name,
6216 const char *environment,
6217 bool open_only)
6219 NTSTATUS status;
6220 struct spoolss_OpenPrinter r;
6221 struct policy_handle handle;
6222 bool ret = true;
6223 struct dcerpc_binding_handle *b = p->binding_handle;
6225 r.in.printername = name;
6226 r.in.datatype = NULL;
6227 r.in.devmode_ctr.devmode= NULL;
6228 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6229 r.out.handle = &handle;
6231 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6233 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6235 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6237 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6239 if (open_only) {
6240 goto close_printer;
6243 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6244 ret = false;
6247 if (!torture_setting_bool(tctx, "samba3", false)) {
6248 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6249 ret = false;
6253 close_printer:
6254 if (!test_ClosePrinter(tctx, b, &handle)) {
6255 ret = false;
6258 return ret;
6261 static bool test_OpenPrinterEx(struct torture_context *tctx,
6262 struct dcerpc_binding_handle *b,
6263 const char *printername,
6264 const char *datatype,
6265 struct spoolss_DeviceMode *devmode,
6266 uint32_t access_mask,
6267 struct spoolss_UserLevelCtr *userlevel_ctr,
6268 struct policy_handle *handle,
6269 WERROR expected_result)
6271 struct spoolss_OpenPrinterEx r;
6273 r.in.printername = printername;
6274 r.in.datatype = datatype;
6275 r.in.devmode_ctr.devmode= devmode;
6276 r.in.access_mask = access_mask;
6277 r.in.userlevel_ctr = *userlevel_ctr;
6278 r.out.handle = handle;
6280 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6282 torture_assert_ntstatus_ok(tctx,
6283 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6284 "OpenPrinterEx failed");
6286 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6287 "OpenPrinterEx failed");
6289 return true;
6292 static bool call_OpenPrinterEx(struct torture_context *tctx,
6293 struct dcerpc_pipe *p,
6294 const char *name,
6295 struct spoolss_DeviceMode *devmode,
6296 struct policy_handle *handle)
6298 struct spoolss_UserLevelCtr userlevel_ctr;
6299 struct spoolss_UserLevel1 userlevel1;
6300 struct dcerpc_binding_handle *b = p->binding_handle;
6302 userlevel1.size = 1234;
6303 userlevel1.client = "hello";
6304 userlevel1.user = "spottyfoot!";
6305 userlevel1.build = 1;
6306 userlevel1.major = 2;
6307 userlevel1.minor = 3;
6308 userlevel1.processor = 4;
6310 userlevel_ctr.level = 1;
6311 userlevel_ctr.user_info.level1 = &userlevel1;
6313 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6314 SEC_FLAG_MAXIMUM_ALLOWED,
6315 &userlevel_ctr,
6316 handle,
6317 WERR_OK);
6320 static bool test_printer_rename(struct torture_context *tctx,
6321 void *private_data)
6323 struct torture_printer_context *t =
6324 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6325 struct dcerpc_pipe *p = t->spoolss_pipe;
6327 bool ret = true;
6328 union spoolss_PrinterInfo info;
6329 union spoolss_SetPrinterInfo sinfo;
6330 struct spoolss_SetPrinterInfoCtr info_ctr;
6331 struct spoolss_DevmodeContainer devmode_ctr;
6332 struct sec_desc_buf secdesc_ctr;
6333 const char *printer_name;
6334 const char *printer_name_orig;
6335 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6336 struct policy_handle new_handle;
6337 const char *q;
6338 struct dcerpc_binding_handle *b = p->binding_handle;
6340 ZERO_STRUCT(devmode_ctr);
6341 ZERO_STRUCT(secdesc_ctr);
6343 torture_comment(tctx, "Testing Printer rename operations\n");
6345 torture_assert(tctx,
6346 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6347 "failed to call GetPrinter level 2");
6349 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6351 q = strrchr(info.info2.printername, '\\');
6352 if (q) {
6353 torture_warning(tctx,
6354 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6357 torture_assert(tctx,
6358 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6360 sinfo.info2->printername = printer_name_new;
6362 info_ctr.level = 2;
6363 info_ctr.info = sinfo;
6365 torture_assert(tctx,
6366 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6367 "failed to call SetPrinter level 2");
6369 torture_assert(tctx,
6370 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6371 "failed to call GetPrinter level 2");
6373 printer_name = talloc_strdup(tctx, info.info2.printername);
6375 q = strrchr(info.info2.printername, '\\');
6376 if (q) {
6377 torture_warning(tctx,
6378 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6379 q++;
6380 printer_name = q;
6383 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6384 "new printer name was not set");
6386 /* samba currently cannot fully rename printers */
6387 if (!torture_setting_bool(tctx, "samba3", false)) {
6388 torture_assert(tctx,
6389 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6390 "still can open printer with oldname after rename");
6391 } else {
6392 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6395 torture_assert(tctx,
6396 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6397 "failed to open printer with new name");
6399 torture_assert(tctx,
6400 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6401 "failed to call GetPrinter level 2");
6403 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6404 "new printer name was not set");
6406 torture_assert(tctx,
6407 test_ClosePrinter(tctx, b, &new_handle),
6408 "failed to close printer");
6410 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6412 return ret;
6415 static bool test_openprinter(struct torture_context *tctx,
6416 struct dcerpc_binding_handle *b,
6417 const char *real_printername)
6419 struct spoolss_UserLevelCtr userlevel_ctr;
6420 struct policy_handle handle;
6421 struct spoolss_UserLevel1 userlevel1;
6422 const char *printername = NULL;
6423 int i;
6425 struct {
6426 const char *suffix;
6427 WERROR expected_result;
6428 } tests[] = {
6430 .suffix = "rubbish",
6431 .expected_result = WERR_INVALID_PRINTER_NAME
6433 .suffix = ", LocalOnl",
6434 .expected_result = WERR_INVALID_PRINTER_NAME
6436 .suffix = ", localOnly",
6437 .expected_result = WERR_INVALID_PRINTER_NAME
6439 .suffix = ", localonl",
6440 .expected_result = WERR_INVALID_PRINTER_NAME
6442 .suffix = ",LocalOnl",
6443 .expected_result = WERR_INVALID_PRINTER_NAME
6445 .suffix = ",localOnl2",
6446 .expected_result = WERR_INVALID_PRINTER_NAME
6448 .suffix = ", DrvConver2t",
6449 .expected_result = WERR_INVALID_PRINTER_NAME
6451 .suffix = ", drvconvert",
6452 .expected_result = WERR_INVALID_PRINTER_NAME
6454 .suffix = ",drvconvert",
6455 .expected_result = WERR_INVALID_PRINTER_NAME
6457 .suffix = ", DrvConvert",
6458 .expected_result = WERR_OK
6460 .suffix = " , DrvConvert",
6461 .expected_result = WERR_INVALID_PRINTER_NAME
6463 .suffix = ",DrvConvert",
6464 .expected_result = WERR_OK
6466 .suffix = ", DrvConvertsadfasdf",
6467 .expected_result = WERR_OK
6469 .suffix = ",DrvConvertasdfasd",
6470 .expected_result = WERR_OK
6472 .suffix = ", LocalOnly",
6473 .expected_result = WERR_OK
6475 .suffix = " , LocalOnly",
6476 .expected_result = WERR_INVALID_PRINTER_NAME
6478 .suffix = ",LocalOnly",
6479 .expected_result = WERR_OK
6481 .suffix = ", LocalOnlysagi4gjfkd",
6482 .expected_result = WERR_OK
6484 .suffix = ",LocalOnlysagi4gjfkd",
6485 .expected_result = WERR_OK
6489 userlevel1.size = 1234;
6490 userlevel1.client = "hello";
6491 userlevel1.user = "spottyfoot!";
6492 userlevel1.build = 1;
6493 userlevel1.major = 2;
6494 userlevel1.minor = 3;
6495 userlevel1.processor = 4;
6497 userlevel_ctr.level = 1;
6498 userlevel_ctr.user_info.level1 = &userlevel1;
6500 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6502 torture_assert(tctx,
6503 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6504 &userlevel_ctr, &handle,
6505 WERR_OK),
6506 "OpenPrinterEx failed");
6507 test_ClosePrinter(tctx, b, &handle);
6509 for (i=0; i < ARRAY_SIZE(tests); i++) {
6511 printername = talloc_asprintf(tctx, "%s%s",
6512 real_printername,
6513 tests[i].suffix);
6515 torture_assert(tctx,
6516 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6517 &userlevel_ctr, &handle,
6518 tests[i].expected_result),
6519 "OpenPrinterEx failed");
6520 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6521 test_ClosePrinter(tctx, b, &handle);
6525 return true;
6529 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6530 struct dcerpc_pipe *p,
6531 const char *name,
6532 const char *environment)
6534 struct policy_handle handle;
6535 bool ret = true;
6536 struct dcerpc_binding_handle *b = p->binding_handle;
6538 if (!test_openprinter(tctx, b, name)) {
6539 return false;
6542 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6543 return false;
6546 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6547 ret = false;
6550 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6551 ret = false;
6554 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6555 ret = false;
6558 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6559 ret = false;
6562 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6563 ret = false;
6566 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6567 ret = false;
6570 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6571 ret = false;
6574 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6575 ret = false;
6578 if (!test_printer_all_keys(tctx, b, &handle)) {
6579 ret = false;
6582 if (!test_PausePrinter(tctx, b, &handle)) {
6583 ret = false;
6586 if (!test_DoPrintTest(tctx, b, &handle)) {
6587 ret = false;
6590 if (!test_ResumePrinter(tctx, b, &handle)) {
6591 ret = false;
6594 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6595 ret = false;
6598 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6599 ret = false;
6602 if (!torture_setting_bool(tctx, "samba3", false)) {
6603 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6604 ret = false;
6608 if (!test_ClosePrinter(tctx, b, &handle)) {
6609 ret = false;
6612 return ret;
6615 static bool test_EnumPrinters_old(struct torture_context *tctx,
6616 void *private_data)
6618 struct test_spoolss_context *ctx =
6619 talloc_get_type_abort(private_data, struct test_spoolss_context);
6620 struct spoolss_EnumPrinters r;
6621 NTSTATUS status;
6622 uint16_t levels[] = {1, 2, 4, 5};
6623 int i;
6624 bool ret = true;
6625 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6626 struct dcerpc_binding_handle *b = p->binding_handle;
6628 for (i=0;i<ARRAY_SIZE(levels);i++) {
6629 union spoolss_PrinterInfo *info;
6630 int j;
6631 uint32_t needed;
6632 uint32_t count;
6634 r.in.flags = PRINTER_ENUM_LOCAL;
6635 r.in.server = "";
6636 r.in.level = levels[i];
6637 r.in.buffer = NULL;
6638 r.in.offered = 0;
6639 r.out.needed = &needed;
6640 r.out.count = &count;
6641 r.out.info = &info;
6643 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6645 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6646 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6648 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6649 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6650 r.in.buffer = &blob;
6651 r.in.offered = needed;
6652 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6655 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6657 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6659 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6661 if (!info) {
6662 torture_comment(tctx, "No printers returned\n");
6663 return true;
6666 for (j=0;j<count;j++) {
6667 if (r.in.level == 1) {
6668 char *unc = talloc_strdup(tctx, info[j].info1.name);
6669 char *slash, *name, *full_name;
6670 name = unc;
6671 if (unc[0] == '\\' && unc[1] == '\\') {
6672 unc +=2;
6674 slash = strchr(unc, '\\');
6675 if (slash) {
6676 slash++;
6677 name = slash;
6679 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6680 dcerpc_server_name(p), name);
6681 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6682 ret = false;
6684 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6685 ret = false;
6687 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6688 ret = false;
6690 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6691 ret = false;
6697 return ret;
6700 static bool test_EnumPrinters_level(struct torture_context *tctx,
6701 struct dcerpc_binding_handle *b,
6702 uint32_t flags,
6703 const char *servername,
6704 uint32_t level,
6705 uint32_t *count_p,
6706 union spoolss_PrinterInfo **info_p)
6708 struct spoolss_EnumPrinters r;
6709 union spoolss_PrinterInfo *info;
6710 uint32_t needed;
6711 uint32_t count;
6713 r.in.flags = flags;
6714 r.in.server = servername;
6715 r.in.level = level;
6716 r.in.buffer = NULL;
6717 r.in.offered = 0;
6718 r.out.needed = &needed;
6719 r.out.count = &count;
6720 r.out.info = &info;
6722 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6723 r.in.server, r.in.level);
6725 torture_assert_ntstatus_ok(tctx,
6726 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6727 "EnumPrinters failed");
6728 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6729 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6730 r.in.buffer = &blob;
6731 r.in.offered = needed;
6732 torture_assert_ntstatus_ok(tctx,
6733 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6734 "EnumPrinters failed");
6737 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6739 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6741 if (count_p) {
6742 *count_p = count;
6744 if (info_p) {
6745 *info_p = info;
6748 return true;
6751 static const char *get_short_printername(struct torture_context *tctx,
6752 const char *name)
6754 const char *short_name;
6756 if (name[0] == '\\' && name[1] == '\\') {
6757 name += 2;
6758 short_name = strchr(name, '\\');
6759 if (short_name) {
6760 return talloc_strdup(tctx, short_name+1);
6764 return name;
6767 static const char *get_full_printername(struct torture_context *tctx,
6768 const char *name)
6770 const char *full_name = talloc_strdup(tctx, name);
6771 char *p;
6773 if (name && name[0] == '\\' && name[1] == '\\') {
6774 name += 2;
6775 p = strchr(name, '\\');
6776 if (p) {
6777 return full_name;
6781 return NULL;
6784 static bool test_OnePrinter_servername(struct torture_context *tctx,
6785 struct dcerpc_pipe *p,
6786 struct dcerpc_binding_handle *b,
6787 const char *servername,
6788 const char *printername)
6790 union spoolss_PrinterInfo info;
6791 const char *short_name = get_short_printername(tctx, printername);
6792 const char *full_name = get_full_printername(tctx, printername);
6794 if (short_name) {
6795 struct policy_handle handle;
6796 torture_assert(tctx,
6797 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6798 "failed to open printer");
6800 torture_assert(tctx,
6801 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6802 "failed to get printer info");
6804 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6805 "unexpected servername");
6806 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6807 "unexpected printername");
6809 if (info.info2.devmode) {
6810 const char *expected_devicename;
6811 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6812 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6813 "unexpected devicemode devicename");
6816 torture_assert(tctx,
6817 test_ClosePrinter(tctx, b, &handle),
6818 "failed to close printer");
6821 if (full_name) {
6822 struct policy_handle handle;
6824 torture_assert(tctx,
6825 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6826 "failed to open printer");
6828 torture_assert(tctx,
6829 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6830 "failed to get printer info");
6832 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6833 "unexpected servername");
6834 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6835 "unexpected printername");
6837 if (info.info2.devmode) {
6838 const char *expected_devicename;
6839 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6840 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6841 "unexpected devicemode devicename");
6844 torture_assert(tctx,
6845 test_ClosePrinter(tctx, b, &handle),
6846 "failed to close printer");
6849 return true;
6852 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6853 void *private_data)
6855 struct test_spoolss_context *ctx =
6856 talloc_get_type_abort(private_data, struct test_spoolss_context);
6857 int i;
6858 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6859 struct dcerpc_binding_handle *b = p->binding_handle;
6860 uint32_t count;
6861 union spoolss_PrinterInfo *info;
6862 const char *servername;
6863 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6865 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6867 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6869 torture_assert(tctx,
6870 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6871 "failed to enumerate printers");
6873 for (i=0; i < count; i++) {
6875 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6876 "unexpected servername");
6878 torture_assert(tctx,
6879 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6880 "failed to check printer");
6883 servername = "";
6885 torture_assert(tctx,
6886 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6887 "failed to enumerate printers");
6889 for (i=0; i < count; i++) {
6891 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6892 "unexpected servername");
6894 torture_assert(tctx,
6895 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6896 "failed to check printer");
6900 return true;
6904 static bool test_GetPrinterDriver(struct torture_context *tctx,
6905 struct dcerpc_binding_handle *b,
6906 struct policy_handle *handle,
6907 const char *driver_name)
6909 struct spoolss_GetPrinterDriver r;
6910 uint32_t needed;
6912 r.in.handle = handle;
6913 r.in.architecture = "W32X86";
6914 r.in.level = 1;
6915 r.in.buffer = NULL;
6916 r.in.offered = 0;
6917 r.out.needed = &needed;
6919 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6921 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6922 "failed to call GetPrinterDriver");
6923 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6924 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6925 r.in.buffer = &blob;
6926 r.in.offered = needed;
6927 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6928 "failed to call GetPrinterDriver");
6931 torture_assert_werr_ok(tctx, r.out.result,
6932 "failed to call GetPrinterDriver");
6934 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6936 return true;
6939 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6940 struct dcerpc_binding_handle *b,
6941 struct policy_handle *handle,
6942 const char *driver_name,
6943 const char *architecture,
6944 uint32_t level,
6945 uint32_t client_major_version,
6946 uint32_t client_minor_version,
6947 union spoolss_DriverInfo *info_p,
6948 WERROR *result_p)
6951 struct spoolss_GetPrinterDriver2 r;
6952 uint32_t needed;
6953 uint32_t server_major_version;
6954 uint32_t server_minor_version;
6956 r.in.handle = handle;
6957 r.in.architecture = architecture;
6958 r.in.client_major_version = client_major_version;
6959 r.in.client_minor_version = client_minor_version;
6960 r.in.buffer = NULL;
6961 r.in.offered = 0;
6962 r.in.level = level;
6963 r.out.needed = &needed;
6964 r.out.server_major_version = &server_major_version;
6965 r.out.server_minor_version = &server_minor_version;
6967 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6968 driver_name, r.in.level);
6970 torture_assert_ntstatus_ok(tctx,
6971 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6972 "failed to call GetPrinterDriver2");
6973 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6974 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6975 r.in.buffer = &blob;
6976 r.in.offered = needed;
6977 torture_assert_ntstatus_ok(tctx,
6978 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6979 "failed to call GetPrinterDriver2");
6982 if (result_p) {
6983 *result_p = r.out.result;
6986 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6987 switch (r.in.level) {
6988 case 101:
6989 case 8:
6990 torture_comment(tctx,
6991 "level %d not implemented, not considering as an error\n",
6992 r.in.level);
6993 return true;
6994 default:
6995 break;
6999 torture_assert_werr_ok(tctx, r.out.result,
7000 "failed to call GetPrinterDriver2");
7002 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7004 if (info_p) {
7005 *info_p = *r.out.info;
7008 return true;
7011 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7012 struct dcerpc_binding_handle *b,
7013 struct policy_handle *handle,
7014 const char *driver_name,
7015 const char *architecture)
7017 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7018 int i;
7021 for (i=0;i<ARRAY_SIZE(levels);i++) {
7023 torture_assert(tctx,
7024 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7025 "");
7028 return true;
7031 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7032 void *private_data)
7034 struct test_spoolss_context *ctx =
7035 talloc_get_type_abort(private_data, struct test_spoolss_context);
7036 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7037 int i;
7038 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7039 struct dcerpc_binding_handle *b = p->binding_handle;
7040 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7042 for (i=0;i<ARRAY_SIZE(levels);i++) {
7044 uint32_t count;
7045 union spoolss_DriverInfo *info;
7047 torture_assert(tctx,
7048 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7049 "failed to enumerate drivers");
7051 if (!info) {
7052 torture_comment(tctx, "No printer drivers returned\n");
7053 break;
7057 return true;
7060 static bool test_DeletePrinter(struct torture_context *tctx,
7061 struct dcerpc_binding_handle *b,
7062 struct policy_handle *handle)
7064 struct spoolss_DeletePrinter r;
7066 torture_comment(tctx, "Testing DeletePrinter\n");
7068 r.in.handle = handle;
7070 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7071 "failed to delete printer");
7072 torture_assert_werr_ok(tctx, r.out.result,
7073 "failed to delete printer");
7075 return true;
7078 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7079 struct dcerpc_binding_handle *b,
7080 uint32_t flags,
7081 uint32_t level,
7082 const char *name,
7083 bool *found)
7085 struct spoolss_EnumPrinters e;
7086 uint32_t count;
7087 union spoolss_PrinterInfo *info;
7088 uint32_t needed;
7089 int i;
7091 *found = false;
7093 e.in.flags = flags;
7094 e.in.server = NULL;
7095 e.in.level = level;
7096 e.in.buffer = NULL;
7097 e.in.offered = 0;
7098 e.out.count = &count;
7099 e.out.info = &info;
7100 e.out.needed = &needed;
7102 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7103 "failed to enum printers");
7105 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7106 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7107 e.in.buffer = &blob;
7108 e.in.offered = needed;
7110 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7111 "failed to enum printers");
7114 torture_assert_werr_ok(tctx, e.out.result,
7115 "failed to enum printers");
7117 for (i=0; i < count; i++) {
7119 const char *current = NULL;
7120 const char *q;
7122 switch (level) {
7123 case 1:
7124 current = info[i].info1.name;
7125 break;
7128 if (strequal(current, name)) {
7129 *found = true;
7130 break;
7133 q = strrchr(current, '\\');
7134 if (q) {
7135 if (!e.in.server) {
7136 torture_warning(tctx,
7137 "server returns printername %s incl. servername although we did not set servername", current);
7139 q++;
7140 if (strequal(q, name)) {
7141 *found = true;
7142 break;
7147 return true;
7150 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7151 struct dcerpc_pipe *p,
7152 const char *printername,
7153 bool ex)
7155 WERROR result;
7156 struct spoolss_AddPrinter r;
7157 struct spoolss_AddPrinterEx rex;
7158 struct spoolss_SetPrinterInfoCtr info_ctr;
7159 struct spoolss_SetPrinterInfo1 info1;
7160 struct spoolss_DevmodeContainer devmode_ctr;
7161 struct sec_desc_buf secdesc_ctr;
7162 struct spoolss_UserLevelCtr userlevel_ctr;
7163 struct policy_handle handle;
7164 bool found = false;
7165 struct dcerpc_binding_handle *b = p->binding_handle;
7167 ZERO_STRUCT(devmode_ctr);
7168 ZERO_STRUCT(secdesc_ctr);
7169 ZERO_STRUCT(userlevel_ctr);
7170 ZERO_STRUCT(info1);
7172 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7173 ex ? "Ex":"", printername);
7175 /* try to add printer to wellknown printer list (level 1) */
7177 userlevel_ctr.level = 1;
7179 info_ctr.info.info1 = &info1;
7180 info_ctr.level = 1;
7182 rex.in.server = NULL;
7183 rex.in.info_ctr = &info_ctr;
7184 rex.in.devmode_ctr = &devmode_ctr;
7185 rex.in.secdesc_ctr = &secdesc_ctr;
7186 rex.in.userlevel_ctr = &userlevel_ctr;
7187 rex.out.handle = &handle;
7189 r.in.server = NULL;
7190 r.in.info_ctr = &info_ctr;
7191 r.in.devmode_ctr = &devmode_ctr;
7192 r.in.secdesc_ctr = &secdesc_ctr;
7193 r.out.handle = &handle;
7195 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7196 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7197 "failed to add printer");
7198 result = ex ? rex.out.result : r.out.result;
7199 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7200 "unexpected result code");
7202 info1.name = printername;
7203 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7205 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7206 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7207 "failed to add printer");
7208 result = ex ? rex.out.result : r.out.result;
7209 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7210 "unexpected result code");
7212 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7213 better do a real check to see the printer is really there */
7215 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7216 PRINTER_ENUM_NETWORK, 1,
7217 printername,
7218 &found),
7219 "failed to enum printers");
7221 torture_assert(tctx, found, "failed to find newly added printer");
7223 info1.flags = 0;
7225 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7226 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7227 "failed to add printer");
7228 result = ex ? rex.out.result : r.out.result;
7229 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7230 "unexpected result code");
7232 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7233 better do a real check to see the printer has really been removed
7234 from the well known printer list */
7236 found = false;
7238 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7239 PRINTER_ENUM_NETWORK, 1,
7240 printername,
7241 &found),
7242 "failed to enum printers");
7243 #if 0
7244 torture_assert(tctx, !found, "printer still in well known printer list");
7245 #endif
7246 return true;
7249 static bool test_AddPrinter_normal(struct torture_context *tctx,
7250 struct dcerpc_pipe *p,
7251 struct policy_handle *handle_p,
7252 const char *printername,
7253 const char *drivername,
7254 const char *portname,
7255 struct spoolss_DeviceMode *devmode,
7256 bool ex)
7258 WERROR result;
7259 struct spoolss_AddPrinter r;
7260 struct spoolss_AddPrinterEx rex;
7261 struct spoolss_SetPrinterInfoCtr info_ctr;
7262 struct spoolss_SetPrinterInfo2 info2;
7263 struct spoolss_DevmodeContainer devmode_ctr;
7264 struct sec_desc_buf secdesc_ctr;
7265 struct spoolss_UserLevelCtr userlevel_ctr;
7266 struct policy_handle handle;
7267 bool found = false;
7268 bool existing_printer_deleted = false;
7269 struct dcerpc_binding_handle *b = p->binding_handle;
7271 ZERO_STRUCT(devmode_ctr);
7272 ZERO_STRUCT(secdesc_ctr);
7273 ZERO_STRUCT(userlevel_ctr);
7275 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7276 ex ? "Ex":"", printername);
7278 devmode_ctr.devmode = devmode;
7280 userlevel_ctr.level = 1;
7282 rex.in.server = NULL;
7283 rex.in.info_ctr = &info_ctr;
7284 rex.in.devmode_ctr = &devmode_ctr;
7285 rex.in.secdesc_ctr = &secdesc_ctr;
7286 rex.in.userlevel_ctr = &userlevel_ctr;
7287 rex.out.handle = &handle;
7289 r.in.server = NULL;
7290 r.in.info_ctr = &info_ctr;
7291 r.in.devmode_ctr = &devmode_ctr;
7292 r.in.secdesc_ctr = &secdesc_ctr;
7293 r.out.handle = &handle;
7295 again:
7297 /* try to add printer to printer list (level 2) */
7299 ZERO_STRUCT(info2);
7301 info_ctr.info.info2 = &info2;
7302 info_ctr.level = 2;
7304 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7305 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7306 "failed to add printer");
7307 result = ex ? rex.out.result : r.out.result;
7308 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7309 "unexpected result code");
7311 info2.printername = printername;
7313 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7314 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7315 "failed to add printer");
7316 result = ex ? rex.out.result : r.out.result;
7318 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7319 struct policy_handle printer_handle;
7321 if (existing_printer_deleted) {
7322 torture_fail(tctx, "already deleted printer still existing?");
7325 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7326 "failed to open printer handle");
7328 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7329 "failed to delete printer");
7331 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7332 "failed to close server handle");
7334 existing_printer_deleted = true;
7336 goto again;
7339 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7340 "unexpected result code");
7342 info2.portname = portname;
7344 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7345 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7346 "failed to add printer");
7347 result = ex ? rex.out.result : r.out.result;
7348 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7349 "unexpected result code");
7351 info2.drivername = drivername;
7353 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7354 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7355 "failed to add printer");
7356 result = ex ? rex.out.result : r.out.result;
7358 /* w2k8r2 allows to add printer w/o defining printprocessor */
7360 if (!W_ERROR_IS_OK(result)) {
7361 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7362 "unexpected result code");
7364 info2.printprocessor = "winprint";
7366 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7367 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7368 "failed to add printer");
7369 result = ex ? rex.out.result : r.out.result;
7370 torture_assert_werr_ok(tctx, result,
7371 "failed to add printer");
7374 *handle_p = handle;
7376 /* we are paranoid, really check if the printer is there now */
7378 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7379 PRINTER_ENUM_LOCAL, 1,
7380 printername,
7381 &found),
7382 "failed to enum printers");
7383 torture_assert(tctx, found, "failed to find newly added printer");
7385 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7386 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7387 "failed to add printer");
7388 result = ex ? rex.out.result : r.out.result;
7389 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7390 "unexpected result code");
7392 return true;
7395 static bool test_printer_info(struct torture_context *tctx,
7396 void *private_data)
7398 struct torture_printer_context *t =
7399 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7400 struct dcerpc_pipe *p = t->spoolss_pipe;
7401 struct dcerpc_binding_handle *b = p->binding_handle;
7403 bool ret = true;
7405 if (torture_setting_bool(tctx, "samba3", false)) {
7406 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7409 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7410 ret = false;
7413 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7414 ret = false;
7417 return ret;
7420 static bool test_EnumPrinterKey(struct torture_context *tctx,
7421 struct dcerpc_binding_handle *b,
7422 struct policy_handle *handle,
7423 const char *key_name,
7424 const char ***array)
7426 struct spoolss_EnumPrinterKey r;
7427 uint32_t needed = 0;
7428 union spoolss_KeyNames key_buffer;
7429 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7430 uint32_t _ndr_size;
7431 int i;
7433 r.in.handle = handle;
7434 r.in.key_name = key_name;
7435 r.out.key_buffer = &key_buffer;
7436 r.out.needed = &needed;
7437 r.out._ndr_size = &_ndr_size;
7439 for (i=0; i < ARRAY_SIZE(offered); i++) {
7441 if (offered[i] < 0 && needed) {
7442 if (needed <= 4) {
7443 continue;
7445 r.in.offered = needed + offered[i];
7446 } else {
7447 r.in.offered = offered[i];
7450 ZERO_STRUCT(key_buffer);
7452 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7454 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7455 "failed to call EnumPrinterKey");
7456 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7458 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7459 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7460 _ndr_size, r.in.offered/2));
7462 r.in.offered = needed;
7463 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7464 "failed to call EnumPrinterKey");
7467 if (offered[i] > 0) {
7468 torture_assert_werr_ok(tctx, r.out.result,
7469 "failed to call EnumPrinterKey");
7472 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7473 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7474 _ndr_size, r.in.offered/2));
7476 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7477 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7479 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7480 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7482 if (key_buffer.string_array) {
7483 uint32_t calc_needed = 0;
7484 int s;
7485 for (s=0; key_buffer.string_array[s]; s++) {
7486 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7488 if (!key_buffer.string_array[0]) {
7489 calc_needed += 2;
7491 calc_needed += 2;
7493 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7494 "EnumPrinterKey unexpected size");
7498 if (array) {
7499 *array = key_buffer.string_array;
7502 return true;
7505 bool test_printer_all_keys(struct torture_context *tctx,
7506 struct dcerpc_binding_handle *b,
7507 struct policy_handle *handle)
7509 const char **key_array = NULL;
7510 int i;
7512 torture_comment(tctx, "Testing Printer Keys\n");
7514 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7515 "failed to call test_EnumPrinterKey");
7517 for (i=0; key_array && key_array[i]; i++) {
7518 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7519 "failed to call test_EnumPrinterKey");
7521 for (i=0; key_array && key_array[i]; i++) {
7522 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7523 "failed to call test_EnumPrinterDataEx");
7526 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7528 return true;
7531 static bool test_openprinter_wrap(struct torture_context *tctx,
7532 void *private_data)
7534 struct torture_printer_context *t =
7535 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7536 struct dcerpc_pipe *p = t->spoolss_pipe;
7537 struct dcerpc_binding_handle *b = p->binding_handle;
7538 const char *printername = t->info2.printername;
7540 return test_openprinter(tctx, b, printername);
7543 static bool test_csetprinter(struct torture_context *tctx,
7544 void *private_data)
7546 struct torture_printer_context *t =
7547 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7548 struct dcerpc_pipe *p = t->spoolss_pipe;
7550 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7551 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7552 const char *portname = t->info2.portname;
7554 union spoolss_PrinterInfo info;
7555 struct policy_handle new_handle, new_handle2;
7556 struct dcerpc_binding_handle *b = p->binding_handle;
7558 torture_comment(tctx, "Testing c_setprinter\n");
7560 torture_assert(tctx,
7561 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7562 "failed to get level 0 printer info");
7563 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7564 info.info0.c_setprinter);
7566 /* check if c_setprinter on 1st handle increases after a printer has
7567 * been added */
7569 torture_assert(tctx,
7570 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7571 "failed to add new printer");
7572 torture_assert(tctx,
7573 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7574 "failed to get level 0 printer info");
7575 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7576 info.info0.c_setprinter);
7578 /* check if c_setprinter on new handle increases after a printer has
7579 * been added */
7581 torture_assert(tctx,
7582 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7583 "failed to get level 0 printer info");
7584 torture_comment(tctx, "csetprinter on created handle: %d\n",
7585 info.info0.c_setprinter);
7587 /* open the new printer and check if c_setprinter increases */
7589 torture_assert(tctx,
7590 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7591 "failed to open created printer");
7592 torture_assert(tctx,
7593 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7594 "failed to get level 0 printer info");
7595 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7596 info.info0.c_setprinter);
7598 /* cleanup */
7600 torture_assert(tctx,
7601 test_ClosePrinter(tctx, b, &new_handle2),
7602 "failed to close printer");
7603 torture_assert(tctx,
7604 test_DeletePrinter(tctx, b, &new_handle),
7605 "failed to delete new printer");
7607 return true;
7610 static bool compose_local_driver_directory(struct torture_context *tctx,
7611 const char *environment,
7612 const char *local_dir,
7613 const char **path)
7615 char *p;
7617 p = strrchr(local_dir, '/');
7618 if (!p) {
7619 return NULL;
7621 p++;
7623 if (strequal(environment, "Windows x64")) {
7624 if (!strequal(p, "x64")) {
7625 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7627 } else if (strequal(environment, "Windows NT x86")) {
7628 if (!strequal(p, "i386")) {
7629 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7631 } else {
7632 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7635 return true;
7638 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7639 const char *devicename)
7641 struct spoolss_DeviceMode *r;
7643 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7644 if (r == NULL) {
7645 return NULL;
7648 r->devicename = talloc_strdup(r, devicename);
7649 r->specversion = DMSPEC_NT4_AND_ABOVE;
7650 r->driverversion = 0x0600;
7651 r->size = 0x00dc;
7652 r->__driverextra_length = 0;
7653 r->fields = DEVMODE_FORMNAME |
7654 DEVMODE_TTOPTION |
7655 DEVMODE_PRINTQUALITY |
7656 DEVMODE_DEFAULTSOURCE |
7657 DEVMODE_COPIES |
7658 DEVMODE_SCALE |
7659 DEVMODE_PAPERSIZE |
7660 DEVMODE_ORIENTATION;
7661 r->orientation = DMORIENT_PORTRAIT;
7662 r->papersize = DMPAPER_LETTER;
7663 r->paperlength = 0;
7664 r->paperwidth = 0;
7665 r->scale = 100;
7666 r->copies = 55;
7667 r->defaultsource = DMBIN_FORMSOURCE;
7668 r->printquality = DMRES_HIGH;
7669 r->color = DMRES_MONOCHROME;
7670 r->duplex = DMDUP_SIMPLEX;
7671 r->yresolution = 0;
7672 r->ttoption = DMTT_SUBDEV;
7673 r->collate = DMCOLLATE_FALSE;
7674 r->formname = talloc_strdup(r, "Letter");
7676 return r;
7679 static bool test_architecture_buffer(struct torture_context *tctx,
7680 void *private_data)
7682 struct test_spoolss_context *ctx =
7683 talloc_get_type_abort(private_data, struct test_spoolss_context);
7685 struct spoolss_OpenPrinterEx r;
7686 struct spoolss_UserLevel1 u1;
7687 struct policy_handle handle;
7688 uint32_t architectures[] = {
7689 PROCESSOR_ARCHITECTURE_INTEL,
7690 PROCESSOR_ARCHITECTURE_IA64,
7691 PROCESSOR_ARCHITECTURE_AMD64
7693 uint32_t needed[3];
7694 int i;
7695 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7696 struct dcerpc_binding_handle *b = p->binding_handle;
7698 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7700 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7702 u1.size = 0;
7703 u1.client = NULL;
7704 u1.user = NULL;
7705 u1.build = 0;
7706 u1.major = 3;
7707 u1.minor = 0;
7708 u1.processor = architectures[i];
7710 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7711 r.in.datatype = NULL;
7712 r.in.devmode_ctr.devmode= NULL;
7713 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7714 r.in.userlevel_ctr.level = 1;
7715 r.in.userlevel_ctr.user_info.level1 = &u1;
7716 r.out.handle = &handle;
7718 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7719 torture_assert_werr_ok(tctx, r.out.result, "");
7722 struct spoolss_EnumPrinters e;
7723 uint32_t count;
7724 union spoolss_PrinterInfo *info;
7726 e.in.flags = PRINTER_ENUM_LOCAL;
7727 e.in.server = NULL;
7728 e.in.level = 2;
7729 e.in.buffer = NULL;
7730 e.in.offered = 0;
7731 e.out.count = &count;
7732 e.out.info = &info;
7733 e.out.needed = &needed[i];
7735 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7736 #if 0
7737 torture_comment(tctx, "needed was %d\n", needed[i]);
7738 #endif
7741 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7744 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7745 if (needed[i-1] != needed[i]) {
7746 torture_fail(tctx,
7747 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7748 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7752 return true;
7755 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7756 void *private_data)
7758 struct test_spoolss_context *ctx =
7759 talloc_get_type_abort(private_data, struct test_spoolss_context);
7760 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7761 struct dcerpc_binding_handle *b = p->binding_handle;
7763 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7766 static bool test_PrintServer_Forms(struct torture_context *tctx,
7767 void *private_data)
7769 struct test_spoolss_context *ctx =
7770 talloc_get_type_abort(private_data, struct test_spoolss_context);
7771 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7772 struct dcerpc_binding_handle *b = p->binding_handle;
7774 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7777 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7778 void *private_data)
7780 struct test_spoolss_context *ctx =
7781 talloc_get_type_abort(private_data, struct test_spoolss_context);
7782 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7783 struct dcerpc_binding_handle *b = p->binding_handle;
7785 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7788 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7790 NTSTATUS status;
7792 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7794 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7796 torture_assert(tctx,
7797 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7798 "failed to open printserver");
7799 torture_assert(tctx,
7800 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7801 "failed to get environment");
7803 return true;
7806 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7808 struct test_spoolss_context *t;
7810 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7812 return torture_rpc_spoolss_setup_common(tctx, t);
7815 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7817 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7819 return true;
7822 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7824 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7825 bool ret;
7827 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7828 talloc_free(t);
7830 return ret;
7833 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7835 struct dcerpc_pipe *p;
7836 struct dcerpc_binding_handle *b;
7837 const char *server_name_slash;
7838 const char *driver_name;
7839 const char *printer_name;
7840 const char *port_name;
7842 torture_assert_ntstatus_ok(tctx,
7843 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7844 "Error connecting to server");
7846 p = t->spoolss_pipe;
7847 b = p->binding_handle;
7848 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7850 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7851 t->driver.info8.driver_name = TORTURE_DRIVER;
7852 t->driver.info8.driver_path = "pscript5.dll";
7853 t->driver.info8.data_file = "cups6.ppd";
7854 t->driver.info8.config_file = "ps5ui.dll";
7855 t->driver.info8.help_file = "pscript.hlp";
7856 t->driver.info8.default_datatype = "RAW";
7857 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7858 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7859 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7860 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7861 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7862 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7863 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7864 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7865 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7866 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7868 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7870 t->info2.portname = "LPT1:";
7872 printer_name = t->info2.printername;
7873 port_name = t->info2.portname;
7875 torture_assert(tctx,
7876 fillup_printserver_info(tctx, p, &t->driver),
7877 "failed to fillup printserver info");
7879 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7881 torture_assert(tctx,
7882 compose_local_driver_directory(tctx, t->driver.remote.environment,
7883 t->driver.local.driver_directory,
7884 &t->driver.local.driver_directory),
7885 "failed to compose local driver directory");
7887 t->info2.drivername = "Microsoft XPS Document Writer";
7889 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7890 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7891 t->info2.drivername, t->driver.remote.environment);
7892 t->have_driver = true;
7893 goto try_add;
7896 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7897 t->info2.drivername, t->driver.remote.environment);
7899 t->info2.drivername = "Microsoft XPS Document Writer v4";
7901 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7902 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
7903 t->info2.drivername, t->driver.remote.environment);
7904 t->have_driver = true;
7905 goto try_add;
7908 torture_comment(tctx, "trying to upload own driver\n");
7910 if (!directory_exist(t->driver.local.driver_directory)) {
7911 torture_warning(tctx, "no local driver is available!");
7912 t->have_driver = false;
7913 goto try_add;
7916 torture_assert(tctx,
7917 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7918 "failed to upload printer driver");
7920 torture_assert(tctx,
7921 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7922 "failed to add driver");
7924 t->added_driver = true;
7925 t->have_driver = true;
7927 try_add:
7928 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7930 if (t->wellknown) {
7931 torture_assert(tctx,
7932 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7933 "failed to add wellknown printer");
7934 } else {
7935 torture_assert(tctx,
7936 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7937 "failed to add printer");
7940 return true;
7943 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7945 struct torture_printer_context *t;
7947 *data = t = talloc_zero(tctx, struct torture_printer_context);
7949 t->ex = false;
7950 t->wellknown = false;
7951 t->info2.printername = TORTURE_PRINTER;
7952 t->devmode = NULL;
7954 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7957 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7959 struct torture_printer_context *t;
7961 *data = t = talloc_zero(tctx, struct torture_printer_context);
7963 t->ex = true;
7964 t->wellknown = false;
7965 t->info2.printername = TORTURE_PRINTER_EX;
7966 t->devmode = NULL;
7968 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7971 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7973 struct torture_printer_context *t;
7975 *data = t = talloc_zero(tctx, struct torture_printer_context);
7977 t->ex = false;
7978 t->wellknown = true;
7979 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7980 t->devmode = NULL;
7982 /* FIXME */
7983 if (t->wellknown) {
7984 torture_skip(tctx, "skipping AddPrinter level 1");
7987 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7990 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7992 struct torture_printer_context *t;
7994 *data = t = talloc_zero(tctx, struct torture_printer_context);
7996 t->ex = true;
7997 t->wellknown = true;
7998 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7999 t->devmode = NULL;
8001 /* FIXME */
8002 if (t->wellknown) {
8003 torture_skip(tctx, "skipping AddPrinterEx level 1");
8006 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8009 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8011 struct torture_printer_context *t;
8013 *data = t = talloc_zero(tctx, struct torture_printer_context);
8015 t->ex = true;
8016 t->wellknown = false;
8017 t->info2.printername = TORTURE_PRINTER_EX;
8018 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8020 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8023 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8025 bool found = false;
8026 struct dcerpc_pipe *p = t->spoolss_pipe;
8027 struct dcerpc_binding_handle *b;
8028 const char *printer_name = t->info2.printername;
8030 if (t->added_driver) {
8031 torture_assert(tctx,
8032 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8033 "failed to remove printer driver");
8036 if (p && !t->wellknown) {
8037 b = p->binding_handle;
8039 torture_assert(tctx,
8040 test_DeletePrinter(tctx, b, &t->handle),
8041 "failed to delete printer");
8043 torture_assert(tctx,
8044 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8045 printer_name, &found),
8046 "failed to enumerate printers");
8048 torture_assert(tctx, !found, "deleted printer still there");
8051 return true;
8054 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8056 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8057 bool ret;
8059 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8060 talloc_free(t);
8062 return ret;
8065 static bool test_print_test(struct torture_context *tctx,
8066 void *private_data)
8068 struct torture_printer_context *t =
8069 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8070 struct dcerpc_pipe *p = t->spoolss_pipe;
8071 struct dcerpc_binding_handle *b = p->binding_handle;
8073 torture_assert(tctx,
8074 test_PausePrinter(tctx, b, &t->handle),
8075 "failed to pause printer");
8077 torture_assert(tctx,
8078 test_DoPrintTest(tctx, b, &t->handle),
8079 "failed to do print test");
8081 torture_assert(tctx,
8082 test_ResumePrinter(tctx, b, &t->handle),
8083 "failed to resume printer");
8085 return true;
8088 static bool test_print_test_extended(struct torture_context *tctx,
8089 void *private_data)
8091 struct torture_printer_context *t =
8092 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8093 struct dcerpc_pipe *p = t->spoolss_pipe;
8094 struct dcerpc_binding_handle *b = p->binding_handle;
8095 bool ret = true;
8097 torture_assert(tctx,
8098 test_PausePrinter(tctx, b, &t->handle),
8099 "failed to pause printer");
8101 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8102 if (ret == false) {
8103 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8104 if (torture_setting_bool(tctx, "samba3", false)) {
8105 torture_comment(tctx, "non-critical for samba3\n");
8106 ret = true;
8107 tctx->last_result = TORTURE_SKIP;
8111 torture_assert(tctx,
8112 test_ResumePrinter(tctx, b, &t->handle),
8113 "failed to resume printer");
8115 return ret;
8118 static bool test_print_test_properties(struct torture_context *tctx,
8119 void *private_data)
8121 struct torture_printer_context *t =
8122 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8123 struct dcerpc_pipe *p = t->spoolss_pipe;
8124 struct dcerpc_binding_handle *b = p->binding_handle;
8126 if (torture_setting_bool(tctx, "samba3", false)) {
8127 torture_skip(tctx, "skip printer job property tests against samba");
8130 torture_assert(tctx,
8131 test_PausePrinter(tctx, b, &t->handle),
8132 "failed to pause printer");
8134 torture_assert(tctx,
8135 test_DoPrintTest_properties(tctx, b, &t->handle),
8136 "failed to test print job properties");
8138 torture_assert(tctx,
8139 test_ResumePrinter(tctx, b, &t->handle),
8140 "failed to resume printer");
8142 return true;
8145 /* use smbd file IO to spool a print job */
8146 static bool test_print_test_smbd(struct torture_context *tctx,
8147 void *private_data)
8149 struct torture_printer_context *t =
8150 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8151 struct dcerpc_pipe *p = t->spoolss_pipe;
8152 struct dcerpc_binding_handle *b = p->binding_handle;
8153 NTSTATUS status;
8154 uint32_t count;
8155 union spoolss_JobInfo *info = NULL;
8156 int i;
8158 struct smb2_tree *tree;
8159 struct smb2_handle job_h;
8160 struct cli_credentials *credentials = cmdline_credentials;
8161 struct smbcli_options options;
8162 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8164 * Do not test against the dynamically added printers, printing via
8165 * smbd means that a different spoolss process may handle the
8166 * OpenPrinter request to the one that handled the AddPrinter request.
8167 * This currently leads to an ugly race condition where one process
8168 * sees the new printer and one doesn't.
8170 const char *share = TORTURE_PRINTER_STATIC1;
8172 torture_comment(tctx, "Testing smbd job spooling\n");
8173 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8175 status = smb2_connect_ext(mem_ctx,
8176 torture_setting_string(tctx, "host", NULL),
8177 lpcfg_smb_ports(tctx->lp_ctx),
8178 share,
8179 lpcfg_resolve_context(tctx->lp_ctx),
8180 credentials,
8182 &tree,
8183 tctx->ev,
8184 &options,
8185 lpcfg_socket_options(tctx->lp_ctx),
8186 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8187 if (!NT_STATUS_IS_OK(status)) {
8188 printf("Failed to connect to SMB2 printer %s - %s\n",
8189 share, nt_errstr(status));
8190 return false;
8193 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8194 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8196 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8197 sizeof("exciting print job data"));
8198 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8200 /* check back end spoolss job was created */
8201 torture_assert(tctx,
8202 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8203 "EnumJobs level 1 failed");
8205 for (i = 0; i < count; i++) {
8206 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8207 break;
8210 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8212 status = smb2_util_close(tree, job_h);
8213 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8215 /* disconnect from printer share */
8216 talloc_free(mem_ctx);
8218 return true;
8221 static bool test_printer_sd(struct torture_context *tctx,
8222 void *private_data)
8224 struct torture_printer_context *t =
8225 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8226 struct dcerpc_pipe *p = t->spoolss_pipe;
8227 struct dcerpc_binding_handle *b = p->binding_handle;
8229 torture_assert(tctx,
8230 test_PrinterInfo_SD(tctx, b, &t->handle),
8231 "failed to test security descriptors");
8233 return true;
8236 static bool test_printer_dm(struct torture_context *tctx,
8237 void *private_data)
8239 struct torture_printer_context *t =
8240 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8241 struct dcerpc_pipe *p = t->spoolss_pipe;
8243 torture_assert(tctx,
8244 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8245 "failed to test devicemodes");
8247 return true;
8250 static bool test_printer_info_winreg(struct torture_context *tctx,
8251 void *private_data)
8253 struct torture_printer_context *t =
8254 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8255 struct dcerpc_pipe *p = t->spoolss_pipe;
8257 torture_assert(tctx,
8258 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8259 "failed to test printer info winreg");
8261 return true;
8264 static bool test_printer_change_id(struct torture_context *tctx,
8265 void *private_data)
8267 struct torture_printer_context *t =
8268 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8269 struct dcerpc_pipe *p = t->spoolss_pipe;
8271 torture_assert(tctx,
8272 test_ChangeID(tctx, p, &t->handle),
8273 "failed to test change id");
8275 return true;
8278 static bool test_printer_keys(struct torture_context *tctx,
8279 void *private_data)
8281 struct torture_printer_context *t =
8282 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8283 struct dcerpc_pipe *p = t->spoolss_pipe;
8284 struct dcerpc_binding_handle *b = p->binding_handle;
8286 torture_assert(tctx,
8287 test_printer_all_keys(tctx, b, &t->handle),
8288 "failed to test printer keys");
8290 return true;
8293 static bool test_printer_data_consistency(struct torture_context *tctx,
8294 void *private_data)
8296 struct torture_printer_context *t =
8297 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8298 struct dcerpc_pipe *p = t->spoolss_pipe;
8300 torture_assert(tctx,
8301 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8302 "failed to test printer data consistency");
8304 return true;
8307 static bool test_printer_data_keys(struct torture_context *tctx,
8308 void *private_data)
8310 struct torture_printer_context *t =
8311 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8312 struct dcerpc_pipe *p = t->spoolss_pipe;
8314 torture_assert(tctx,
8315 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8316 "failed to test printer data keys");
8318 return true;
8321 static bool test_printer_data_values(struct torture_context *tctx,
8322 void *private_data)
8324 struct torture_printer_context *t =
8325 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8326 struct dcerpc_pipe *p = t->spoolss_pipe;
8328 torture_assert(tctx,
8329 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8330 "failed to test printer data values");
8332 return true;
8335 static bool test_printer_data_set(struct torture_context *tctx,
8336 void *private_data)
8338 struct torture_printer_context *t =
8339 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8340 struct dcerpc_pipe *p = t->spoolss_pipe;
8342 torture_assert(tctx,
8343 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8344 "failed to test printer data set");
8346 return true;
8349 static bool test_printer_data_winreg(struct torture_context *tctx,
8350 void *private_data)
8352 struct torture_printer_context *t =
8353 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8354 struct dcerpc_pipe *p = t->spoolss_pipe;
8356 torture_assert(tctx,
8357 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8358 "failed to test printer data winreg");
8360 return true;
8363 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8364 void *private_data)
8366 struct torture_printer_context *t =
8367 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8368 struct dcerpc_pipe *p = t->spoolss_pipe;
8370 torture_assert(tctx,
8371 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8372 "failed to test printer data winreg dsspooler");
8374 return true;
8377 static bool test_printer_ic(struct torture_context *tctx,
8378 void *private_data)
8380 struct torture_printer_context *t =
8381 talloc_get_type_abort(private_data,
8382 struct torture_printer_context);
8383 struct dcerpc_pipe *p = t->spoolss_pipe;
8384 struct dcerpc_binding_handle *b = p->binding_handle;
8385 struct policy_handle gdi_handle;
8387 if (torture_setting_bool(tctx, "samba3", false)) {
8388 torture_skip(tctx, "skip printer information context tests against samba");
8392 struct spoolss_CreatePrinterIC r;
8393 struct spoolss_DevmodeContainer devmode_ctr;
8395 ZERO_STRUCT(devmode_ctr);
8397 r.in.handle = &t->handle;
8398 r.in.devmode_ctr = &devmode_ctr;
8399 r.out.gdi_handle = &gdi_handle;
8401 torture_assert_ntstatus_ok(tctx,
8402 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8403 "CreatePrinterIC failed");
8404 torture_assert_werr_ok(tctx, r.out.result,
8405 "CreatePrinterIC failed");
8409 struct spoolss_PlayGDIScriptOnPrinterIC r;
8410 DATA_BLOB in,out;
8411 int i;
8412 uint32_t num_fonts = 0;
8414 in = data_blob_string_const("");
8416 r.in.gdi_handle = &gdi_handle;
8417 r.in.pIn = in.data;
8418 r.in.cIn = in.length;
8419 r.in.ul = 0;
8421 for (i = 0; i < 4; i++) {
8423 out = data_blob_talloc_zero(tctx, i);
8425 r.in.cOut = out.length;
8426 r.out.pOut = out.data;
8428 torture_assert_ntstatus_ok(tctx,
8429 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8430 "PlayGDIScriptOnPrinterIC failed");
8431 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8432 "PlayGDIScriptOnPrinterIC failed");
8435 out = data_blob_talloc_zero(tctx, 4);
8437 r.in.cOut = out.length;
8438 r.out.pOut = out.data;
8440 torture_assert_ntstatus_ok(tctx,
8441 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8442 "PlayGDIScriptOnPrinterIC failed");
8443 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8444 "PlayGDIScriptOnPrinterIC failed");
8446 /* now we should have the required length, so retry with a
8447 * buffer which is large enough to carry all font ids */
8449 num_fonts = IVAL(r.out.pOut, 0);
8451 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8453 out = data_blob_talloc_zero(tctx,
8454 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8456 r.in.cOut = out.length;
8457 r.out.pOut = out.data;
8459 torture_assert_ntstatus_ok(tctx,
8460 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8461 "PlayGDIScriptOnPrinterIC failed");
8462 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8463 "PlayGDIScriptOnPrinterIC failed");
8468 struct spoolss_DeletePrinterIC r;
8470 r.in.gdi_handle = &gdi_handle;
8471 r.out.gdi_handle = &gdi_handle;
8473 torture_assert_ntstatus_ok(tctx,
8474 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8475 "DeletePrinterIC failed");
8476 torture_assert_werr_ok(tctx, r.out.result,
8477 "DeletePrinterIC failed");
8481 return true;
8484 static bool test_printer_bidi(struct torture_context *tctx,
8485 void *private_data)
8487 struct torture_printer_context *t =
8488 talloc_get_type_abort(private_data,
8489 struct torture_printer_context);
8490 struct dcerpc_pipe *p = t->spoolss_pipe;
8491 struct dcerpc_binding_handle *b = p->binding_handle;
8492 struct spoolss_RpcSendRecvBidiData r;
8493 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8494 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8496 if (torture_setting_bool(tctx, "samba3", false)) {
8497 torture_skip(tctx, "skip printer bidirectional tests against samba");
8500 ZERO_STRUCT(bidi_req);
8502 r.in.hPrinter = t->handle;
8503 r.in.pAction = "foobar";
8504 r.in.pReqData = &bidi_req;
8505 r.out.ppRespData = &bidi_rep;
8507 torture_assert_ntstatus_ok(tctx,
8508 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8509 "RpcSendRecvBidiData failed");
8510 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8511 "RpcSendRecvBidiData failed");
8513 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8514 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8517 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8519 torture_assert_ntstatus_ok(tctx,
8520 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8521 "RpcSendRecvBidiData failed");
8522 torture_assert_werr_ok(tctx, r.out.result,
8523 "RpcSendRecvBidiData failed");
8525 return true;
8528 static bool test_driver_info_winreg(struct torture_context *tctx,
8529 void *private_data)
8531 struct torture_printer_context *t =
8532 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8533 struct dcerpc_pipe *p = t->spoolss_pipe;
8534 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8536 if (!t->have_driver) {
8537 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8540 torture_assert(tctx,
8541 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8542 "failed to test driver info winreg");
8544 return true;
8547 void torture_tcase_printer(struct torture_tcase *tcase)
8549 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8550 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8551 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8552 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8553 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8554 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8555 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8556 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8557 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8558 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8559 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8560 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8561 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8562 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8563 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8564 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8565 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8566 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8567 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8568 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8569 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8570 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
8573 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8575 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8576 struct torture_tcase *tcase;
8578 tcase = torture_suite_add_tcase(suite, "addprinter");
8580 torture_tcase_set_fixture(tcase,
8581 torture_rpc_spoolss_printer_setup,
8582 torture_rpc_spoolss_printer_teardown);
8584 torture_tcase_printer(tcase);
8586 tcase = torture_suite_add_tcase(suite, "addprinterex");
8588 torture_tcase_set_fixture(tcase,
8589 torture_rpc_spoolss_printerex_setup,
8590 torture_rpc_spoolss_printer_teardown);
8592 torture_tcase_printer(tcase);
8594 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8596 torture_tcase_set_fixture(tcase,
8597 torture_rpc_spoolss_printerwkn_setup,
8598 torture_rpc_spoolss_printer_teardown);
8600 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8602 torture_tcase_set_fixture(tcase,
8603 torture_rpc_spoolss_printerexwkn_setup,
8604 torture_rpc_spoolss_printer_teardown);
8606 #if 0
8607 /* test is not correct */
8608 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8610 torture_tcase_set_fixture(tcase,
8611 torture_rpc_spoolss_printerdm_setup,
8612 torture_rpc_spoolss_printer_teardown);
8614 torture_tcase_printer(tcase);
8615 #endif
8616 return suite;
8619 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8621 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8622 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8624 torture_tcase_set_fixture(tcase,
8625 torture_rpc_spoolss_setup,
8626 torture_rpc_spoolss_teardown);
8628 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8629 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8630 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8631 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8632 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8633 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8634 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8635 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8636 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8637 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8638 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8639 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8640 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8641 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
8642 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8643 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8644 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8645 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8646 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8647 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8648 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8650 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8652 return suite;
8655 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8656 struct dcerpc_binding_handle *b,
8657 const char *server,
8658 const char *environment,
8659 const char **dir_p)
8661 struct spoolss_GetPrinterDriverDirectory r;
8662 uint32_t needed;
8664 r.in.server = server;
8665 r.in.environment = environment;
8666 r.in.level = 1;
8667 r.in.buffer = NULL;
8668 r.in.offered = 0;
8669 r.out.needed = &needed;
8671 torture_assert_ntstatus_ok(tctx,
8672 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8673 "failed to query driver directory");
8675 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8676 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8677 r.in.buffer = &blob;
8678 r.in.offered = needed;
8680 torture_assert_ntstatus_ok(tctx,
8681 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8682 "failed to query driver directory");
8685 torture_assert_werr_ok(tctx, r.out.result,
8686 "failed to query driver directory");
8688 if (dir_p) {
8689 *dir_p = r.out.info->info1.directory_name;
8692 return true;
8695 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8697 if (info_ctr == NULL) {
8698 return NULL;
8701 switch (info_ctr->level) {
8702 case 1:
8703 return info_ctr->info.info1->driver_name;
8704 case 2:
8705 return info_ctr->info.info2->driver_name;
8706 case 3:
8707 return info_ctr->info.info3->driver_name;
8708 case 4:
8709 return info_ctr->info.info4->driver_name;
8710 case 6:
8711 return info_ctr->info.info6->driver_name;
8712 case 8:
8713 return info_ctr->info.info8->driver_name;
8714 default:
8715 return NULL;
8719 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8721 if (info_ctr == NULL) {
8722 return NULL;
8725 switch (info_ctr->level) {
8726 case 2:
8727 return info_ctr->info.info2->architecture;
8728 case 3:
8729 return info_ctr->info.info3->architecture;
8730 case 4:
8731 return info_ctr->info.info4->architecture;
8732 case 6:
8733 return info_ctr->info.info6->architecture;
8734 case 8:
8735 return info_ctr->info.info8->architecture;
8736 default:
8737 return NULL;
8742 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8743 struct dcerpc_binding_handle *b,
8744 const char *servername,
8745 struct spoolss_AddDriverInfoCtr *info_ctr,
8746 WERROR expected_result)
8748 struct spoolss_AddPrinterDriver r;
8749 const char *drivername = get_driver_from_info(info_ctr);
8750 const char *environment = get_environment_from_info(info_ctr);
8752 r.in.servername = servername;
8753 r.in.info_ctr = info_ctr;
8755 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8756 drivername, info_ctr->level, environment);
8758 torture_assert_ntstatus_ok(tctx,
8759 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8760 "spoolss_AddPrinterDriver failed");
8761 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8762 "spoolss_AddPrinterDriver failed with unexpected result");
8764 return true;
8768 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8769 struct dcerpc_binding_handle *b,
8770 const char *servername,
8771 struct spoolss_AddDriverInfoCtr *info_ctr,
8772 uint32_t flags,
8773 WERROR expected_result)
8775 struct spoolss_AddPrinterDriverEx r;
8776 const char *drivername = get_driver_from_info(info_ctr);
8777 const char *environment = get_environment_from_info(info_ctr);
8779 r.in.servername = servername;
8780 r.in.info_ctr = info_ctr;
8781 r.in.flags = flags;
8783 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8784 drivername, info_ctr->level, environment);
8786 torture_assert_ntstatus_ok(tctx,
8787 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8788 "AddPrinterDriverEx failed");
8789 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8790 "AddPrinterDriverEx failed with unexpected result");
8792 return true;
8795 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8796 if (path && strlen(path)) {\
8797 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8800 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8801 struct dcerpc_binding_handle *b,
8802 const char *server_name,
8803 struct spoolss_AddDriverInfo8 *r,
8804 uint32_t flags,
8805 bool ex,
8806 const char *remote_driver_dir)
8808 struct spoolss_AddDriverInfoCtr info_ctr;
8809 struct spoolss_AddDriverInfo1 info1;
8811 ZERO_STRUCT(info1);
8813 info_ctr.level = 1;
8814 info_ctr.info.info1 = &info1;
8816 if (ex) {
8817 torture_assert(tctx,
8818 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8819 "failed to test AddPrinterDriverEx level 1");
8820 } else {
8821 torture_assert(tctx,
8822 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8823 "failed to test AddPrinterDriver level 1");
8826 info1.driver_name = r->driver_name;
8828 if (ex) {
8829 torture_assert(tctx,
8830 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8831 "failed to test AddPrinterDriverEx level 1");
8832 } else {
8833 torture_assert(tctx,
8834 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8835 "failed to test AddPrinterDriver level 1");
8838 return true;
8841 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8842 struct dcerpc_binding_handle *b,
8843 const char *server_name,
8844 struct spoolss_AddDriverInfo8 *r,
8845 uint32_t flags,
8846 bool ex,
8847 const char *remote_driver_dir)
8849 struct spoolss_AddDriverInfoCtr info_ctr;
8850 struct spoolss_AddDriverInfo2 info2;
8851 union spoolss_DriverInfo info;
8853 ZERO_STRUCT(info2);
8855 info_ctr.level = 2;
8856 info_ctr.info.info2 = &info2;
8858 if (ex) {
8859 torture_assert(tctx,
8860 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8861 "failed to test AddPrinterDriverEx level 2");
8862 } else {
8863 torture_assert(tctx,
8864 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8865 "failed to test AddPrinterDriver level 2");
8868 info2.driver_name = r->driver_name;
8870 if (ex) {
8871 torture_assert(tctx,
8872 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8873 "failed to test AddPrinterDriverEx level 2");
8874 } else {
8875 torture_assert(tctx,
8876 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8877 "failed to test AddPrinterDriver level 2");
8880 info2.version = r->version;
8882 if (ex) {
8883 torture_assert(tctx,
8884 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8885 "failed to test AddPrinterDriverEx level 2");
8886 } else {
8887 torture_assert(tctx,
8888 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8889 "failed to test AddPrinterDriver level 2");
8892 info2.architecture = r->architecture;
8894 if (ex) {
8895 torture_assert(tctx,
8896 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8897 "failed to test AddPrinterDriverEx level 2");
8898 } else {
8899 torture_assert(tctx,
8900 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8901 "failed to test AddPrinterDriver level 2");
8904 info2.driver_path = r->driver_path;
8906 if (ex) {
8907 torture_assert(tctx,
8908 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8909 "failed to test AddPrinterDriverEx level 2");
8910 } else {
8911 torture_assert(tctx,
8912 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8913 "failed to test AddPrinterDriver level 2");
8916 info2.data_file = r->data_file;
8918 if (ex) {
8919 torture_assert(tctx,
8920 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8921 "failed to test AddPrinterDriverEx level 2");
8922 } else {
8923 torture_assert(tctx,
8924 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8925 "failed to test AddPrinterDriver level 2");
8928 info2.config_file = r->config_file;
8930 if (ex) {
8931 torture_assert(tctx,
8932 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8933 "failed to test AddPrinterDriverEx");
8936 if (ex) {
8937 torture_assert(tctx,
8938 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8939 "failed to test AddPrinterDriverEx level 2");
8940 } else {
8941 torture_assert(tctx,
8942 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8943 "failed to test AddPrinterDriver level 2");
8946 torture_assert(tctx,
8947 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8948 "failed to find added printer driver");
8950 if (remote_driver_dir) {
8951 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8952 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8953 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8956 return true;
8959 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8960 struct dcerpc_binding_handle *b,
8961 const char *server_name,
8962 struct spoolss_AddDriverInfo8 *r,
8963 uint32_t flags,
8964 bool ex,
8965 const char *remote_driver_dir)
8967 struct spoolss_AddDriverInfoCtr info_ctr;
8968 struct spoolss_AddDriverInfo3 info3;
8969 union spoolss_DriverInfo info;
8971 info3.driver_name = r->driver_name;
8972 info3.version = r->version;
8973 info3.architecture = r->architecture;
8974 info3.driver_path = r->driver_path;
8975 info3.data_file = r->data_file;
8976 info3.config_file = r->config_file;
8977 info3.help_file = r->help_file;
8978 info3.monitor_name = r->monitor_name;
8979 info3.default_datatype = r->default_datatype;
8980 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8981 info3.dependent_files = r->dependent_files;
8983 info_ctr.level = 3;
8984 info_ctr.info.info3 = &info3;
8986 if (ex) {
8987 torture_assert(tctx,
8988 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8989 "failed to test AddPrinterDriverEx level 3");
8990 } else {
8991 torture_assert(tctx,
8992 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8993 "failed to test AddPrinterDriver level 3");
8996 torture_assert(tctx,
8997 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8998 "failed to find added printer driver");
9000 if (remote_driver_dir) {
9001 int i;
9002 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9003 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9004 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9005 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9006 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9007 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9011 return true;
9014 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9015 struct dcerpc_binding_handle *b,
9016 const char *server_name,
9017 struct spoolss_AddDriverInfo8 *r,
9018 uint32_t flags,
9019 bool ex,
9020 const char *remote_driver_dir)
9022 struct spoolss_AddDriverInfoCtr info_ctr;
9023 struct spoolss_AddDriverInfo4 info4;
9024 union spoolss_DriverInfo info;
9026 info4.version = r->version;
9027 info4.driver_name = r->driver_name;
9028 info4.architecture = r->architecture;
9029 info4.driver_path = r->driver_path;
9030 info4.data_file = r->data_file;
9031 info4.config_file = r->config_file;
9032 info4.help_file = r->help_file;
9033 info4.monitor_name = r->monitor_name;
9034 info4.default_datatype = r->default_datatype;
9035 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9036 info4.dependent_files = r->dependent_files;
9037 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9038 info4.previous_names = r->previous_names;
9040 info_ctr.level = 4;
9041 info_ctr.info.info4 = &info4;
9043 if (ex) {
9044 torture_assert(tctx,
9045 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9046 "failed to test AddPrinterDriverEx level 4");
9047 } else {
9048 torture_assert(tctx,
9049 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9050 "failed to test AddPrinterDriver level 4");
9053 torture_assert(tctx,
9054 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9055 "failed to find added printer driver");
9057 if (remote_driver_dir) {
9058 int i;
9059 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9060 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9061 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9062 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9063 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9064 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9068 return true;
9071 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9072 struct dcerpc_binding_handle *b,
9073 const char *server_name,
9074 struct spoolss_AddDriverInfo8 *r,
9075 uint32_t flags,
9076 bool ex,
9077 const char *remote_driver_dir)
9079 struct spoolss_AddDriverInfoCtr info_ctr;
9080 struct spoolss_AddDriverInfo6 info6;
9081 union spoolss_DriverInfo info;
9083 info6.version = r->version;
9084 info6.driver_name = r->driver_name;
9085 info6.architecture = r->architecture;
9086 info6.driver_path = r->driver_path;
9087 info6.data_file = r->data_file;
9088 info6.config_file = r->config_file;
9089 info6.help_file = r->help_file;
9090 info6.monitor_name = r->monitor_name;
9091 info6.default_datatype = r->default_datatype;
9092 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9093 info6.dependent_files = r->dependent_files;
9094 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9095 info6.previous_names = r->previous_names;
9096 info6.driver_date = r->driver_date;
9097 info6.driver_version = r->driver_version;
9098 info6.manufacturer_name = r->manufacturer_name;
9099 info6.manufacturer_url = r->manufacturer_url;
9100 info6.hardware_id = r->hardware_id;
9101 info6.provider = r->provider;
9103 info_ctr.level = 6;
9104 info_ctr.info.info6 = &info6;
9106 if (ex) {
9107 torture_assert(tctx,
9108 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9109 "failed to test AddPrinterDriverEx level 6");
9110 } else {
9111 torture_assert(tctx,
9112 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9113 "failed to test AddPrinterDriver level 6");
9116 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9118 if (!ex) {
9119 return true;
9122 torture_assert(tctx,
9123 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9124 "failed to find added printer driver");
9126 if (remote_driver_dir) {
9127 int i;
9128 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9129 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9130 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9131 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9132 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9133 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9137 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9138 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9140 return true;
9143 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9144 struct dcerpc_binding_handle *b,
9145 const char *server_name,
9146 struct spoolss_AddDriverInfo8 *r,
9147 uint32_t flags,
9148 bool ex,
9149 const char *remote_driver_dir)
9151 struct spoolss_AddDriverInfoCtr info_ctr;
9152 union spoolss_DriverInfo info;
9154 info_ctr.level = 8;
9155 info_ctr.info.info8 = r;
9157 if (ex) {
9158 torture_assert(tctx,
9159 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9160 "failed to test AddPrinterDriverEx level 8");
9161 } else {
9162 torture_assert(tctx,
9163 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9164 "failed to test AddPrinterDriver level 8");
9167 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9169 if (!ex) {
9170 return true;
9173 torture_assert(tctx,
9174 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9175 "failed to find added printer driver");
9177 if (remote_driver_dir) {
9178 int i;
9179 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9180 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9181 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9182 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9183 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9184 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9188 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9189 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9191 return true;
9194 #undef ASSERT_DRIVER_PATH
9196 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9197 struct dcerpc_binding_handle *b,
9198 const char *server,
9199 const char *driver,
9200 const char *environment,
9201 WERROR expected_result)
9203 struct spoolss_DeletePrinterDriver r;
9205 r.in.server = server;
9206 r.in.architecture = environment;
9207 r.in.driver = driver;
9209 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9211 torture_assert_ntstatus_ok(tctx,
9212 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9213 "DeletePrinterDriver failed");
9214 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9215 "DeletePrinterDriver failed with unexpected result");
9217 return true;
9220 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9221 struct dcerpc_binding_handle *b,
9222 const char *server,
9223 const char *driver,
9224 const char *environment,
9225 uint32_t delete_flags,
9226 uint32_t version,
9227 WERROR expected_result)
9229 struct spoolss_DeletePrinterDriverEx r;
9231 r.in.server = server;
9232 r.in.architecture = environment;
9233 r.in.driver = driver;
9234 r.in.delete_flags = delete_flags;
9235 r.in.version = version;
9237 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9239 torture_assert_ntstatus_ok(tctx,
9240 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9241 "DeletePrinterDriverEx failed");
9242 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9243 "DeletePrinterDriverEx failed with unexpected result");
9245 return true;
9248 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9249 struct dcerpc_binding_handle *b,
9250 const char *server_name,
9251 const char *driver,
9252 const char *environment)
9254 torture_assert(tctx,
9255 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9256 "failed to delete driver");
9258 torture_assert(tctx,
9259 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9260 "failed to delete driver");
9262 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9263 torture_fail(tctx, "deleted driver still enumerated");
9266 torture_assert(tctx,
9267 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9268 "2nd delete failed");
9270 return true;
9273 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9274 struct dcerpc_binding_handle *b,
9275 const char *server_name,
9276 const char *driver,
9277 const char *environment,
9278 uint32_t delete_flags,
9279 uint32_t version)
9281 torture_assert(tctx,
9282 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9283 "failed to delete driver");
9285 torture_assert(tctx,
9286 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9287 "failed to delete driver");
9289 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9290 torture_fail(tctx, "deleted driver still enumerated");
9293 torture_assert(tctx,
9294 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9295 "2nd delete failed");
9297 return true;
9300 static bool test_PrinterDriver_args(struct torture_context *tctx,
9301 struct dcerpc_binding_handle *b,
9302 const char *server_name,
9303 uint32_t level,
9304 struct spoolss_AddDriverInfo8 *r,
9305 uint32_t add_flags,
9306 uint32_t delete_flags,
9307 uint32_t delete_version,
9308 bool ex,
9309 const char *remote_driver_dir)
9311 bool ret = true;
9313 switch (level) {
9314 case 1:
9315 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9316 break;
9317 case 2:
9318 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9319 break;
9320 case 3:
9321 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9322 break;
9323 case 4:
9324 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9325 break;
9326 case 6:
9327 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9328 break;
9329 case 8:
9330 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9331 break;
9332 default:
9333 return false;
9336 if (ret == false) {
9337 return ret;
9340 if (level == 1) {
9341 return ret;
9344 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9346 if (!ex && (level == 6 || level == 8)) {
9347 return ret;
9351 struct dcerpc_pipe *p2;
9352 struct policy_handle hive_handle;
9353 struct dcerpc_binding_handle *b2;
9355 torture_assert_ntstatus_ok(tctx,
9356 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9357 "could not open winreg pipe");
9358 b2 = p2->binding_handle;
9360 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9362 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9364 test_winreg_CloseKey(tctx, b2, &hive_handle);
9366 talloc_free(p2);
9369 if (ex) {
9370 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9371 } else {
9372 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9376 static bool fillup_printserver_info(struct torture_context *tctx,
9377 struct dcerpc_pipe *p,
9378 struct torture_driver_context *d)
9380 struct policy_handle server_handle;
9381 struct dcerpc_binding_handle *b = p->binding_handle;
9382 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9384 torture_assert(tctx,
9385 test_OpenPrinter_server(tctx, p, &server_handle),
9386 "failed to open printserver");
9387 torture_assert(tctx,
9388 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9389 "failed to get environment");
9390 torture_assert(tctx,
9391 test_ClosePrinter(tctx, b, &server_handle),
9392 "failed to close printserver");
9394 torture_assert(tctx,
9395 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9396 d->local.environment ? d->local.environment : d->remote.environment,
9397 &d->remote.driver_directory),
9398 "failed to get driver directory");
9400 return true;
9403 static const char *driver_directory_dir(const char *driver_directory)
9405 char *p;
9407 p = strrchr(driver_directory, '\\');
9408 if (p) {
9409 return p+1;
9412 return NULL;
9415 static const char *driver_directory_share(struct torture_context *tctx,
9416 const char *driver_directory)
9418 const char *p;
9419 char *tok;
9421 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9422 driver_directory += 2;
9425 p = talloc_strdup(tctx, driver_directory);
9427 torture_assert(tctx,
9428 next_token_talloc(tctx, &p, &tok, "\\"),
9429 "cannot explode uri");
9430 torture_assert(tctx,
9431 next_token_talloc(tctx, &p, &tok, "\\"),
9432 "cannot explode uri");
9434 return tok;
9437 static bool upload_printer_driver_file(struct torture_context *tctx,
9438 struct smbcli_state *cli,
9439 struct torture_driver_context *d,
9440 const char *file_name)
9442 XFILE *f;
9443 int fnum;
9444 uint8_t *buf;
9445 int maxwrite = 64512;
9446 off_t nread = 0;
9447 size_t start = 0;
9448 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9449 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9450 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9452 if (!file_name || strlen(file_name) == 0) {
9453 return true;
9456 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9458 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9459 if (fnum == -1) {
9460 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9463 f = x_fopen(local_name, O_RDONLY, 0);
9464 if (f == NULL) {
9465 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9468 buf = talloc_array(tctx, uint8_t, maxwrite);
9469 if (!buf) {
9470 x_fclose(f);
9471 return false;
9474 while (!x_feof(f)) {
9475 int n = maxwrite;
9476 int ret;
9478 if ((n = x_fread(buf, 1, n, f)) < 1) {
9479 if((n == 0) && x_feof(f))
9480 break; /* Empty local file. */
9482 torture_warning(tctx,
9483 "failed to read file: %s\n", strerror(errno));
9484 break;
9487 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9489 if (n != ret) {
9490 torture_warning(tctx,
9491 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9492 break;
9495 nread += n;
9498 x_fclose(f);
9500 torture_assert_ntstatus_ok(tctx,
9501 smbcli_close(cli->tree, fnum),
9502 "failed to close file");
9504 return true;
9507 static bool connect_printer_driver_share(struct torture_context *tctx,
9508 const char *server_name,
9509 const char *share_name,
9510 struct smbcli_state **cli)
9512 struct smbcli_options smb_options;
9513 struct smbcli_session_options smb_session_options;
9515 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9516 share_name, server_name);
9518 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9519 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9521 torture_assert_ntstatus_ok(tctx,
9522 smbcli_full_connection(tctx, cli, server_name,
9523 lpcfg_smb_ports(tctx->lp_ctx),
9524 share_name, NULL,
9525 lpcfg_socket_options(tctx->lp_ctx),
9526 cmdline_credentials,
9527 lpcfg_resolve_context(tctx->lp_ctx),
9528 tctx->ev,
9529 &smb_options,
9530 &smb_session_options,
9531 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9532 "failed to open driver share");
9534 return true;
9537 static bool upload_printer_driver(struct torture_context *tctx,
9538 const char *server_name,
9539 struct torture_driver_context *d)
9541 struct smbcli_state *cli;
9542 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9543 int i;
9545 torture_assert(tctx,
9546 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9547 "failed to connect to driver share");
9549 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9550 server_name, share_name);
9552 torture_assert(tctx,
9553 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9554 "failed to upload driver_path");
9555 torture_assert(tctx,
9556 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9557 "failed to upload data_file");
9558 torture_assert(tctx,
9559 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9560 "failed to upload config_file");
9561 torture_assert(tctx,
9562 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9563 "failed to upload help_file");
9564 if (d->info8.dependent_files) {
9565 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9566 torture_assert(tctx,
9567 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9568 "failed to upload dependent_files");
9572 talloc_free(cli);
9574 return true;
9577 static bool check_printer_driver_file(struct torture_context *tctx,
9578 struct smbcli_state *cli,
9579 struct torture_driver_context *d,
9580 const char *file_name)
9582 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9583 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9584 remote_arch_dir,
9585 d->info8.version,
9586 file_name);
9587 int fnum;
9589 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9591 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9593 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9594 if (fnum == -1) {
9595 return false;
9598 torture_assert_ntstatus_ok(tctx,
9599 smbcli_close(cli->tree, fnum),
9600 "failed to close driver file");
9602 return true;
9605 static bool check_printer_driver_files(struct torture_context *tctx,
9606 const char *server_name,
9607 struct torture_driver_context *d,
9608 bool expect_exist)
9610 struct smbcli_state *cli;
9611 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9612 int i;
9614 torture_assert(tctx,
9615 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9616 "failed to connect to driver share");
9618 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9619 (expect_exist ? "": "non-"),
9620 server_name, share_name);
9622 if (d->info8.driver_path && d->info8.driver_path[0]) {
9623 torture_assert(tctx,
9624 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9625 "failed driver_path check");
9627 if (d->info8.data_file && d->info8.data_file[0]) {
9628 torture_assert(tctx,
9629 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9630 "failed data_file check");
9632 if (d->info8.config_file && d->info8.config_file[0]) {
9633 torture_assert(tctx,
9634 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9635 "failed config_file check");
9637 if (d->info8.help_file && d->info8.help_file[0]) {
9638 torture_assert(tctx,
9639 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9640 "failed help_file check");
9642 if (d->info8.dependent_files) {
9643 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9644 torture_assert(tctx,
9645 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9646 "failed dependent_files check");
9650 talloc_free(cli);
9652 return true;
9655 static bool remove_printer_driver_file(struct torture_context *tctx,
9656 struct smbcli_state *cli,
9657 struct torture_driver_context *d,
9658 const char *file_name)
9660 const char *remote_name;
9661 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9663 if (!file_name || strlen(file_name) == 0) {
9664 return true;
9667 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9669 torture_comment(tctx, "Removing %s\n", remote_name);
9671 torture_assert_ntstatus_ok(tctx,
9672 smbcli_unlink(cli->tree, remote_name),
9673 "failed to unlink");
9675 return true;
9678 static bool remove_printer_driver(struct torture_context *tctx,
9679 const char *server_name,
9680 struct torture_driver_context *d)
9682 struct smbcli_state *cli;
9683 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9684 int i;
9686 torture_assert(tctx,
9687 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9688 "failed to connect to driver share");
9690 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9691 server_name, share_name);
9693 torture_assert(tctx,
9694 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9695 "failed to remove driver_path");
9696 torture_assert(tctx,
9697 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9698 "failed to remove data_file");
9699 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9700 torture_assert(tctx,
9701 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9702 "failed to remove config_file");
9704 torture_assert(tctx,
9705 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9706 "failed to remove help_file");
9707 if (d->info8.dependent_files) {
9708 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9709 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9710 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9711 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9712 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9713 continue;
9715 torture_assert(tctx,
9716 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9717 "failed to remove dependent_files");
9721 talloc_free(cli);
9723 return true;
9727 static bool test_add_driver_arg(struct torture_context *tctx,
9728 struct dcerpc_pipe *p,
9729 struct torture_driver_context *d)
9731 bool ret = true;
9732 struct dcerpc_binding_handle *b = p->binding_handle;
9733 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9734 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9735 int i;
9736 struct spoolss_AddDriverInfo8 info8;
9737 uint32_t add_flags = APD_COPY_NEW_FILES;
9738 uint32_t delete_flags = 0;
9740 ZERO_STRUCT(info8);
9742 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9743 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9745 torture_assert(tctx,
9746 fillup_printserver_info(tctx, p, d),
9747 "failed to fillup printserver info");
9749 if (!directory_exist(d->local.driver_directory)) {
9750 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9753 torture_assert(tctx,
9754 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9755 "failed to upload printer driver");
9757 info8 = d->info8;
9758 if (d->info8.dependent_files) {
9759 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9760 if (d->info8.dependent_files->string) {
9761 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9763 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9764 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9765 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9769 info8.architecture = d->local.environment;
9771 for (i=0; i < ARRAY_SIZE(levels); i++) {
9773 if (torture_setting_bool(tctx, "samba3", false)) {
9774 switch (levels[i]) {
9775 case 2:
9776 case 4:
9777 case 8:
9778 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9779 continue;
9780 default:
9781 break;
9784 if (torture_setting_bool(tctx, "w2k3", false)) {
9785 switch (levels[i]) {
9786 case 8:
9787 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9788 continue;
9789 default:
9790 break;
9794 torture_comment(tctx,
9795 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9796 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9798 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);
9801 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9802 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9803 if (d->info8.config_file) {
9804 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9806 if (d->info8.help_file) {
9807 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9809 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9810 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9811 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9815 for (i=0; i < ARRAY_SIZE(levels); i++) {
9817 if (torture_setting_bool(tctx, "samba3", false)) {
9818 switch (levels[i]) {
9819 case 2:
9820 case 4:
9821 case 8:
9822 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9823 continue;
9824 default:
9825 break;
9828 if (torture_setting_bool(tctx, "w2k3", false)) {
9829 switch (levels[i]) {
9830 case 8:
9831 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9832 continue;
9833 default:
9834 break;
9838 torture_comment(tctx,
9839 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9840 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9842 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);
9845 torture_assert(tctx,
9846 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9847 "failed to remove printer driver");
9849 torture_comment(tctx, "\n");
9851 return ret;
9854 static bool test_add_driver_ex_64(struct torture_context *tctx,
9855 struct dcerpc_pipe *p)
9857 struct torture_driver_context *d;
9859 d = talloc_zero(tctx, struct torture_driver_context);
9861 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9862 d->info8.driver_name = TORTURE_DRIVER_EX;
9863 d->info8.architecture = NULL;
9864 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9865 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9866 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9867 d->local.environment = talloc_strdup(d, "Windows x64");
9868 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9869 d->ex = true;
9871 return test_add_driver_arg(tctx, p, d);
9874 static bool test_add_driver_ex_32(struct torture_context *tctx,
9875 struct dcerpc_pipe *p)
9877 struct torture_driver_context *d;
9879 d = talloc_zero(tctx, struct torture_driver_context);
9881 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9882 d->info8.driver_name = TORTURE_DRIVER_EX;
9883 d->info8.architecture = NULL;
9884 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9885 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9886 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9887 d->local.environment = talloc_strdup(d, "Windows NT x86");
9888 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9889 d->ex = true;
9891 return test_add_driver_arg(tctx, p, d);
9894 static bool test_add_driver_64(struct torture_context *tctx,
9895 struct dcerpc_pipe *p)
9897 struct torture_driver_context *d;
9899 d = talloc_zero(tctx, struct torture_driver_context);
9901 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9902 d->info8.driver_name = TORTURE_DRIVER;
9903 d->info8.architecture = NULL;
9904 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9905 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9906 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9907 d->local.environment = talloc_strdup(d, "Windows x64");
9908 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9909 d->ex = false;
9911 return test_add_driver_arg(tctx, p, d);
9914 static bool test_add_driver_32(struct torture_context *tctx,
9915 struct dcerpc_pipe *p)
9917 struct torture_driver_context *d;
9919 d = talloc_zero(tctx, struct torture_driver_context);
9921 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9922 d->info8.driver_name = TORTURE_DRIVER;
9923 d->info8.architecture = NULL;
9924 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9925 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9926 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9927 d->local.environment = talloc_strdup(d, "Windows NT x86");
9928 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9929 d->ex = false;
9931 return test_add_driver_arg(tctx, p, d);
9934 static bool test_add_driver_adobe(struct torture_context *tctx,
9935 struct dcerpc_pipe *p)
9937 struct torture_driver_context *d;
9939 if (!torture_setting_bool(tctx, "samba3", false)) {
9940 torture_skip(tctx, "skipping adobe test which only works against samba3");
9943 d = talloc_zero(tctx, struct torture_driver_context);
9945 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9946 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9947 d->info8.architecture = NULL;
9948 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9949 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9950 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9951 #if 0
9952 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9953 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9954 #endif
9955 d->local.environment = talloc_strdup(d, "Windows 4.0");
9956 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9957 d->ex = false;
9959 return test_add_driver_arg(tctx, p, d);
9962 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9963 struct dcerpc_pipe *p)
9965 struct torture_driver_context *d;
9966 struct spoolss_StringArray *a;
9968 if (!torture_setting_bool(tctx, "samba3", false)) {
9969 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9972 d = talloc_zero(tctx, struct torture_driver_context);
9974 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9975 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9976 d->info8.architecture = NULL;
9977 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9978 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9979 d->info8.config_file = NULL;
9980 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9981 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9982 d->info8.default_datatype = talloc_strdup(d, "RAW");
9984 a = talloc_zero(d, struct spoolss_StringArray);
9985 a->string = talloc_zero_array(a, const char *, 7);
9986 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9987 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9988 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9989 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9990 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9991 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9993 d->info8.dependent_files = a;
9994 d->local.environment = talloc_strdup(d, "Windows 4.0");
9995 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9996 d->ex = false;
9998 return test_add_driver_arg(tctx, p, d);
10001 static bool test_add_driver_timestamps(struct torture_context *tctx,
10002 struct dcerpc_pipe *p)
10004 struct torture_driver_context *d;
10005 struct timeval t = timeval_current();
10007 d = talloc_zero(tctx, struct torture_driver_context);
10009 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10010 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
10011 d->info8.architecture = NULL;
10012 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10013 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10014 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10015 d->info8.driver_date = timeval_to_nttime(&t);
10016 d->local.environment = talloc_strdup(d, "Windows NT x86");
10017 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10018 d->ex = true;
10020 torture_assert(tctx,
10021 test_add_driver_arg(tctx, p, d),
10022 "");
10024 unix_to_nt_time(&d->info8.driver_date, 1);
10026 torture_assert(tctx,
10027 test_add_driver_arg(tctx, p, d),
10028 "");
10030 return true;
10033 static bool test_multiple_drivers(struct torture_context *tctx,
10034 struct dcerpc_pipe *p)
10036 struct torture_driver_context *d;
10037 struct dcerpc_binding_handle *b = p->binding_handle;
10038 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10039 int i;
10040 struct spoolss_AddDriverInfo8 info8;
10041 uint32_t add_flags = APD_COPY_NEW_FILES;
10042 uint32_t delete_flags = 0;
10044 d = talloc_zero(tctx, struct torture_driver_context);
10046 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10047 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10048 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10049 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10050 d->local.environment = talloc_strdup(d, "Windows NT x86");
10051 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10052 d->ex = true;
10054 torture_assert(tctx,
10055 fillup_printserver_info(tctx, p, d),
10056 "failed to fillup printserver info");
10058 if (!directory_exist(d->local.driver_directory)) {
10059 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10062 torture_assert(tctx,
10063 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10064 "failed to upload printer driver");
10066 info8 = d->info8;
10067 info8.architecture = d->local.environment;
10069 for (i=0; i < 3; i++) {
10070 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
10072 torture_assert(tctx,
10073 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10074 "failed to add driver");
10077 torture_assert(tctx,
10078 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10079 "failed to delete driver");
10081 torture_assert(tctx,
10082 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10083 "torture_test_driver_1 no longer on the server");
10085 torture_assert(tctx,
10086 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10087 "torture_test_driver_2 no longer on the server");
10089 torture_assert(tctx,
10090 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10091 "failed to delete driver");
10093 torture_assert(tctx,
10094 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10095 "torture_test_driver_2 no longer on the server");
10097 torture_assert(tctx,
10098 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10099 "failed to delete driver");
10101 torture_assert(tctx,
10102 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10103 "failed to remove printer driver");
10105 return true;
10108 static bool test_del_driver_all_files(struct torture_context *tctx,
10109 struct dcerpc_pipe *p)
10111 struct torture_driver_context *d;
10112 struct spoolss_StringArray *a;
10113 uint32_t add_flags = APD_COPY_NEW_FILES;
10114 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10115 struct dcerpc_binding_handle *b = p->binding_handle;
10116 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10118 d = talloc_zero(tctx, struct torture_driver_context);
10120 d->ex = true;
10121 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10122 d->info8.driver_name = TORTURE_DRIVER_DELETER;
10123 d->info8.architecture = NULL;
10124 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10125 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10126 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10127 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
10128 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10129 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10131 a = talloc_zero(d, struct spoolss_StringArray);
10132 a->string = talloc_zero_array(a, const char *, 3);
10133 a->string[0] = talloc_strdup(a->string, "cups6.inf");
10134 a->string[1] = talloc_strdup(a->string, "cups6.ini");
10136 d->info8.dependent_files = a;
10137 d->info8.architecture = d->local.environment;
10139 torture_assert(tctx,
10140 fillup_printserver_info(tctx, p, d),
10141 "failed to fillup printserver info");
10143 if (!directory_exist(d->local.driver_directory)) {
10144 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10147 torture_assert(tctx,
10148 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10149 "failed to upload printer driver");
10151 torture_assert(tctx,
10152 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10153 "failed to add driver");
10155 torture_assert(tctx,
10156 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10157 d->info8.driver_name,
10158 d->local.environment,
10159 delete_flags,
10160 d->info8.version),
10161 "failed to delete driver");
10163 torture_assert(tctx,
10164 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10165 "printer driver file check failed");
10167 talloc_free(d);
10168 return true;
10171 static bool test_del_driver_unused_files(struct torture_context *tctx,
10172 struct dcerpc_pipe *p)
10174 struct torture_driver_context *d1;
10175 struct torture_driver_context *d2;
10176 uint32_t add_flags = APD_COPY_NEW_FILES;
10177 struct dcerpc_binding_handle *b = p->binding_handle;
10178 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10180 d1 = talloc_zero(tctx, struct torture_driver_context);
10181 d1->ex = true;
10182 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10183 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10184 d1->info8.architecture = NULL;
10185 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10186 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10187 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10188 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10189 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10190 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10191 d1->info8.architecture = d1->local.environment;
10193 d2 = talloc_zero(tctx, struct torture_driver_context);
10194 d2->ex = true;
10195 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10196 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10197 d2->info8.architecture = NULL;
10198 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10199 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10200 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10201 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10202 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10203 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10204 d2->info8.architecture = d2->local.environment;
10206 torture_assert(tctx,
10207 fillup_printserver_info(tctx, p, d1),
10208 "failed to fillup printserver info");
10209 torture_assert(tctx,
10210 fillup_printserver_info(tctx, p, d2),
10211 "failed to fillup printserver info");
10213 if (!directory_exist(d1->local.driver_directory)) {
10214 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10217 torture_assert(tctx,
10218 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10219 "failed to upload printer driver");
10220 torture_assert(tctx,
10221 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10222 "failed to add driver");
10224 torture_assert(tctx,
10225 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10226 "failed to upload printer driver");
10227 torture_assert(tctx,
10228 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10229 "failed to add driver");
10231 /* some files are in use by a separate driver, should fail */
10232 torture_assert(tctx,
10233 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10234 d1->info8.driver_name,
10235 d1->local.environment,
10236 DPD_DELETE_ALL_FILES,
10237 d1->info8.version,
10238 WERR_PRINTER_DRIVER_IN_USE),
10239 "invalid delete driver response");
10241 /* should only delete files not in use by other driver */
10242 torture_assert(tctx,
10243 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10244 d1->info8.driver_name,
10245 d1->local.environment,
10246 DPD_DELETE_UNUSED_FILES,
10247 d1->info8.version,
10248 WERR_OK),
10249 "failed to delete driver (unused files)");
10251 /* check non-overlapping were deleted */
10252 d1->info8.driver_path = NULL;
10253 d1->info8.help_file = NULL;
10254 torture_assert(tctx,
10255 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10256 "printer driver file check failed");
10257 /* d2 files should be uneffected */
10258 torture_assert(tctx,
10259 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10260 "printer driver file check failed");
10262 torture_assert(tctx,
10263 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10264 d2->info8.driver_name,
10265 d2->local.environment,
10266 DPD_DELETE_ALL_FILES,
10267 d2->info8.version,
10268 WERR_OK),
10269 "failed to delete driver");
10271 torture_assert(tctx,
10272 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10273 "printer driver file check failed");
10275 talloc_free(d1);
10276 talloc_free(d2);
10277 return true;
10280 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10282 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10284 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10285 "driver", &ndr_table_spoolss);
10286 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10287 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10289 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10290 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10292 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10294 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10296 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10298 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10300 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10302 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10304 return suite;