testprogs: Update the kpasswd setpassword test
[Samba.git] / source4 / torture / rpc / spoolss.c
blob31b9525ee62eae0b4809420e376560b14b7a27ea
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_ADD "torture_driver_add"
51 #define TORTURE_DRIVER_EX "torture_driver_ex"
52 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
53 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
54 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
55 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
56 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
57 #define TORTURE_DRIVER_COPY_DIR "torture_driver_copy_from_directory"
58 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
59 #define TORTURE_PRINTER_STATIC1 "print1"
61 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
62 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
63 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
64 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
65 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
66 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
68 struct test_spoolss_context {
69 struct dcerpc_pipe *spoolss_pipe;
71 /* server environment */
72 const char *environment;
74 /* print server handle */
75 struct policy_handle server_handle;
77 /* for EnumPorts */
78 uint32_t port_count[3];
79 union spoolss_PortInfo *ports[3];
81 /* for EnumPrinterDrivers */
82 uint32_t driver_count[9];
83 union spoolss_DriverInfo *drivers[9];
85 /* for EnumMonitors */
86 uint32_t monitor_count[3];
87 union spoolss_MonitorInfo *monitors[3];
89 /* for EnumPrintProcessors */
90 uint32_t print_processor_count[2];
91 union spoolss_PrintProcessorInfo *print_processors[2];
93 /* for EnumPrinters */
94 uint32_t printer_count[6];
95 union spoolss_PrinterInfo *printers[6];
98 struct torture_driver_context {
99 struct {
100 const char *driver_directory;
101 const char *environment;
102 } local;
103 struct {
104 const char *driver_directory;
105 const char *driver_upload_directory;
106 const char *environment;
107 } remote;
108 struct spoolss_AddDriverInfo8 info8;
109 bool ex;
112 struct torture_printer_context {
113 struct dcerpc_pipe *spoolss_pipe;
114 struct spoolss_SetPrinterInfo2 info2;
115 struct torture_driver_context driver;
116 bool ex;
117 bool wellknown;
118 bool added_driver;
119 bool have_driver;
120 struct spoolss_DeviceMode *devmode;
121 struct policy_handle handle;
124 static bool upload_printer_driver(struct torture_context *tctx,
125 const char *server_name,
126 struct torture_driver_context *d);
127 static bool remove_printer_driver(struct torture_context *tctx,
128 const char *server_name,
129 struct torture_driver_context *d);
130 static bool fillup_printserver_info(struct torture_context *tctx,
131 struct dcerpc_pipe *p,
132 struct torture_driver_context *d);
133 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
134 struct dcerpc_binding_handle *b,
135 const char *server_name,
136 struct spoolss_AddDriverInfo8 *r,
137 uint32_t flags,
138 bool ex,
139 const char *remote_driver_dir);
141 #define COMPARE_STRING(tctx, c,r,e) \
142 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
144 /* not every compiler supports __typeof__() */
145 #if (__GNUC__ >= 3)
146 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
147 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
148 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
150 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
151 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
153 } while(0)
154 #else
155 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
156 #endif
158 #define COMPARE_UINT32(tctx, c, r, e) do {\
159 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
160 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
161 } while(0)
163 #define COMPARE_UINT64(tctx, c, r, e) do {\
164 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
165 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
166 } while(0)
169 #define COMPARE_NTTIME(tctx, c, r, e) do {\
170 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
171 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
172 } while(0)
174 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
175 int __i; \
176 if (!c.e && !r.e) { \
177 break; \
179 if (c.e && !r.e) { \
180 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
182 if (!c.e && r.e) { \
183 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
185 for (__i=0;c.e[__i] != NULL; __i++) { \
186 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
188 } while(0)
190 #define CHECK_ALIGN(size, n) do {\
191 if (size % n) {\
192 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
193 size, n, size + n - (size % n));\
195 } while(0)
197 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
199 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
200 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
201 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
202 uint32_t round_size = DO_ROUND(size, align);\
203 if (round_size != needed) {\
204 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
205 CHECK_ALIGN(size, align);\
208 } while(0)
210 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
211 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
212 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
213 uint32_t round_size = DO_ROUND(size, align);\
214 if (round_size != needed) {\
215 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
216 CHECK_ALIGN(size, align);\
219 } while(0)
221 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
222 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
223 uint32_t size = ndr_size_##fn(info, level, 0);\
224 uint32_t round_size = DO_ROUND(size, align);\
225 if (round_size != needed) {\
226 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
227 CHECK_ALIGN(size, align);\
230 } while(0)
232 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
233 const union spoolss_PrinterInfo *i,
234 uint32_t level,
235 union spoolss_SetPrinterInfo *s)
237 switch (level) {
238 case 0:
239 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
240 break;
241 case 2:
242 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
243 s->info2->servername = i->info2.servername;
244 s->info2->printername = i->info2.printername;
245 s->info2->sharename = i->info2.sharename;
246 s->info2->portname = i->info2.portname;
247 s->info2->drivername = i->info2.drivername;
248 s->info2->comment = i->info2.comment;
249 s->info2->location = i->info2.location;
250 s->info2->devmode_ptr = 0;
251 s->info2->sepfile = i->info2.sepfile;
252 s->info2->printprocessor = i->info2.printprocessor;
253 s->info2->datatype = i->info2.datatype;
254 s->info2->parameters = i->info2.parameters;
255 s->info2->secdesc_ptr = 0;
256 s->info2->attributes = i->info2.attributes;
257 s->info2->priority = i->info2.priority;
258 s->info2->defaultpriority = i->info2.defaultpriority;
259 s->info2->starttime = i->info2.starttime;
260 s->info2->untiltime = i->info2.untiltime;
261 s->info2->status = i->info2.status;
262 s->info2->cjobs = i->info2.cjobs;
263 s->info2->averageppm = i->info2.averageppm;
264 break;
265 case 3:
266 case 4:
267 case 5:
268 case 6:
269 case 7:
270 case 8:
271 case 9:
272 default:
273 return false;
276 return true;
279 static bool test_OpenPrinter_server(struct torture_context *tctx,
280 struct dcerpc_pipe *p,
281 struct policy_handle *server_handle)
283 NTSTATUS status;
284 struct spoolss_OpenPrinter op;
285 struct dcerpc_binding_handle *b = p->binding_handle;
287 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
288 op.in.datatype = NULL;
289 op.in.devmode_ctr.devmode= NULL;
290 op.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
291 op.out.handle = server_handle;
293 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
295 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
296 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
297 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
299 return true;
302 static bool test_EnumPorts(struct torture_context *tctx,
303 void *private_data)
305 struct test_spoolss_context *ctx =
306 talloc_get_type_abort(private_data, struct test_spoolss_context);
307 struct dcerpc_pipe *p = ctx->spoolss_pipe;
308 struct dcerpc_binding_handle *b = p->binding_handle;
309 NTSTATUS status;
310 struct spoolss_EnumPorts r;
311 uint16_t levels[] = { 1, 2 };
312 int i, j;
314 for (i=0;i<ARRAY_SIZE(levels);i++) {
315 int level = levels[i];
316 DATA_BLOB blob;
317 uint32_t needed;
318 uint32_t count;
319 union spoolss_PortInfo *info;
321 r.in.servername = "";
322 r.in.level = level;
323 r.in.buffer = NULL;
324 r.in.offered = 0;
325 r.out.needed = &needed;
326 r.out.count = &count;
327 r.out.info = &info;
329 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
331 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
332 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
333 if (W_ERROR_IS_OK(r.out.result)) {
334 /* TODO: do some more checks here */
335 continue;
337 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
338 "EnumPorts unexpected return code");
340 blob = data_blob_talloc_zero(ctx, needed);
341 r.in.buffer = &blob;
342 r.in.offered = needed;
344 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
345 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
347 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
349 torture_assert(tctx, info, "EnumPorts returned no info");
351 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
353 ctx->port_count[level] = count;
354 ctx->ports[level] = info;
357 for (i=1;i<ARRAY_SIZE(levels);i++) {
358 int level = levels[i];
359 int old_level = levels[i-1];
360 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
361 "EnumPorts invalid value");
363 /* if the array sizes are not the same we would maybe segfault in the following code */
365 for (i=0;i<ARRAY_SIZE(levels);i++) {
366 int level = levels[i];
367 for (j=0;j<ctx->port_count[level];j++) {
368 union spoolss_PortInfo *cur = &ctx->ports[level][j];
369 union spoolss_PortInfo *ref = &ctx->ports[2][j];
370 switch (level) {
371 case 1:
372 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
373 break;
374 case 2:
375 /* level 2 is our reference, and it makes no sense to compare it to itself */
376 break;
381 return true;
384 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
385 void *private_data)
387 struct test_spoolss_context *ctx =
388 talloc_get_type_abort(private_data, struct test_spoolss_context);
390 NTSTATUS status;
391 struct dcerpc_pipe *p = ctx->spoolss_pipe;
392 struct dcerpc_binding_handle *b = p->binding_handle;
393 struct spoolss_GetPrintProcessorDirectory r;
394 struct {
395 uint16_t level;
396 const char *server;
397 } levels[] = {{
398 .level = 1,
399 .server = NULL
401 .level = 1,
402 .server = ""
404 .level = 78,
405 .server = ""
407 .level = 1,
408 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
410 .level = 1024,
411 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
414 int i;
415 uint32_t needed;
417 for (i=0;i<ARRAY_SIZE(levels);i++) {
418 int level = levels[i].level;
419 DATA_BLOB blob;
421 r.in.server = levels[i].server;
422 r.in.environment = ctx->environment;
423 r.in.level = level;
424 r.in.buffer = NULL;
425 r.in.offered = 0;
426 r.out.needed = &needed;
428 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
430 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
431 torture_assert_ntstatus_ok(tctx, status,
432 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
433 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
434 "GetPrintProcessorDirectory unexpected return code");
436 blob = data_blob_talloc_zero(tctx, needed);
437 r.in.buffer = &blob;
438 r.in.offered = needed;
440 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
441 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
443 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
445 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
448 return true;
452 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
453 void *private_data)
455 struct test_spoolss_context *ctx =
456 talloc_get_type_abort(private_data, struct test_spoolss_context);
458 NTSTATUS status;
459 struct dcerpc_pipe *p = ctx->spoolss_pipe;
460 struct dcerpc_binding_handle *b = p->binding_handle;
461 struct spoolss_GetPrinterDriverDirectory r;
462 struct {
463 uint16_t level;
464 const char *server;
465 } levels[] = {{
466 .level = 1,
467 .server = NULL
469 .level = 1,
470 .server = ""
472 .level = 78,
473 .server = ""
475 .level = 1,
476 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
478 .level = 1024,
479 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
482 int i;
483 uint32_t needed;
485 for (i=0;i<ARRAY_SIZE(levels);i++) {
486 int level = levels[i].level;
487 DATA_BLOB blob;
489 r.in.server = levels[i].server;
490 r.in.environment = ctx->environment;
491 r.in.level = level;
492 r.in.buffer = NULL;
493 r.in.offered = 0;
494 r.out.needed = &needed;
496 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
498 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
499 torture_assert_ntstatus_ok(tctx, status,
500 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
501 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
502 "GetPrinterDriverDirectory unexpected return code");
504 blob = data_blob_talloc_zero(tctx, needed);
505 r.in.buffer = &blob;
506 r.in.offered = needed;
508 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
509 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
511 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
513 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
516 return true;
519 static bool test_EnumPrinterDrivers_buffers(struct torture_context *tctx,
520 struct dcerpc_binding_handle *b,
521 const char *server_name,
522 const char *environment,
523 uint32_t level,
524 uint32_t offered,
525 uint32_t *count_p,
526 union spoolss_DriverInfo **info_p)
528 struct spoolss_EnumPrinterDrivers r;
529 uint32_t needed;
530 uint32_t count;
531 union spoolss_DriverInfo *info;
532 DATA_BLOB buffer;
534 if (offered > 0) {
535 buffer = data_blob_talloc_zero(tctx, offered);
538 r.in.server = server_name;
539 r.in.environment = environment;
540 r.in.level = level;
541 r.in.buffer = offered ? &buffer : NULL;
542 r.in.offered = offered;
543 r.out.needed = &needed;
544 r.out.count = &count;
545 r.out.info = &info;
547 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
548 r.in.environment, r.in.level, r.in.offered);
550 torture_assert_ntstatus_ok(tctx,
551 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
552 "EnumPrinterDrivers failed");
553 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
554 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
555 r.in.buffer = &blob;
556 r.in.offered = needed;
558 torture_assert_ntstatus_ok(tctx,
559 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
560 "EnumPrinterDrivers failed");
563 torture_assert_werr_ok(tctx, r.out.result,
564 "EnumPrinterDrivers failed");
566 if (count_p) {
567 *count_p = count;
569 if (info_p) {
570 *info_p = info;
573 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
575 return true;
580 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
581 struct dcerpc_binding_handle *b,
582 const char *server_name,
583 const char *environment,
584 uint32_t level,
585 uint32_t *count_p,
586 union spoolss_DriverInfo **info_p)
588 return test_EnumPrinterDrivers_buffers(tctx, b, server_name,
589 environment, level, 0,
590 count_p, info_p);
593 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
594 struct dcerpc_binding_handle *b,
595 const char *server_name,
596 const char *environment,
597 uint32_t level,
598 const char *driver_name,
599 union spoolss_DriverInfo *info_p)
601 uint32_t count;
602 union spoolss_DriverInfo *info;
603 int i;
604 const char *environment_ret = NULL;
606 torture_assert(tctx,
607 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
608 "failed to enumerate printer drivers");
610 for (i=0; i < count; i++) {
611 const char *driver_name_ret = "";
612 switch (level) {
613 case 1:
614 driver_name_ret = info[i].info1.driver_name;
615 break;
616 case 2:
617 driver_name_ret = info[i].info2.driver_name;
618 environment_ret = info[i].info2.architecture;
619 break;
620 case 3:
621 driver_name_ret = info[i].info3.driver_name;
622 environment_ret = info[i].info3.architecture;
623 break;
624 case 4:
625 driver_name_ret = info[i].info4.driver_name;
626 environment_ret = info[i].info4.architecture;
627 break;
628 case 5:
629 driver_name_ret = info[i].info5.driver_name;
630 environment_ret = info[i].info5.architecture;
631 break;
632 case 6:
633 driver_name_ret = info[i].info6.driver_name;
634 environment_ret = info[i].info6.architecture;
635 break;
636 case 7:
637 driver_name_ret = info[i].info7.driver_name;
638 break;
639 case 8:
640 driver_name_ret = info[i].info8.driver_name;
641 environment_ret = info[i].info8.architecture;
642 break;
643 default:
644 break;
646 if (environment_ret) {
647 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
649 if (strequal(driver_name, driver_name_ret)) {
650 if (info_p) {
651 *info_p = info[i];
653 return true;
657 return false;
660 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
661 void *private_data)
663 struct test_spoolss_context *ctx =
664 talloc_get_type_abort(private_data, struct test_spoolss_context);
665 struct dcerpc_pipe *p = ctx->spoolss_pipe;
666 struct dcerpc_binding_handle *b = p->binding_handle;
667 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
668 uint16_t buffer_sizes[] = { 0, 1024, 6040, 0xffff };
669 int i, j, a;
671 /* FIXME: gd, come back and fix "" as server, and handle
672 * priority of returned error codes in torture test and samba 3
673 * server */
674 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
675 const char *environments[2];
677 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
678 environments[1] = ctx->environment;
680 for (a=0;a<ARRAY_SIZE(environments);a++) {
682 for (i=0;i<ARRAY_SIZE(buffer_sizes);i++) {
683 torture_assert(tctx,
684 test_EnumPrinterDrivers_buffers(tctx, b, server_name,
685 environments[a], 3,
686 buffer_sizes[i],
687 NULL, NULL),
688 "failed to enumerate drivers");
691 for (i=0;i<ARRAY_SIZE(levels);i++) {
692 int level = levels[i];
693 uint32_t count;
694 union spoolss_DriverInfo *info;
696 torture_assert(tctx,
697 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
698 "failed to enumerate drivers");
700 ctx->driver_count[level] = count;
701 ctx->drivers[level] = info;
704 for (i=1;i<ARRAY_SIZE(levels);i++) {
705 int level = levels[i];
706 int old_level = levels[i-1];
708 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
709 "EnumPrinterDrivers invalid value");
712 for (i=0;i<ARRAY_SIZE(levels);i++) {
713 int level = levels[i];
715 for (j=0;j<ctx->driver_count[level - 1];j++) {
716 union spoolss_DriverInfo *cur = &ctx->drivers[level - 1][j];
717 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
719 switch (level) {
720 case 1:
721 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
722 break;
723 case 2:
724 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
725 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
726 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
727 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
728 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
729 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
730 break;
731 case 3:
732 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
733 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
734 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
735 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
736 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
737 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
738 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
739 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
740 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
741 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
742 break;
743 case 4:
744 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
745 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
746 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
747 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
748 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
749 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
750 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
751 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
752 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
753 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
754 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
755 break;
756 case 5:
757 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
758 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
759 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
760 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
761 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
762 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
763 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
764 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
765 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
766 break;
767 case 6:
768 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
769 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
770 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
771 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
772 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
773 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
774 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
775 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
776 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
777 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
778 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
779 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
780 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
781 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
782 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
783 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
784 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
785 break;
786 case 8:
787 /* level 8 is our reference, and it makes no sense to compare it to itself */
788 break;
794 return true;
797 static bool test_EnumMonitors(struct torture_context *tctx,
798 void *private_data)
800 struct test_spoolss_context *ctx =
801 talloc_get_type_abort(private_data, struct test_spoolss_context);
802 struct dcerpc_pipe *p = ctx->spoolss_pipe;
803 struct dcerpc_binding_handle *b = p->binding_handle;
804 NTSTATUS status;
805 struct spoolss_EnumMonitors r;
806 uint16_t levels[] = { 1, 2 };
807 int i, j;
809 for (i=0;i<ARRAY_SIZE(levels);i++) {
810 int level = levels[i];
811 DATA_BLOB blob;
812 uint32_t needed;
813 uint32_t count;
814 union spoolss_MonitorInfo *info;
816 r.in.servername = "";
817 r.in.level = level;
818 r.in.buffer = NULL;
819 r.in.offered = 0;
820 r.out.needed = &needed;
821 r.out.count = &count;
822 r.out.info = &info;
824 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
826 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
827 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
828 if (W_ERROR_IS_OK(r.out.result)) {
829 /* TODO: do some more checks here */
830 continue;
832 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
833 "EnumMonitors failed");
835 blob = data_blob_talloc_zero(ctx, needed);
836 r.in.buffer = &blob;
837 r.in.offered = needed;
839 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
840 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
842 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
844 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
846 ctx->monitor_count[level] = count;
847 ctx->monitors[level] = info;
850 for (i=1;i<ARRAY_SIZE(levels);i++) {
851 int level = levels[i];
852 int old_level = levels[i-1];
853 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
854 "EnumMonitors invalid value");
857 for (i=0;i<ARRAY_SIZE(levels);i++) {
858 int level = levels[i];
859 for (j=0;j<ctx->monitor_count[level];j++) {
860 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
861 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
862 switch (level) {
863 case 1:
864 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
865 break;
866 case 2:
867 torture_assert_str_equal(tctx, ref->info2.environment, ctx->environment, "invalid environment");
868 /* level 2 is our reference, and it makes no sense to compare it to itself */
869 break;
874 return true;
877 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
878 struct dcerpc_binding_handle *b,
879 const char *environment,
880 uint32_t level,
881 uint32_t *count_p,
882 union spoolss_PrintProcessorInfo **info_p,
883 WERROR expected_result)
885 struct spoolss_EnumPrintProcessors r;
886 DATA_BLOB blob;
887 uint32_t needed;
888 uint32_t count;
889 union spoolss_PrintProcessorInfo *info;
891 r.in.servername = "";
892 r.in.environment = environment;
893 r.in.level = level;
894 r.in.buffer = NULL;
895 r.in.offered = 0;
896 r.out.needed = &needed;
897 r.out.count = &count;
898 r.out.info = &info;
900 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
901 r.in.environment, r.in.level);
903 torture_assert_ntstatus_ok(tctx,
904 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
905 "EnumPrintProcessors failed");
906 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
907 blob = data_blob_talloc_zero(tctx, needed);
908 r.in.buffer = &blob;
909 r.in.offered = needed;
910 torture_assert_ntstatus_ok(tctx,
911 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
912 "EnumPrintProcessors failed");
914 torture_assert_werr_equal(tctx, r.out.result, expected_result,
915 "EnumPrintProcessors failed");
917 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
919 if (count_p) {
920 *count_p = count;
922 if (info_p) {
923 *info_p = info;
926 return true;
929 static bool test_EnumPrintProcessors(struct torture_context *tctx,
930 void *private_data)
932 struct test_spoolss_context *ctx =
933 talloc_get_type_abort(private_data, struct test_spoolss_context);
935 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
936 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
937 int i;
938 struct dcerpc_pipe *p = ctx->spoolss_pipe;
939 struct dcerpc_binding_handle *b = p->binding_handle;
941 torture_assert(tctx,
942 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
943 "test_EnumPrintProcessors_level failed");
945 for (i=0;i<ARRAY_SIZE(levels);i++) {
946 union spoolss_PrintProcessorInfo *info;
947 uint32_t count;
948 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
950 torture_assert(tctx,
951 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
952 "test_EnumPrintProcessors_level failed");
955 return true;
958 static bool test_EnumPrintProcessorDataTypes_level(struct torture_context *tctx,
959 struct dcerpc_binding_handle *b,
960 const char *print_processor_name,
961 uint32_t level,
962 uint32_t *count_p,
963 union spoolss_PrintProcDataTypesInfo **info_p,
964 WERROR expected_result)
966 struct spoolss_EnumPrintProcessorDataTypes r;
967 DATA_BLOB blob;
968 uint32_t needed;
969 uint32_t count;
970 union spoolss_PrintProcDataTypesInfo *info;
972 r.in.servername = "";
973 r.in.print_processor_name = print_processor_name;
974 r.in.level = level;
975 r.in.buffer = NULL;
976 r.in.offered = 0;
977 r.out.needed = &needed;
978 r.out.count = &count;
979 r.out.info = &info;
981 torture_comment(tctx, "Testing EnumPrintProcessorDataTypes(%s) level %u\n",
982 r.in.print_processor_name, r.in.level);
984 torture_assert_ntstatus_ok(tctx,
985 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b, tctx, &r),
986 "EnumPrintProcessorDataTypes failed");
987 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
988 blob = data_blob_talloc_zero(tctx, needed);
989 r.in.buffer = &blob;
990 r.in.offered = needed;
991 torture_assert_ntstatus_ok(tctx,
992 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b, tctx, &r),
993 "EnumPrintProcessorDataTypes failed");
995 torture_assert_werr_equal(tctx, r.out.result, expected_result,
996 "EnumPrintProcessorDataTypes failed");
998 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes, info, level, count, needed, 4);
1000 if (count_p) {
1001 *count_p = count;
1003 if (info_p) {
1004 *info_p = info;
1007 return true;
1010 static bool test_EnumPrintProcessorDataTypes(struct torture_context *tctx,
1011 void *private_data)
1013 struct test_spoolss_context *ctx =
1014 talloc_get_type_abort(private_data, struct test_spoolss_context);
1016 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
1017 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
1018 int i;
1019 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1020 struct dcerpc_binding_handle *b = p->binding_handle;
1022 torture_assert(tctx,
1023 test_EnumPrintProcessorDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
1024 "test_EnumPrintProcessorDataTypes_level failed");
1026 torture_assert(tctx,
1027 test_EnumPrintProcessorDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
1028 "test_EnumPrintProcessorDataTypes_level failed");
1030 for (i=0;i<ARRAY_SIZE(levels);i++) {
1031 int level = levels[i];
1032 uint32_t count;
1033 union spoolss_PrintProcDataTypesInfo *info;
1034 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1036 torture_assert(tctx,
1037 test_EnumPrintProcessorDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1038 "test_EnumPrintProcessorDataTypes_level failed");
1042 union spoolss_PrintProcessorInfo *info;
1043 uint32_t count;
1045 torture_assert(tctx,
1046 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1047 "test_EnumPrintProcessors_level failed");
1049 for (i=0; i < count; i++) {
1050 torture_assert(tctx,
1051 test_EnumPrintProcessorDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1052 "test_EnumPrintProcessorDataTypes_level failed");
1057 return true;
1060 static bool test_EnumPrinters(struct torture_context *tctx,
1061 void *private_data)
1063 struct test_spoolss_context *ctx =
1064 talloc_get_type_abort(private_data, struct test_spoolss_context);
1065 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1066 struct dcerpc_binding_handle *b = p->binding_handle;
1067 struct spoolss_EnumPrinters r;
1068 NTSTATUS status;
1069 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1070 int i, j;
1072 for (i=0;i<ARRAY_SIZE(levels);i++) {
1073 int level = levels[i];
1074 DATA_BLOB blob;
1075 uint32_t needed;
1076 uint32_t count;
1077 union spoolss_PrinterInfo *info;
1079 r.in.flags = PRINTER_ENUM_LOCAL;
1080 r.in.server = "";
1081 r.in.level = level;
1082 r.in.buffer = NULL;
1083 r.in.offered = 0;
1084 r.out.needed = &needed;
1085 r.out.count = &count;
1086 r.out.info = &info;
1088 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1090 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1091 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1092 if (W_ERROR_IS_OK(r.out.result)) {
1093 /* TODO: do some more checks here */
1094 continue;
1096 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1097 "EnumPrinters unexpected return code");
1099 blob = data_blob_talloc_zero(ctx, needed);
1100 r.in.buffer = &blob;
1101 r.in.offered = needed;
1103 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1104 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1106 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1108 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1110 ctx->printer_count[level] = count;
1111 ctx->printers[level] = info;
1114 for (i=1;i<ARRAY_SIZE(levels);i++) {
1115 int level = levels[i];
1116 int old_level = levels[i-1];
1117 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1118 "EnumPrinters invalid value");
1121 for (i=0;i<ARRAY_SIZE(levels);i++) {
1122 int level = levels[i];
1123 for (j=0;j<ctx->printer_count[level];j++) {
1124 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1125 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1126 switch (level) {
1127 case 0:
1128 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1129 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1130 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1131 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1132 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1133 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1134 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1135 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1136 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1137 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1138 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1139 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1140 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1141 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1142 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1143 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1144 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1145 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1146 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1147 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1148 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1149 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1150 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1151 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1152 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1153 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1154 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1155 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1156 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1157 break;
1158 case 1:
1159 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1160 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1161 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1162 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1163 break;
1164 case 2:
1165 /* level 2 is our reference, and it makes no sense to compare it to itself */
1166 break;
1167 case 4:
1168 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1169 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1170 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1171 break;
1172 case 5:
1173 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1174 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1175 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1176 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1177 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1178 break;
1183 /* TODO:
1184 * - verify that the port of a printer was in the list returned by EnumPorts
1187 return true;
1190 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1191 struct dcerpc_binding_handle *b,
1192 struct policy_handle *handle,
1193 const char *driver_name,
1194 const char *environment);
1196 bool test_GetPrinter_level_exp(struct torture_context *tctx,
1197 struct dcerpc_binding_handle *b,
1198 struct policy_handle *handle,
1199 uint32_t level,
1200 WERROR expected_werror,
1201 union spoolss_PrinterInfo *info)
1203 struct spoolss_GetPrinter r;
1204 uint32_t needed;
1206 r.in.handle = handle;
1207 r.in.level = level;
1208 r.in.buffer = NULL;
1209 r.in.offered = 0;
1210 r.out.needed = &needed;
1212 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1214 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1215 "GetPrinter failed");
1217 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1218 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1219 r.in.buffer = &blob;
1220 r.in.offered = needed;
1222 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1223 "GetPrinter failed");
1226 torture_assert_werr_equal(tctx,
1227 r.out.result, expected_werror,
1228 "GetPrinter failed");
1230 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1232 if (info && r.out.info) {
1233 *info = *r.out.info;
1236 return true;
1239 bool test_GetPrinter_level(struct torture_context *tctx,
1240 struct dcerpc_binding_handle *b,
1241 struct policy_handle *handle,
1242 uint32_t level,
1243 union spoolss_PrinterInfo *info)
1245 return test_GetPrinter_level_exp(tctx, b, handle, level, WERR_OK, info);
1248 static bool test_GetPrinter(struct torture_context *tctx,
1249 struct dcerpc_binding_handle *b,
1250 struct policy_handle *handle,
1251 const char *environment)
1253 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1254 int i;
1256 for (i=0;i<ARRAY_SIZE(levels);i++) {
1258 union spoolss_PrinterInfo info;
1260 ZERO_STRUCT(info);
1262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1263 "failed to call GetPrinter");
1265 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1266 torture_assert(tctx,
1267 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1268 "failed to call test_GetPrinterDriver2");
1272 return true;
1275 static bool test_SetPrinter(struct torture_context *tctx,
1276 struct dcerpc_binding_handle *b,
1277 struct policy_handle *handle,
1278 struct spoolss_SetPrinterInfoCtr *info_ctr,
1279 struct spoolss_DevmodeContainer *devmode_ctr,
1280 struct sec_desc_buf *secdesc_ctr,
1281 enum spoolss_PrinterControl command)
1283 struct spoolss_SetPrinter r;
1285 r.in.handle = handle;
1286 r.in.info_ctr = info_ctr;
1287 r.in.devmode_ctr = devmode_ctr;
1288 r.in.secdesc_ctr = secdesc_ctr;
1289 r.in.command = command;
1291 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1293 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1294 "failed to call SetPrinter");
1295 torture_assert(tctx, (W_ERROR_EQUAL(r.out.result, WERR_OK)
1296 || W_ERROR_EQUAL(r.out.result, WERR_IO_PENDING)),
1297 "SetPrinter failed");
1299 return true;
1302 static bool test_SetPrinter_errors(struct torture_context *tctx,
1303 struct dcerpc_binding_handle *b,
1304 struct policy_handle *handle)
1306 struct spoolss_SetPrinter r;
1307 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1308 int i;
1310 struct spoolss_SetPrinterInfoCtr info_ctr;
1311 struct spoolss_DevmodeContainer devmode_ctr;
1312 struct sec_desc_buf secdesc_ctr;
1314 info_ctr.level = 0;
1315 info_ctr.info.info0 = NULL;
1317 ZERO_STRUCT(devmode_ctr);
1318 ZERO_STRUCT(secdesc_ctr);
1320 r.in.handle = handle;
1321 r.in.info_ctr = &info_ctr;
1322 r.in.devmode_ctr = &devmode_ctr;
1323 r.in.secdesc_ctr = &secdesc_ctr;
1324 r.in.command = 0;
1326 torture_comment(tctx, "Testing SetPrinter all zero\n");
1328 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1329 "failed to call SetPrinter");
1330 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
1331 "failed to call SetPrinter");
1333 again:
1334 for (i=0; i < ARRAY_SIZE(levels); i++) {
1336 struct spoolss_SetPrinterInfo0 info0;
1337 struct spoolss_SetPrinterInfo1 info1;
1338 struct spoolss_SetPrinterInfo2 info2;
1339 struct spoolss_SetPrinterInfo3 info3;
1340 struct spoolss_SetPrinterInfo4 info4;
1341 struct spoolss_SetPrinterInfo5 info5;
1342 struct spoolss_SetPrinterInfo6 info6;
1343 struct spoolss_SetPrinterInfo7 info7;
1344 struct spoolss_SetPrinterInfo8 info8;
1345 struct spoolss_SetPrinterInfo9 info9;
1348 info_ctr.level = levels[i];
1349 switch (levels[i]) {
1350 case 0:
1351 ZERO_STRUCT(info0);
1352 info_ctr.info.info0 = &info0;
1353 break;
1354 case 1:
1355 ZERO_STRUCT(info1);
1356 info_ctr.info.info1 = &info1;
1357 break;
1358 case 2:
1359 ZERO_STRUCT(info2);
1360 info_ctr.info.info2 = &info2;
1361 break;
1362 case 3:
1363 ZERO_STRUCT(info3);
1364 info_ctr.info.info3 = &info3;
1365 break;
1366 case 4:
1367 ZERO_STRUCT(info4);
1368 info_ctr.info.info4 = &info4;
1369 break;
1370 case 5:
1371 ZERO_STRUCT(info5);
1372 info_ctr.info.info5 = &info5;
1373 break;
1374 case 6:
1375 ZERO_STRUCT(info6);
1376 info_ctr.info.info6 = &info6;
1377 break;
1378 case 7:
1379 ZERO_STRUCT(info7);
1380 info_ctr.info.info7 = &info7;
1381 break;
1382 case 8:
1383 ZERO_STRUCT(info8);
1384 info_ctr.info.info8 = &info8;
1385 break;
1386 case 9:
1387 ZERO_STRUCT(info9);
1388 info_ctr.info.info9 = &info9;
1389 break;
1392 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1393 info_ctr.level, r.in.command);
1395 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1396 "failed to call SetPrinter");
1398 switch (r.in.command) {
1399 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1400 /* is ignored for all levels other then 0 */
1401 if (info_ctr.level > 0) {
1402 /* ignored then */
1403 break;
1405 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1406 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1407 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1408 if (info_ctr.level > 0) {
1409 /* is invalid for all levels other then 0 */
1410 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1411 "unexpected error code returned");
1412 continue;
1413 } else {
1414 torture_assert_werr_ok(tctx, r.out.result,
1415 "failed to call SetPrinter with non 0 command");
1416 continue;
1418 break;
1420 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1421 /* FIXME: gd needs further investigation */
1422 default:
1423 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1424 "unexpected error code returned");
1425 continue;
1428 switch (info_ctr.level) {
1429 case 1:
1430 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL,
1431 "unexpected error code returned");
1432 break;
1433 case 2:
1434 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1435 "unexpected error code returned");
1436 break;
1437 case 3:
1438 case 4:
1439 case 5:
1440 case 7:
1441 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
1442 "unexpected error code returned");
1443 break;
1444 case 9:
1445 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1446 "unexpected error code returned");
1447 break;
1448 default:
1449 torture_assert_werr_ok(tctx, r.out.result,
1450 "failed to call SetPrinter");
1451 break;
1455 if (r.in.command < 5) {
1456 r.in.command++;
1457 goto again;
1460 return true;
1463 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1465 if ((r->level == 2) && (r->info.info2)) {
1466 r->info.info2->secdesc_ptr = 0;
1467 r->info.info2->devmode_ptr = 0;
1471 static bool test_PrinterInfo(struct torture_context *tctx,
1472 struct dcerpc_binding_handle *b,
1473 struct policy_handle *handle)
1475 NTSTATUS status;
1476 struct spoolss_SetPrinter s;
1477 struct spoolss_GetPrinter q;
1478 struct spoolss_GetPrinter q0;
1479 struct spoolss_SetPrinterInfoCtr info_ctr;
1480 union spoolss_PrinterInfo info;
1481 struct spoolss_DevmodeContainer devmode_ctr;
1482 struct sec_desc_buf secdesc_ctr;
1483 uint32_t needed;
1484 bool ret = true;
1485 int i;
1487 uint32_t status_list[] = {
1488 /* these do not stick
1489 PRINTER_STATUS_PAUSED,
1490 PRINTER_STATUS_ERROR,
1491 PRINTER_STATUS_PENDING_DELETION, */
1492 PRINTER_STATUS_PAPER_JAM,
1493 PRINTER_STATUS_PAPER_OUT,
1494 PRINTER_STATUS_MANUAL_FEED,
1495 PRINTER_STATUS_PAPER_PROBLEM,
1496 PRINTER_STATUS_OFFLINE,
1497 PRINTER_STATUS_IO_ACTIVE,
1498 PRINTER_STATUS_BUSY,
1499 PRINTER_STATUS_PRINTING,
1500 PRINTER_STATUS_OUTPUT_BIN_FULL,
1501 PRINTER_STATUS_NOT_AVAILABLE,
1502 PRINTER_STATUS_WAITING,
1503 PRINTER_STATUS_PROCESSING,
1504 PRINTER_STATUS_INITIALIZING,
1505 PRINTER_STATUS_WARMING_UP,
1506 PRINTER_STATUS_TONER_LOW,
1507 PRINTER_STATUS_NO_TONER,
1508 PRINTER_STATUS_PAGE_PUNT,
1509 PRINTER_STATUS_USER_INTERVENTION,
1510 PRINTER_STATUS_OUT_OF_MEMORY,
1511 PRINTER_STATUS_DOOR_OPEN,
1512 PRINTER_STATUS_SERVER_UNKNOWN,
1513 PRINTER_STATUS_POWER_SAVE,
1514 /* these do not stick
1515 0x02000000,
1516 0x04000000,
1517 0x08000000,
1518 0x10000000,
1519 0x20000000,
1520 0x40000000,
1521 0x80000000 */
1523 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1524 uint32_t attribute_list[] = {
1525 PRINTER_ATTRIBUTE_QUEUED,
1526 /* fails with WERR_INVALID_DATATYPE:
1527 PRINTER_ATTRIBUTE_DIRECT, */
1528 /* does not stick
1529 PRINTER_ATTRIBUTE_DEFAULT, */
1530 PRINTER_ATTRIBUTE_SHARED,
1531 /* does not stick
1532 PRINTER_ATTRIBUTE_NETWORK, */
1533 PRINTER_ATTRIBUTE_HIDDEN,
1534 PRINTER_ATTRIBUTE_LOCAL,
1535 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1536 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1537 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1538 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1539 /* does not stick
1540 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1541 /* fails with WERR_INVALID_DATATYPE:
1542 PRINTER_ATTRIBUTE_RAW_ONLY, */
1543 /* these do not stick
1544 PRINTER_ATTRIBUTE_PUBLISHED,
1545 PRINTER_ATTRIBUTE_FAX,
1546 PRINTER_ATTRIBUTE_TS,
1547 0x00010000,
1548 0x00020000,
1549 0x00040000,
1550 0x00080000,
1551 0x00100000,
1552 0x00200000,
1553 0x00400000,
1554 0x00800000,
1555 0x01000000,
1556 0x02000000,
1557 0x04000000,
1558 0x08000000,
1559 0x10000000,
1560 0x20000000,
1561 0x40000000,
1562 0x80000000 */
1565 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1568 ZERO_STRUCT(devmode_ctr);
1569 ZERO_STRUCT(secdesc_ctr);
1571 s.in.handle = handle;
1572 s.in.command = 0;
1573 s.in.info_ctr = &info_ctr;
1574 s.in.devmode_ctr = &devmode_ctr;
1575 s.in.secdesc_ctr = &secdesc_ctr;
1577 q.in.handle = handle;
1578 q.out.info = &info;
1579 q0 = q;
1581 #define TESTGETCALL(call, r) \
1582 r.in.buffer = NULL; \
1583 r.in.offered = 0;\
1584 r.out.needed = &needed; \
1585 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1586 if (!NT_STATUS_IS_OK(status)) { \
1587 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1588 r.in.level, nt_errstr(status), __location__); \
1589 ret = false; \
1590 break; \
1592 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1593 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1594 r.in.buffer = &blob; \
1595 r.in.offered = needed; \
1597 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1598 if (!NT_STATUS_IS_OK(status)) { \
1599 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1600 r.in.level, nt_errstr(status), __location__); \
1601 ret = false; \
1602 break; \
1604 if (!W_ERROR_IS_OK(r.out.result)) { \
1605 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1606 r.in.level, win_errstr(r.out.result), __location__); \
1607 ret = false; \
1608 break; \
1612 #define TESTSETCALL_EXP(call, r, err) \
1613 clear_info2(&info_ctr);\
1614 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1615 if (!NT_STATUS_IS_OK(status)) { \
1616 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1617 r.in.info_ctr->level, nt_errstr(status), __location__); \
1618 ret = false; \
1619 break; \
1621 if (!W_ERROR_IS_OK(err)) { \
1622 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1623 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1624 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1625 ret = false; \
1627 break; \
1629 if (!W_ERROR_IS_OK(r.out.result)) { \
1630 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1631 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1632 ret = false; \
1633 break; \
1636 #define TESTSETCALL(call, r) \
1637 TESTSETCALL_EXP(call, r, WERR_OK)
1639 #define STRING_EQUAL(s1, s2, field) \
1640 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1641 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1642 #field, s2, __location__); \
1643 ret = false; \
1644 break; \
1647 #define MEM_EQUAL(s1, s2, length, field) \
1648 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1649 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1650 #field, (const char *)s2, __location__); \
1651 ret = false; \
1652 break; \
1655 #define INT_EQUAL(i1, i2, field) \
1656 if (i1 != i2) { \
1657 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1658 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1659 ret = false; \
1660 break; \
1663 #define SD_EQUAL(sd1, sd2, field) \
1664 if (!security_descriptor_equal(sd1, sd2)) { \
1665 torture_comment(tctx, "Failed to set %s (%s)\n", \
1666 #field, __location__); \
1667 ret = false; \
1668 break; \
1671 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1672 void *p; \
1673 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1674 q.in.level = lvl1; \
1675 TESTGETCALL(GetPrinter, q) \
1676 info_ctr.level = lvl1; \
1677 p = (void *)&q.out.info->info ## lvl1; \
1678 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1679 info_ctr.info.info ## lvl1->field1 = value;\
1680 TESTSETCALL_EXP(SetPrinter, s, err) \
1681 info_ctr.info.info ## lvl1->field1 = ""; \
1682 TESTGETCALL(GetPrinter, q) \
1683 info_ctr.info.info ## lvl1->field1 = value; \
1684 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1685 q.in.level = lvl2; \
1686 TESTGETCALL(GetPrinter, q) \
1687 p = (void *)&q.out.info->info ## lvl2; \
1688 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1689 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1690 } while (0)
1692 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1693 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1694 } while (0);
1696 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1697 void *p; \
1698 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1699 q.in.level = lvl1; \
1700 TESTGETCALL(GetPrinter, q) \
1701 info_ctr.level = lvl1; \
1702 p = (void *)&q.out.info->info ## lvl1; \
1703 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1704 info_ctr.info.info ## lvl1->field1 = value; \
1705 TESTSETCALL(SetPrinter, s) \
1706 info_ctr.info.info ## lvl1->field1 = 0; \
1707 TESTGETCALL(GetPrinter, q) \
1708 p = (void *)&q.out.info->info ## lvl1; \
1709 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1710 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1711 q.in.level = lvl2; \
1712 TESTGETCALL(GetPrinter, q) \
1713 p = (void *)&q.out.info->info ## lvl2; \
1714 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1715 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1716 } while (0)
1718 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1719 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1720 } while (0)
1722 q0.in.level = 0;
1723 do { TESTGETCALL(GetPrinter, q0) } while (0);
1725 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1726 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1728 /* level 0 printername does not stick */
1729 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1730 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1731 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1732 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1733 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1734 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1735 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1736 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1737 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1738 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1739 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1740 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1741 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1742 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1743 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1745 /* servername can be set but does not stick
1746 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1747 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1748 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1751 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1752 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1753 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1754 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1755 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1757 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1758 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1759 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1760 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1761 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1762 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1763 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1764 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1765 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1766 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1768 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1769 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1770 attribute_list[i],
1771 (attribute_list[i] | default_attribute)
1772 ); */
1773 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1774 attribute_list[i],
1775 (attribute_list[i] | default_attribute)
1777 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1778 attribute_list[i],
1779 (attribute_list[i] | default_attribute)
1781 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1782 attribute_list[i],
1783 (attribute_list[i] | default_attribute)
1785 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1786 attribute_list[i],
1787 (attribute_list[i] | default_attribute)
1788 ); */
1789 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1790 attribute_list[i],
1791 (attribute_list[i] | default_attribute)
1793 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1794 attribute_list[i],
1795 (attribute_list[i] | default_attribute)
1797 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1798 attribute_list[i],
1799 (attribute_list[i] | default_attribute)
1801 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1802 attribute_list[i],
1803 (attribute_list[i] | default_attribute)
1804 ); */
1805 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1806 attribute_list[i],
1807 (attribute_list[i] | default_attribute)
1809 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1810 attribute_list[i],
1811 (attribute_list[i] | default_attribute)
1813 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1814 attribute_list[i],
1815 (attribute_list[i] | default_attribute)
1819 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1820 /* level 2 sets do not stick
1821 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1822 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1823 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1824 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1825 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1826 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1829 /* priorities need to be between 0 and 99
1830 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1831 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1832 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1833 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1834 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1835 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1836 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1837 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1838 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1840 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1841 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1843 /* does not stick
1844 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1845 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1847 /* does not stick
1848 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1849 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1851 /* FIXME: gd also test devmode and secdesc behavior */
1854 /* verify composition of level 1 description field */
1855 const char *description;
1856 const char *tmp;
1858 q0.in.level = 1;
1859 do { TESTGETCALL(GetPrinter, q0) } while (0);
1861 description = talloc_strdup(tctx, q0.out.info->info1.description);
1863 q0.in.level = 2;
1864 do { TESTGETCALL(GetPrinter, q0) } while (0);
1866 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1867 q0.out.info->info2.printername,
1868 q0.out.info->info2.drivername,
1869 q0.out.info->info2.location);
1871 do { STRING_EQUAL(description, tmp, "description")} while (0);
1874 return ret;
1877 static bool test_security_descriptor_equal(struct torture_context *tctx,
1878 const struct security_descriptor *sd1,
1879 const struct security_descriptor *sd2)
1881 if (sd1 == sd2) {
1882 return true;
1885 if (!sd1 || !sd2) {
1886 torture_comment(tctx, "%s\n", __location__);
1887 return false;
1890 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1891 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1893 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1894 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1896 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1897 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1898 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1899 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1900 return false;
1902 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1903 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1904 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1905 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1906 return false;
1909 return true;
1912 static bool test_sd_set_level(struct torture_context *tctx,
1913 struct dcerpc_binding_handle *b,
1914 struct policy_handle *handle,
1915 uint32_t level,
1916 struct security_descriptor *sd)
1918 struct spoolss_SetPrinterInfoCtr info_ctr;
1919 struct spoolss_DevmodeContainer devmode_ctr;
1920 struct sec_desc_buf secdesc_ctr;
1921 union spoolss_SetPrinterInfo sinfo;
1922 union spoolss_PrinterInfo info;
1923 struct spoolss_SetPrinterInfo3 info3;
1925 ZERO_STRUCT(devmode_ctr);
1926 ZERO_STRUCT(secdesc_ctr);
1928 switch (level) {
1929 case 2: {
1930 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1933 info_ctr.level = 2;
1934 info_ctr.info = sinfo;
1936 break;
1938 case 3: {
1940 info3.sec_desc_ptr = 0;
1942 info_ctr.level = 3;
1943 info_ctr.info.info3 = &info3;
1945 break;
1947 default:
1948 return false;
1951 secdesc_ctr.sd = sd;
1953 torture_assert(tctx,
1954 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1956 return true;
1959 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1960 struct dcerpc_binding_handle *b,
1961 struct policy_handle *handle)
1963 union spoolss_PrinterInfo info;
1964 struct security_descriptor *sd1, *sd2;
1965 int i;
1967 /* just compare level 2 and level 3 */
1969 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1971 sd1 = info.info2.secdesc;
1973 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1975 sd2 = info.info3.secdesc;
1977 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1978 "SD level 2 != SD level 3");
1981 /* query level 2, set level 2, query level 2 */
1983 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1985 sd1 = info.info2.secdesc;
1987 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1989 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1991 sd2 = info.info2.secdesc;
1992 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1993 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1994 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1997 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1998 "SD level 2 != SD level 2 after SD has been set via level 2");
2001 /* query level 2, set level 3, query level 2 */
2003 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2005 sd1 = info.info2.secdesc;
2007 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
2009 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2011 sd2 = info.info2.secdesc;
2013 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
2014 "SD level 2 != SD level 2 after SD has been set via level 3");
2016 /* set modified sd level 3, query level 2 */
2018 for (i=0; i < 93; i++) {
2019 struct security_ace a;
2020 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
2021 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
2022 a.flags = 0;
2023 a.size = 0; /* autogenerated */
2024 a.access_mask = 0;
2025 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
2026 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
2029 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
2031 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2032 sd2 = info.info2.secdesc;
2034 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
2035 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
2036 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
2039 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
2040 "modified SD level 2 != SD level 2 after SD has been set via level 3");
2043 return true;
2047 * wrapper call that saves original sd, runs tests, and restores sd
2050 static bool test_PrinterInfo_SD(struct torture_context *tctx,
2051 struct dcerpc_binding_handle *b,
2052 struct policy_handle *handle)
2054 union spoolss_PrinterInfo info;
2055 struct security_descriptor *sd;
2056 bool ret = true;
2058 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2060 /* save original sd */
2062 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2063 "failed to get initial security descriptor");
2065 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2067 /* run tests */
2069 ret = test_PrinterInfo_SDs(tctx, b, handle);
2071 /* restore original sd */
2073 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2074 "failed to restore initial security descriptor");
2076 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2077 ret ? "succeeded" : "failed");
2080 return ret;
2083 static bool test_devmode_set_level(struct torture_context *tctx,
2084 struct dcerpc_binding_handle *b,
2085 struct policy_handle *handle,
2086 uint32_t level,
2087 struct spoolss_DeviceMode *devmode)
2089 struct spoolss_SetPrinterInfoCtr info_ctr;
2090 struct spoolss_DevmodeContainer devmode_ctr;
2091 struct sec_desc_buf secdesc_ctr;
2092 union spoolss_SetPrinterInfo sinfo;
2094 ZERO_STRUCT(devmode_ctr);
2095 ZERO_STRUCT(secdesc_ctr);
2097 switch (level) {
2098 case 2: {
2099 union spoolss_PrinterInfo info;
2100 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2101 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2103 info_ctr.level = 2;
2104 info_ctr.info = sinfo;
2106 break;
2108 case 8: {
2109 struct spoolss_SetPrinterInfo8 info8;
2111 info8.devmode_ptr = 0;
2113 info_ctr.level = 8;
2114 info_ctr.info.info8 = &info8;
2116 break;
2118 default:
2119 return false;
2122 devmode_ctr.devmode = devmode;
2124 torture_assert(tctx,
2125 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2127 return true;
2131 static bool test_devicemode_equal(struct torture_context *tctx,
2132 const struct spoolss_DeviceMode *d1,
2133 const struct spoolss_DeviceMode *d2)
2135 if (d1 == d2) {
2136 return true;
2139 if (!d1 || !d2) {
2140 torture_comment(tctx, "%s\n", __location__);
2141 return false;
2143 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2144 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2145 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2146 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2147 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2148 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2149 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2150 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2151 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2152 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2153 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2154 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2155 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2156 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2157 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2158 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2159 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2160 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2161 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2162 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2163 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2164 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2165 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2166 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2167 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2168 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2169 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2170 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2171 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2172 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2173 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2174 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2175 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2176 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2177 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2179 return true;
2182 static bool test_devicemode_full(struct torture_context *tctx,
2183 struct dcerpc_binding_handle *b,
2184 struct policy_handle *handle)
2186 struct spoolss_SetPrinter s;
2187 struct spoolss_GetPrinter q;
2188 struct spoolss_SetPrinterInfoCtr info_ctr;
2189 struct spoolss_SetPrinterInfo8 info8;
2190 union spoolss_PrinterInfo info;
2191 struct spoolss_DevmodeContainer devmode_ctr;
2192 struct sec_desc_buf secdesc_ctr;
2193 uint32_t needed;
2194 bool ret = true;
2195 NTSTATUS status;
2197 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2198 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2199 q.in.level = lvl1; \
2200 TESTGETCALL(GetPrinter, q) \
2201 info_ctr.level = lvl1; \
2202 if (lvl1 == 2) {\
2203 void *p = (void *)&q.out.info->info ## lvl1; \
2204 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
2205 } else if (lvl1 == 8) {\
2206 info_ctr.info.info ## lvl1 = &info8; \
2208 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2209 devmode_ctr.devmode->field1 = value; \
2210 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2211 if (W_ERROR_IS_OK(expected_result)) { \
2212 TESTGETCALL(GetPrinter, q) \
2213 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2214 q.in.level = lvl2; \
2215 TESTGETCALL(GetPrinter, q) \
2216 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2218 } while (0)
2220 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2221 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2222 } while (0)
2224 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2225 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2226 } while (0)
2228 ZERO_STRUCT(devmode_ctr);
2229 ZERO_STRUCT(secdesc_ctr);
2230 ZERO_STRUCT(info8);
2232 s.in.handle = handle;
2233 s.in.command = 0;
2234 s.in.info_ctr = &info_ctr;
2235 s.in.devmode_ctr = &devmode_ctr;
2236 s.in.secdesc_ctr = &secdesc_ctr;
2238 q.in.handle = handle;
2239 q.out.info = &info;
2241 #if 0
2242 const char *devicename;/* [charset(UTF16)] */
2243 enum spoolss_DeviceModeSpecVersion specversion;
2244 uint16_t driverversion;
2245 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2246 uint32_t fields;
2247 #endif
2248 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAMETER);
2249 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAMETER);
2250 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAMETER);
2251 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
2252 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2254 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2255 torture_assert(tctx,
2256 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2257 "failed to set devmode");
2259 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
2260 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2262 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2263 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2264 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2265 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2266 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2267 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2268 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2269 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2270 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2271 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2272 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2273 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2274 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2275 #if 0
2276 const char *formname;/* [charset(UTF16)] */
2277 #endif
2278 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2279 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2280 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2281 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2282 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2283 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2284 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2285 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2286 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2287 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2288 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2289 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2290 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2291 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2293 return ret;
2296 static bool call_OpenPrinterEx(struct torture_context *tctx,
2297 struct dcerpc_pipe *p,
2298 const char *name,
2299 struct spoolss_DeviceMode *devmode,
2300 struct policy_handle *handle);
2302 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2303 struct dcerpc_pipe *p,
2304 struct policy_handle *handle,
2305 const char *name)
2307 union spoolss_PrinterInfo info;
2308 struct spoolss_DeviceMode *devmode;
2309 struct spoolss_DeviceMode *devmode2;
2310 struct policy_handle handle_devmode;
2311 struct dcerpc_binding_handle *b = p->binding_handle;
2313 /* simply compare level8 and level2 devmode */
2315 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2317 devmode = info.info8.devmode;
2319 if (devmode && devmode->size == 0) {
2320 torture_fail(tctx,
2321 "devmode of zero size!");
2324 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2326 devmode2 = info.info2.devmode;
2328 if (devmode2 && devmode2->size == 0) {
2329 torture_fail(tctx,
2330 "devmode of zero size!");
2333 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2334 "DM level 8 != DM level 2");
2337 /* set devicemode level 8 and see if it persists */
2339 devmode->copies = 93;
2340 devmode->formname = talloc_strdup(tctx, "Legal");
2342 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2344 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2346 devmode2 = info.info8.devmode;
2348 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2349 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2351 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2353 devmode2 = info.info2.devmode;
2355 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2356 "modified DM level 8 != DM level 2");
2359 /* set devicemode level 2 and see if it persists */
2361 devmode->copies = 39;
2362 devmode->formname = talloc_strdup(tctx, "Executive");
2364 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2366 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2368 devmode2 = info.info8.devmode;
2370 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2371 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2373 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2375 devmode2 = info.info2.devmode;
2377 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2378 "modified DM level 8 != DM level 2");
2381 /* check every single bit in public part of devicemode */
2383 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2384 "failed to set every single devicemode component");
2387 /* change formname upon open and see if it persists in getprinter calls */
2389 devmode->formname = talloc_strdup(tctx, "A4");
2390 devmode->copies = 42;
2392 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2393 "failed to open printer handle");
2395 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2397 devmode2 = info.info8.devmode;
2399 if (strequal(devmode->devicename, devmode2->devicename)) {
2400 torture_warning(tctx, "devicenames are the same\n");
2401 } else {
2402 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2403 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2406 if (strequal(devmode->formname, devmode2->formname)) {
2407 torture_warning(tctx, "formname are the same\n");
2408 } else {
2409 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2410 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2413 if (devmode->copies == devmode2->copies) {
2414 torture_warning(tctx, "copies are the same\n");
2415 } else {
2416 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2417 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2420 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2422 devmode2 = info.info2.devmode;
2424 if (strequal(devmode->devicename, devmode2->devicename)) {
2425 torture_warning(tctx, "devicenames are the same\n");
2426 } else {
2427 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2428 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2431 if (strequal(devmode->formname, devmode2->formname)) {
2432 torture_warning(tctx, "formname is the same\n");
2433 } else {
2434 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2435 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2438 if (devmode->copies == devmode2->copies) {
2439 torture_warning(tctx, "copies are the same\n");
2440 } else {
2441 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2442 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2445 test_ClosePrinter(tctx, b, &handle_devmode);
2447 return true;
2451 * wrapper call that saves original devmode, runs tests, and restores devmode
2454 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2455 struct dcerpc_pipe *p,
2456 struct policy_handle *handle,
2457 const char *name,
2458 struct spoolss_DeviceMode *addprinter_devmode)
2460 union spoolss_PrinterInfo info;
2461 struct spoolss_DeviceMode *devmode;
2462 bool ret = true;
2463 struct dcerpc_binding_handle *b = p->binding_handle;
2465 torture_comment(tctx, "Testing Printer Devicemodes\n");
2467 /* save original devmode */
2469 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2470 "failed to get initial global devicemode");
2472 devmode = info.info8.devmode;
2474 if (devmode && devmode->size == 0) {
2475 torture_fail(tctx,
2476 "devmode of zero size!");
2479 if (addprinter_devmode) {
2480 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2481 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2485 /* run tests */
2487 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2489 /* restore original devmode */
2491 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2492 "failed to restore initial global device mode");
2494 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2495 ret ? "succeeded" : "failed");
2498 return ret;
2501 bool test_ClosePrinter(struct torture_context *tctx,
2502 struct dcerpc_binding_handle *b,
2503 struct policy_handle *handle)
2505 NTSTATUS status;
2506 struct spoolss_ClosePrinter r;
2508 r.in.handle = handle;
2509 r.out.handle = handle;
2511 torture_comment(tctx, "Testing ClosePrinter\n");
2513 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2514 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2515 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2517 return true;
2520 static bool test_GetForm_args(struct torture_context *tctx,
2521 struct dcerpc_binding_handle *b,
2522 struct policy_handle *handle,
2523 const char *form_name,
2524 uint32_t level,
2525 union spoolss_FormInfo *info_p)
2527 NTSTATUS status;
2528 struct spoolss_GetForm r;
2529 uint32_t needed;
2531 r.in.handle = handle;
2532 r.in.form_name = form_name;
2533 r.in.level = level;
2534 r.in.buffer = NULL;
2535 r.in.offered = 0;
2536 r.out.needed = &needed;
2538 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2540 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2541 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2543 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2544 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2545 r.in.buffer = &blob;
2546 r.in.offered = needed;
2547 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2548 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2550 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2552 torture_assert(tctx, r.out.info, "No form info returned");
2555 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2557 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2559 if (info_p) {
2560 *info_p = *r.out.info;
2563 return true;
2566 static bool test_GetForm(struct torture_context *tctx,
2567 struct dcerpc_binding_handle *b,
2568 struct policy_handle *handle,
2569 const char *form_name,
2570 uint32_t level)
2572 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2575 static bool test_EnumForms(struct torture_context *tctx,
2576 struct dcerpc_binding_handle *b,
2577 struct policy_handle *handle,
2578 bool print_server,
2579 uint32_t level,
2580 uint32_t *count_p,
2581 union spoolss_FormInfo **info_p)
2583 struct spoolss_EnumForms r;
2584 uint32_t needed;
2585 uint32_t count;
2586 union spoolss_FormInfo *info;
2588 r.in.handle = handle;
2589 r.in.level = level;
2590 r.in.buffer = NULL;
2591 r.in.offered = 0;
2592 r.out.needed = &needed;
2593 r.out.count = &count;
2594 r.out.info = &info;
2596 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2598 torture_assert_ntstatus_ok(tctx,
2599 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2600 "EnumForms failed");
2602 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL))) {
2603 torture_skip(tctx, "EnumForms level 2 not supported");
2606 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_INVALID_HANDLE)) {
2607 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2610 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2611 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2612 r.in.buffer = &blob;
2613 r.in.offered = needed;
2615 torture_assert_ntstatus_ok(tctx,
2616 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2617 "EnumForms failed");
2619 torture_assert(tctx, info, "No forms returned");
2622 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2624 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2626 if (info_p) {
2627 *info_p = info;
2629 if (count_p) {
2630 *count_p = count;
2633 return true;
2636 static bool test_EnumForms_all(struct torture_context *tctx,
2637 struct dcerpc_binding_handle *b,
2638 struct policy_handle *handle,
2639 bool print_server)
2641 uint32_t levels[] = { 1, 2 };
2642 int i, j;
2644 for (i=0; i<ARRAY_SIZE(levels); i++) {
2646 uint32_t count = 0;
2647 union spoolss_FormInfo *info = NULL;
2649 torture_assert(tctx,
2650 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2651 "failed to enum forms");
2653 for (j = 0; j < count; j++) {
2654 if (!print_server) {
2655 torture_assert(tctx,
2656 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2657 "failed to get form");
2662 return true;
2665 static bool test_EnumForms_find_one(struct torture_context *tctx,
2666 struct dcerpc_binding_handle *b,
2667 struct policy_handle *handle,
2668 bool print_server,
2669 const char *form_name)
2671 union spoolss_FormInfo *info = NULL;
2672 uint32_t count = 0;
2673 bool found = false;
2674 int i;
2676 torture_assert(tctx,
2677 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2678 "failed to enumerate forms");
2680 for (i=0; i<count; i++) {
2681 if (strequal(form_name, info[i].info1.form_name)) {
2682 found = true;
2683 break;
2687 return found;
2690 static bool test_DeleteForm(struct torture_context *tctx,
2691 struct dcerpc_binding_handle *b,
2692 struct policy_handle *handle,
2693 const char *form_name,
2694 WERROR expected_result)
2696 struct spoolss_DeleteForm r;
2698 r.in.handle = handle;
2699 r.in.form_name = form_name;
2701 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2703 torture_assert_ntstatus_ok(tctx,
2704 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2705 "DeleteForm failed");
2706 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2707 "DeleteForm gave unexpected result");
2708 if (W_ERROR_IS_OK(r.out.result)) {
2709 torture_assert_ntstatus_ok(tctx,
2710 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2711 "2nd DeleteForm failed");
2712 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2713 "2nd DeleteForm failed");
2716 return true;
2719 static bool test_AddForm(struct torture_context *tctx,
2720 struct dcerpc_binding_handle *b,
2721 struct policy_handle *handle,
2722 uint32_t level,
2723 union spoolss_AddFormInfo *info,
2724 WERROR expected_result)
2726 struct spoolss_AddForm r;
2727 struct spoolss_AddFormInfoCtr info_ctr;
2729 info_ctr.level = level;
2730 info_ctr.info = *info;
2732 if (level != 1) {
2733 torture_skip(tctx, "only level 1 supported");
2736 r.in.handle = handle;
2737 r.in.info_ctr = &info_ctr;
2739 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2740 r.in.info_ctr->info.info1->form_name, level,
2741 r.in.info_ctr->info.info1->flags);
2743 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2744 "AddForm failed");
2745 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2746 "AddForm gave unexpected result");
2748 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2749 "2nd AddForm failed");
2750 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAMETER)) {
2751 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
2752 "2nd AddForm gave unexpected result");
2753 } else {
2754 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2755 "2nd AddForm gave unexpected result");
2758 return true;
2761 static bool test_SetForm(struct torture_context *tctx,
2762 struct dcerpc_binding_handle *b,
2763 struct policy_handle *handle,
2764 const char *form_name,
2765 uint32_t level,
2766 union spoolss_AddFormInfo *info)
2768 struct spoolss_SetForm r;
2769 struct spoolss_AddFormInfoCtr info_ctr;
2771 info_ctr.level = level;
2772 info_ctr.info = *info;
2774 r.in.handle = handle;
2775 r.in.form_name = form_name;
2776 r.in.info_ctr = &info_ctr;
2778 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2779 form_name, level);
2781 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2782 "SetForm failed");
2784 torture_assert_werr_ok(tctx, r.out.result,
2785 "SetForm failed");
2787 return true;
2790 static bool test_GetForm_winreg(struct torture_context *tctx,
2791 struct dcerpc_binding_handle *b,
2792 struct policy_handle *handle,
2793 const char *key_name,
2794 const char *form_name,
2795 enum winreg_Type *w_type,
2796 uint32_t *w_size,
2797 uint32_t *w_length,
2798 uint8_t **w_data);
2800 static bool test_Forms_args(struct torture_context *tctx,
2801 struct dcerpc_binding_handle *b,
2802 struct policy_handle *handle,
2803 bool print_server,
2804 const char *printer_name,
2805 struct dcerpc_binding_handle *winreg_handle,
2806 struct policy_handle *hive_handle,
2807 const char *form_name,
2808 struct spoolss_AddFormInfo1 *info1,
2809 WERROR expected_add_result,
2810 WERROR expected_delete_result)
2812 union spoolss_FormInfo info;
2813 union spoolss_AddFormInfo add_info;
2815 enum winreg_Type w_type;
2816 uint32_t w_size;
2817 uint32_t w_length;
2818 uint8_t *w_data;
2820 add_info.info1 = info1;
2822 torture_assert(tctx,
2823 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2824 "failed to add form");
2826 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2828 struct spoolss_FormInfo1 i1;
2830 torture_assert(tctx,
2831 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2832 "failed to get form via winreg");
2834 i1.size.width = IVAL(w_data, 0);
2835 i1.size.height = IVAL(w_data, 4);
2836 i1.area.left = IVAL(w_data, 8);
2837 i1.area.top = IVAL(w_data, 12);
2838 i1.area.right = IVAL(w_data, 16);
2839 i1.area.bottom = IVAL(w_data, 20);
2840 /* skip index here */
2841 i1.flags = IVAL(w_data, 28);
2843 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2844 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2845 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2846 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2847 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2848 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2849 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2850 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2851 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2852 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2855 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2856 torture_assert(tctx,
2857 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2858 "failed to get added form");
2860 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2861 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2862 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2863 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2864 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2865 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2866 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2868 if (winreg_handle && hive_handle) {
2870 struct spoolss_FormInfo1 i1;
2872 i1.size.width = IVAL(w_data, 0);
2873 i1.size.height = IVAL(w_data, 4);
2874 i1.area.left = IVAL(w_data, 8);
2875 i1.area.top = IVAL(w_data, 12);
2876 i1.area.right = IVAL(w_data, 16);
2877 i1.area.bottom = IVAL(w_data, 20);
2878 /* skip index here */
2879 i1.flags = IVAL(w_data, 28);
2881 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2882 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2883 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2884 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2885 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2886 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2887 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2890 add_info.info1->size.width = 1234;
2892 torture_assert(tctx,
2893 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2894 "failed to set form");
2895 torture_assert(tctx,
2896 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2897 "failed to get setted form");
2899 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2902 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAMETER)) {
2903 torture_assert(tctx,
2904 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2905 "Newly added form not found in enum call");
2908 torture_assert(tctx,
2909 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2910 "failed to delete form");
2912 return true;
2915 static bool test_Forms(struct torture_context *tctx,
2916 struct dcerpc_binding_handle *b,
2917 struct policy_handle *handle,
2918 bool print_server,
2919 const char *printer_name,
2920 struct dcerpc_binding_handle *winreg_handle,
2921 struct policy_handle *hive_handle)
2923 const struct spoolss_FormSize size = {
2924 .width = 50,
2925 .height = 25
2927 const struct spoolss_FormArea area = {
2928 .left = 5,
2929 .top = 10,
2930 .right = 45,
2931 .bottom = 15
2933 int i;
2935 struct {
2936 struct spoolss_AddFormInfo1 info1;
2937 WERROR expected_add_result;
2938 WERROR expected_delete_result;
2939 } forms[] = {
2941 .info1 = {
2942 .flags = SPOOLSS_FORM_USER,
2943 .form_name = "testform_user",
2944 .size = size,
2945 .area = area,
2947 .expected_add_result = WERR_OK,
2948 .expected_delete_result = WERR_OK
2951 weird, we can add a builtin form but we can never remove it
2952 again - gd
2955 .info1 = {
2956 .flags = SPOOLSS_FORM_BUILTIN,
2957 .form_name = "testform_builtin",
2958 .size = size,
2959 .area = area,
2961 .expected_add_result = WERR_OK,
2962 .expected_delete_result = WERR_INVALID_PARAMETER,
2966 .info1 = {
2967 .flags = SPOOLSS_FORM_PRINTER,
2968 .form_name = "testform_printer",
2969 .size = size,
2970 .area = area,
2972 .expected_add_result = WERR_OK,
2973 .expected_delete_result = WERR_OK
2976 .info1 = {
2977 .flags = SPOOLSS_FORM_USER,
2978 .form_name = "Letter",
2979 .size = size,
2980 .area = area,
2982 .expected_add_result = WERR_FILE_EXISTS,
2983 .expected_delete_result = WERR_INVALID_PARAMETER
2986 .info1 = {
2987 .flags = SPOOLSS_FORM_BUILTIN,
2988 .form_name = "Letter",
2989 .size = size,
2990 .area = area,
2992 .expected_add_result = WERR_FILE_EXISTS,
2993 .expected_delete_result = WERR_INVALID_PARAMETER
2996 .info1 = {
2997 .flags = SPOOLSS_FORM_PRINTER,
2998 .form_name = "Letter",
2999 .size = size,
3000 .area = area,
3002 .expected_add_result = WERR_FILE_EXISTS,
3003 .expected_delete_result = WERR_INVALID_PARAMETER
3006 .info1 = {
3007 .flags = 12345,
3008 .form_name = "invalid_flags",
3009 .size = size,
3010 .area = area,
3012 .expected_add_result = WERR_INVALID_PARAMETER,
3013 .expected_delete_result = WERR_INVALID_FORM_NAME
3018 for (i=0; i < ARRAY_SIZE(forms); i++) {
3019 torture_assert(tctx,
3020 test_Forms_args(tctx, b, handle, print_server, printer_name,
3021 winreg_handle, hive_handle,
3022 forms[i].info1.form_name,
3023 &forms[i].info1,
3024 forms[i].expected_add_result,
3025 forms[i].expected_delete_result),
3026 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
3029 return true;
3032 static bool test_EnumPorts_old(struct torture_context *tctx,
3033 void *private_data)
3035 struct test_spoolss_context *ctx =
3036 talloc_get_type_abort(private_data, struct test_spoolss_context);
3038 NTSTATUS status;
3039 struct spoolss_EnumPorts r;
3040 uint32_t needed;
3041 uint32_t count;
3042 union spoolss_PortInfo *info;
3043 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3044 struct dcerpc_binding_handle *b = p->binding_handle;
3046 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
3047 dcerpc_server_name(p));
3048 r.in.level = 2;
3049 r.in.buffer = NULL;
3050 r.in.offered = 0;
3051 r.out.needed = &needed;
3052 r.out.count = &count;
3053 r.out.info = &info;
3055 torture_comment(tctx, "Testing EnumPorts\n");
3057 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3059 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3061 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3062 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3063 r.in.buffer = &blob;
3064 r.in.offered = needed;
3066 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3067 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3068 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3070 torture_assert(tctx, info, "No ports returned");
3073 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3075 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3077 return true;
3080 static bool test_AddPort(struct torture_context *tctx,
3081 void *private_data)
3083 struct test_spoolss_context *ctx =
3084 talloc_get_type_abort(private_data, struct test_spoolss_context);
3086 NTSTATUS status;
3087 struct spoolss_AddPort r;
3088 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3089 struct dcerpc_binding_handle *b = p->binding_handle;
3091 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3092 dcerpc_server_name(p));
3093 r.in.unknown = 0;
3094 r.in.monitor_name = "foo";
3096 torture_comment(tctx, "Testing AddPort\n");
3098 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3100 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3102 /* win2k3 returns WERR_NOT_SUPPORTED */
3104 #if 0
3106 if (!W_ERROR_IS_OK(r.out.result)) {
3107 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3108 return false;
3111 #endif
3113 return true;
3116 static bool test_GetJob_args(struct torture_context *tctx,
3117 struct dcerpc_binding_handle *b,
3118 struct policy_handle *handle,
3119 uint32_t job_id,
3120 uint32_t level,
3121 union spoolss_JobInfo *info_p)
3123 NTSTATUS status;
3124 struct spoolss_GetJob r;
3125 union spoolss_JobInfo info;
3126 uint32_t needed;
3128 r.in.handle = handle;
3129 r.in.job_id = job_id;
3130 r.in.level = level;
3131 r.in.buffer = NULL;
3132 r.in.offered = 0;
3133 r.out.needed = &needed;
3134 r.out.info = &info;
3136 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3138 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3139 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3140 if (level == 0) {
3141 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "Unexpected return code");
3144 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3145 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3146 r.in.buffer = &blob;
3147 r.in.offered = needed;
3149 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3150 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3153 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3154 torture_assert(tctx, r.out.info, "No job info returned");
3156 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3158 if (info_p) {
3159 *info_p = *r.out.info;
3162 return true;
3165 #if 0
3166 static bool test_GetJob(struct torture_context *tctx,
3167 struct dcerpc_binding_handle *b,
3168 struct policy_handle *handle,
3169 uint32_t job_id)
3171 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3172 uint32_t i;
3174 for (i=0; i < ARRAY_SIZE(levels); i++) {
3175 torture_assert(tctx,
3176 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3177 "GetJob failed");
3180 return true;
3182 #endif
3184 static bool test_SetJob(struct torture_context *tctx,
3185 struct dcerpc_binding_handle *b,
3186 struct policy_handle *handle,
3187 uint32_t job_id,
3188 struct spoolss_JobInfoContainer *ctr,
3189 enum spoolss_JobControl command)
3191 NTSTATUS status;
3192 struct spoolss_SetJob r;
3194 r.in.handle = handle;
3195 r.in.job_id = job_id;
3196 r.in.ctr = ctr;
3197 r.in.command = command;
3199 switch (command) {
3200 case SPOOLSS_JOB_CONTROL_PAUSE:
3201 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3202 break;
3203 case SPOOLSS_JOB_CONTROL_RESUME:
3204 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3205 break;
3206 case SPOOLSS_JOB_CONTROL_CANCEL:
3207 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3208 break;
3209 case SPOOLSS_JOB_CONTROL_RESTART:
3210 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3211 break;
3212 case SPOOLSS_JOB_CONTROL_DELETE:
3213 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3214 break;
3215 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3216 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3217 break;
3218 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3219 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3220 break;
3221 case SPOOLSS_JOB_CONTROL_RETAIN:
3222 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3223 break;
3224 case SPOOLSS_JOB_CONTROL_RELEASE:
3225 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3226 break;
3227 default:
3228 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3229 break;
3232 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3233 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3234 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3236 return true;
3239 static bool test_AddJob(struct torture_context *tctx,
3240 struct dcerpc_binding_handle *b,
3241 struct policy_handle *handle)
3243 NTSTATUS status;
3244 struct spoolss_AddJob r;
3245 uint32_t needed;
3247 r.in.level = 0;
3248 r.in.handle = handle;
3249 r.in.offered = 0;
3250 r.out.needed = &needed;
3251 r.in.buffer = r.out.buffer = NULL;
3253 torture_comment(tctx, "Testing AddJob\n");
3255 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3256 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3257 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "AddJob failed");
3259 r.in.level = 1;
3261 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3262 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3263 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER, "AddJob failed");
3265 return true;
3269 static bool test_EnumJobs_args(struct torture_context *tctx,
3270 struct dcerpc_binding_handle *b,
3271 struct policy_handle *handle,
3272 uint32_t level,
3273 WERROR werr_expected,
3274 uint32_t *count_p,
3275 union spoolss_JobInfo **info_p)
3277 NTSTATUS status;
3278 struct spoolss_EnumJobs r;
3279 uint32_t needed;
3280 uint32_t count;
3281 union spoolss_JobInfo *info;
3283 r.in.handle = handle;
3284 r.in.firstjob = 0;
3285 r.in.numjobs = 0xffffffff;
3286 r.in.level = level;
3287 r.in.buffer = NULL;
3288 r.in.offered = 0;
3289 r.out.needed = &needed;
3290 r.out.count = &count;
3291 r.out.info = &info;
3293 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3295 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3297 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3299 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3300 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3301 r.in.buffer = &blob;
3302 r.in.offered = needed;
3304 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3306 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3307 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3308 "EnumJobs failed");
3309 torture_assert(tctx, info, "No jobs returned");
3311 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3313 } else {
3314 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3315 "EnumJobs failed");
3318 if (count_p) {
3319 *count_p = count;
3321 if (info_p) {
3322 *info_p = info;
3325 return true;
3328 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3329 struct dcerpc_binding_handle *b,
3330 struct policy_handle *handle,
3331 uint32_t job_id)
3333 struct spoolss_EnumJobNamedProperties r;
3334 uint32_t pcProperties = 0;
3335 struct spoolss_PrintNamedProperty *ppProperties = NULL;
3337 r.in.hPrinter = handle;
3338 r.in.JobId = job_id;
3339 r.out.pcProperties = &pcProperties;
3340 r.out.ppProperties = &ppProperties;
3342 torture_comment(tctx, "Testing EnumJobNamedProperties(%d)\n", job_id);
3344 torture_assert_ntstatus_ok(tctx,
3345 dcerpc_spoolss_EnumJobNamedProperties_r(b, tctx, &r),
3346 "spoolss_EnumJobNamedProperties failed");
3347 torture_assert_werr_ok(tctx, r.out.result,
3348 "spoolss_EnumJobNamedProperties failed");
3350 return true;
3353 static bool test_JobPropertySet(struct torture_context *tctx,
3354 struct dcerpc_binding_handle *b,
3355 struct policy_handle *handle,
3356 uint32_t job_id,
3357 struct spoolss_PrintNamedProperty *property)
3359 struct spoolss_SetJobNamedProperty r;
3361 r.in.hPrinter = handle;
3362 r.in.JobId = job_id;
3363 r.in.pProperty = property;
3365 torture_comment(tctx, "Testing SetJobNamedProperty(%d) %s - %d\n",
3366 job_id, property->propertyName,
3367 property->propertyValue.ePropertyType);
3369 torture_assert_ntstatus_ok(tctx,
3370 dcerpc_spoolss_SetJobNamedProperty_r(b, tctx, &r),
3371 "spoolss_SetJobNamedProperty failed");
3372 torture_assert_werr_ok(tctx, r.out.result,
3373 "spoolss_SetJobNamedProperty failed");
3375 return true;
3378 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3379 struct dcerpc_binding_handle *b,
3380 struct policy_handle *handle,
3381 uint32_t job_id,
3382 const char *property_name,
3383 struct spoolss_PrintPropertyValue *value)
3385 struct spoolss_GetJobNamedPropertyValue r;
3387 r.in.hPrinter = handle;
3388 r.in.JobId = job_id;
3389 r.in.pszName = property_name;
3390 r.out.pValue = value;
3392 torture_comment(tctx, "Testing GetJobNamedPropertyValue(%d) %s\n",
3393 job_id, property_name);
3395 torture_assert_ntstatus_ok(tctx,
3396 dcerpc_spoolss_GetJobNamedPropertyValue_r(b, tctx, &r),
3397 "spoolss_GetJobNamedPropertyValue failed");
3398 torture_assert_werr_ok(tctx, r.out.result,
3399 "spoolss_GetJobNamedPropertyValue failed");
3401 return true;
3404 static bool test_JobPropertyDelete(struct torture_context *tctx,
3405 struct dcerpc_binding_handle *b,
3406 struct policy_handle *handle,
3407 uint32_t job_id,
3408 const char *property_name)
3410 struct spoolss_DeleteJobNamedProperty r;
3412 r.in.hPrinter = handle;
3413 r.in.JobId = job_id;
3414 r.in.pszName = property_name;
3416 torture_comment(tctx, "Testing DeleteJobNamedProperty(%d) %s\n",
3417 job_id, property_name);
3419 torture_assert_ntstatus_ok(tctx,
3420 dcerpc_spoolss_DeleteJobNamedProperty_r(b, tctx, &r),
3421 "spoolss_DeleteJobNamedProperty failed");
3422 torture_assert_werr_ok(tctx, r.out.result,
3423 "spoolss_DeleteJobNamedProperty failed");
3425 return true;
3428 static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
3429 struct dcerpc_binding_handle *b,
3430 struct policy_handle *handle,
3431 const char *document_name,
3432 const char *datatype,
3433 uint32_t *job_id)
3435 NTSTATUS status;
3436 struct spoolss_StartDocPrinter s;
3437 struct spoolss_DocumentInfoCtr info_ctr;
3438 struct spoolss_DocumentInfo1 info1;
3439 struct spoolss_StartPagePrinter sp;
3440 struct spoolss_WritePrinter w;
3441 struct spoolss_EndPagePrinter ep;
3442 struct spoolss_EndDocPrinter e;
3443 int i;
3444 uint32_t num_written;
3446 torture_comment(tctx, "Testing StartDocPrinter\n");
3448 s.in.handle = handle;
3449 s.in.info_ctr = &info_ctr;
3450 s.out.job_id = job_id;
3452 info1.document_name = document_name;
3453 info1.output_file = NULL;
3454 info1.datatype = datatype;
3456 info_ctr.level = 1;
3457 info_ctr.info.info1 = &info1;
3459 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3460 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3461 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3463 for (i=1; i < 4; i++) {
3464 union spoolss_JobInfo ginfo;
3465 bool ok;
3467 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3469 sp.in.handle = handle;
3471 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3472 torture_assert_ntstatus_ok(tctx, status,
3473 "dcerpc_spoolss_StartPagePrinter failed");
3474 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3476 ok = test_GetJob_args(tctx, b, handle, *job_id, 1, &ginfo);
3477 if (!ok) {
3478 torture_comment(tctx, "test_GetJob failed for JobId[%d]\n", *job_id);
3481 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3483 w.in.handle = handle;
3484 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3485 w.out.num_written = &num_written;
3487 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3488 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3489 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3491 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3493 ep.in.handle = handle;
3495 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3496 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3497 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3500 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3502 e.in.handle = handle;
3504 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3505 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3506 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3508 return true;
3511 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3512 struct dcerpc_binding_handle *b,
3513 struct policy_handle *handle,
3514 const char *document_name,
3515 uint32_t *job_id)
3517 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
3519 return true;
3522 static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
3523 struct dcerpc_binding_handle *b,
3524 struct policy_handle *handle,
3525 const char *document_name,
3526 uint32_t *job_id)
3528 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
3530 return true;
3534 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3535 struct dcerpc_binding_handle *b,
3536 struct policy_handle *handle,
3537 uint32_t num_jobs,
3538 uint32_t *job_ids)
3540 uint32_t count;
3541 union spoolss_JobInfo *info = NULL;
3542 int i;
3544 torture_assert(tctx,
3545 test_AddJob(tctx, b, handle),
3546 "AddJob failed");
3548 torture_assert(tctx,
3549 test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
3550 "EnumJobs level 1 failed");
3552 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3554 for (i=0; i < num_jobs; i++) {
3555 union spoolss_JobInfo ginfo;
3556 const char *document_name;
3557 const char *new_document_name = "any_other_docname";
3558 struct spoolss_JobInfoContainer ctr;
3559 struct spoolss_SetJobInfo1 info1;
3561 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3563 torture_assert(tctx,
3564 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3565 "failed to call test_GetJob");
3567 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3569 document_name = ginfo.info1.document_name;
3571 info1.job_id = ginfo.info1.job_id;
3572 info1.printer_name = ginfo.info1.printer_name;
3573 info1.server_name = ginfo.info1.server_name;
3574 info1.user_name = ginfo.info1.user_name;
3575 info1.document_name = new_document_name;
3576 info1.data_type = ginfo.info1.data_type;
3577 info1.text_status = ginfo.info1.text_status;
3578 info1.status = ginfo.info1.status;
3579 info1.priority = ginfo.info1.priority;
3580 info1.position = ginfo.info1.position;
3581 info1.total_pages = ginfo.info1.total_pages;
3582 info1.pages_printed = ginfo.info1.pages_printed;
3583 info1.submitted = ginfo.info1.submitted;
3585 ctr.level = 1;
3586 ctr.info.info1 = &info1;
3588 torture_assert(tctx,
3589 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3590 "failed to call test_SetJob level 1");
3592 torture_assert(tctx,
3593 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3594 "failed to call test_GetJob");
3596 if (strequal(ginfo.info1.document_name, document_name)) {
3597 torture_warning(tctx,
3598 "document_name did *NOT* change from '%s' to '%s'\n",
3599 document_name, new_document_name);
3603 for (i=0; i < num_jobs; i++) {
3604 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3605 torture_warning(tctx, "failed to pause printjob\n");
3607 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3608 torture_warning(tctx, "failed to resume printjob\n");
3612 return true;
3615 static bool test_DoPrintTest(struct torture_context *tctx,
3616 struct dcerpc_binding_handle *b,
3617 struct policy_handle *handle)
3619 bool ret = true;
3620 uint32_t num_jobs = 8;
3621 uint32_t *job_ids;
3622 int i;
3624 torture_comment(tctx, "Testing real print operations\n");
3626 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3628 for (i=0; i < num_jobs; i++) {
3629 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3632 for (i=0; i < num_jobs; i++) {
3633 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3636 for (i=0; i < num_jobs; i++) {
3637 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
3640 for (i=0; i < num_jobs; i++) {
3641 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3644 if (ret == true) {
3645 torture_comment(tctx, "real print operations test succeeded\n\n");
3648 return ret;
3651 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3652 struct dcerpc_binding_handle *b,
3653 struct policy_handle *handle)
3655 bool ret = true;
3656 uint32_t num_jobs = 8;
3657 uint32_t *job_ids;
3658 int i;
3659 torture_comment(tctx, "Testing real print operations (extended)\n");
3661 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3663 for (i=0; i < num_jobs; i++) {
3664 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3667 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3669 for (i=0; i < num_jobs; i++) {
3670 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3673 if (ret == true) {
3674 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3677 return ret;
3680 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3681 struct spoolss_PrintPropertyValue *got,
3682 struct spoolss_PrintNamedProperty *exp)
3684 torture_assert_int_equal(tctx,
3685 got->ePropertyType,
3686 exp->propertyValue.ePropertyType,
3687 "ePropertyType");
3689 switch (exp->propertyValue.ePropertyType) {
3690 case kRpcPropertyTypeString:
3691 torture_assert_str_equal(tctx,
3692 got->value.propertyString,
3693 exp->propertyValue.value.propertyString,
3694 "propertyString");
3695 break;
3696 case kRpcPropertyTypeInt32:
3697 torture_assert_int_equal(tctx,
3698 got->value.propertyInt32,
3699 exp->propertyValue.value.propertyInt32,
3700 "propertyInt32");
3701 break;
3702 case kRpcPropertyTypeInt64:
3703 torture_assert_u64_equal(tctx,
3704 got->value.propertyInt64,
3705 exp->propertyValue.value.propertyInt64,
3706 "propertyInt64");
3707 break;
3708 case kRpcPropertyTypeByte:
3709 torture_assert_int_equal(tctx,
3710 got->value.propertyByte,
3711 exp->propertyValue.value.propertyByte,
3712 "propertyByte");
3713 break;
3714 case kRpcPropertyTypeBuffer:
3715 torture_assert_int_equal(tctx,
3716 got->value.propertyBlob.cbBuf,
3717 exp->propertyValue.value.propertyBlob.cbBuf,
3718 "propertyBlob.cbBuf");
3719 torture_assert_mem_equal(tctx,
3720 got->value.propertyBlob.pBuf,
3721 exp->propertyValue.value.propertyBlob.pBuf,
3722 exp->propertyValue.value.propertyBlob.cbBuf,
3723 "propertyBlob.pBuf");
3725 break;
3729 return true;
3732 static bool test_JobPrintProperties(struct torture_context *tctx,
3733 struct dcerpc_binding_handle *b,
3734 struct policy_handle *handle,
3735 uint32_t job_id)
3737 struct spoolss_PrintNamedProperty in;
3738 struct spoolss_PrintPropertyValue out;
3739 int i;
3740 DATA_BLOB blob = data_blob_string_const("blob");
3741 struct {
3742 const char *property_name;
3743 enum spoolss_EPrintPropertyType type;
3744 union spoolss_PrintPropertyValueUnion value;
3745 WERROR expected_result;
3746 } tests[] = {
3748 .property_name = "torture_property_string",
3749 .type = kRpcPropertyTypeString,
3750 .value.propertyString = "torture_property_value_string",
3752 .property_name = "torture_property_int32",
3753 .type = kRpcPropertyTypeInt32,
3754 .value.propertyInt32 = 42,
3756 .property_name = "torture_property_int64",
3757 .type = kRpcPropertyTypeInt64,
3758 .value.propertyInt64 = 0xaffe,
3760 .property_name = "torture_property_byte",
3761 .type = kRpcPropertyTypeByte,
3762 .value.propertyByte = 0xab,
3764 .property_name = "torture_property_buffer",
3765 .type = kRpcPropertyTypeBuffer,
3766 .value.propertyBlob.cbBuf = blob.length,
3767 .value.propertyBlob.pBuf = blob.data,
3771 torture_assert(tctx,
3772 test_JobPropertiesEnum(tctx, b, handle, job_id),
3773 "failed to enum properties");
3775 for (i=0; i <ARRAY_SIZE(tests); i++) {
3777 in.propertyName = tests[i].property_name;
3778 in.propertyValue.ePropertyType = tests[i].type;
3779 in.propertyValue.value = tests[i].value;
3781 torture_assert(tctx,
3782 test_JobPropertySet(tctx, b, handle, job_id, &in),
3783 "failed to set property");
3785 torture_assert(tctx,
3786 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3787 "failed to get property");
3789 torture_assert(tctx,
3790 test_JobPrintProperties_equal(tctx, &out, &in),
3791 "property unequal");
3793 torture_assert(tctx,
3794 test_JobPropertiesEnum(tctx, b, handle, job_id),
3795 "failed to enum properties");
3797 torture_assert(tctx,
3798 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3799 "failed to delete job property");
3802 torture_assert(tctx,
3803 test_JobPropertiesEnum(tctx, b, handle, job_id),
3804 "failed to enum properties");
3806 return true;
3809 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3810 struct dcerpc_binding_handle *b,
3811 struct policy_handle *handle)
3813 uint32_t num_jobs = 8;
3814 uint32_t *job_ids;
3815 int i;
3816 torture_comment(tctx, "Testing real print operations (properties)\n");
3818 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3820 for (i=0; i < num_jobs; i++) {
3821 torture_assert(tctx,
3822 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3823 "failed to create print job");
3826 for (i=0; i < num_jobs; i++) {
3827 torture_assert(tctx,
3828 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3829 "failed to test job properties");
3833 for (i=0; i < num_jobs; i++) {
3834 torture_assert(tctx,
3835 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3836 "failed to delete printjob");
3839 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3841 return true;
3844 static bool test_PausePrinter(struct torture_context *tctx,
3845 struct dcerpc_binding_handle *b,
3846 struct policy_handle *handle)
3848 NTSTATUS status;
3849 struct spoolss_SetPrinter r;
3850 struct spoolss_SetPrinterInfoCtr info_ctr;
3851 struct spoolss_DevmodeContainer devmode_ctr;
3852 struct sec_desc_buf secdesc_ctr;
3854 info_ctr.level = 0;
3855 info_ctr.info.info0 = NULL;
3857 ZERO_STRUCT(devmode_ctr);
3858 ZERO_STRUCT(secdesc_ctr);
3860 r.in.handle = handle;
3861 r.in.info_ctr = &info_ctr;
3862 r.in.devmode_ctr = &devmode_ctr;
3863 r.in.secdesc_ctr = &secdesc_ctr;
3864 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3866 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3868 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3870 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3872 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3874 return true;
3877 static bool test_ResumePrinter(struct torture_context *tctx,
3878 struct dcerpc_binding_handle *b,
3879 struct policy_handle *handle)
3881 NTSTATUS status;
3882 struct spoolss_SetPrinter r;
3883 struct spoolss_SetPrinterInfoCtr info_ctr;
3884 struct spoolss_DevmodeContainer devmode_ctr;
3885 struct sec_desc_buf secdesc_ctr;
3887 info_ctr.level = 0;
3888 info_ctr.info.info0 = NULL;
3890 ZERO_STRUCT(devmode_ctr);
3891 ZERO_STRUCT(secdesc_ctr);
3893 r.in.handle = handle;
3894 r.in.info_ctr = &info_ctr;
3895 r.in.devmode_ctr = &devmode_ctr;
3896 r.in.secdesc_ctr = &secdesc_ctr;
3897 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3899 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3901 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3903 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3905 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3907 return true;
3910 static bool test_printer_purge(struct torture_context *tctx,
3911 struct dcerpc_binding_handle *b,
3912 struct policy_handle *handle)
3914 NTSTATUS status;
3915 struct spoolss_SetPrinter r;
3916 struct spoolss_SetPrinterInfoCtr info_ctr;
3917 struct spoolss_DevmodeContainer devmode_ctr;
3918 struct sec_desc_buf secdesc_ctr;
3920 info_ctr.level = 0;
3921 info_ctr.info.info0 = NULL;
3923 ZERO_STRUCT(devmode_ctr);
3924 ZERO_STRUCT(secdesc_ctr);
3926 r.in.handle = handle;
3927 r.in.info_ctr = &info_ctr;
3928 r.in.devmode_ctr = &devmode_ctr;
3929 r.in.secdesc_ctr = &secdesc_ctr;
3930 r.in.command = SPOOLSS_PRINTER_CONTROL_PURGE;
3932 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3934 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3935 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3936 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3938 return true;
3941 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3942 struct dcerpc_binding_handle *b,
3943 struct policy_handle *handle,
3944 const char *value_name,
3945 enum winreg_Type *expected_type,
3946 enum winreg_Type *type_p,
3947 uint8_t **data_p,
3948 uint32_t *needed_p)
3950 NTSTATUS status;
3951 struct spoolss_GetPrinterData r;
3952 uint32_t needed;
3953 enum winreg_Type type;
3954 union spoolss_PrinterData data;
3956 r.in.handle = handle;
3957 r.in.value_name = value_name;
3958 r.in.offered = 0;
3959 r.out.needed = &needed;
3960 r.out.type = &type;
3961 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3963 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3965 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3966 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3968 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3969 if (expected_type) {
3970 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3972 r.in.offered = needed;
3973 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3974 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3975 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3978 torture_assert_werr_ok(tctx, r.out.result,
3979 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3981 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3983 if (type_p) {
3984 *type_p = type;
3987 if (data_p) {
3988 *data_p = r.out.data;
3991 if (needed_p) {
3992 *needed_p = needed;
3995 return true;
3998 static bool test_GetPrinterData(struct torture_context *tctx,
3999 struct dcerpc_binding_handle *b,
4000 struct policy_handle *handle,
4001 const char *value_name,
4002 enum winreg_Type *type_p,
4003 uint8_t **data_p,
4004 uint32_t *needed_p)
4006 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
4007 NULL, type_p, data_p, needed_p);
4010 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
4011 struct dcerpc_pipe *p,
4012 struct policy_handle *handle,
4013 const char *key_name,
4014 const char *value_name,
4015 enum winreg_Type *expected_type,
4016 enum winreg_Type *type_p,
4017 uint8_t **data_p,
4018 uint32_t *needed_p)
4020 NTSTATUS status;
4021 struct spoolss_GetPrinterDataEx r;
4022 enum winreg_Type type;
4023 uint32_t needed;
4024 union spoolss_PrinterData data;
4025 struct dcerpc_binding_handle *b = p->binding_handle;
4027 r.in.handle = handle;
4028 r.in.key_name = key_name;
4029 r.in.value_name = value_name;
4030 r.in.offered = 0;
4031 r.out.type = &type;
4032 r.out.needed = &needed;
4033 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4035 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
4036 r.in.key_name, r.in.value_name);
4038 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
4041 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
4043 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4046 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4047 if (expected_type) {
4048 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
4050 r.in.offered = needed;
4051 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4052 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4053 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4056 torture_assert_werr_ok(tctx, r.out.result,
4057 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
4059 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
4061 if (type_p) {
4062 *type_p = type;
4065 if (data_p) {
4066 *data_p = r.out.data;
4069 if (needed_p) {
4070 *needed_p = needed;
4073 return true;
4076 static bool test_GetPrinterDataEx(struct torture_context *tctx,
4077 struct dcerpc_pipe *p,
4078 struct policy_handle *handle,
4079 const char *key_name,
4080 const char *value_name,
4081 enum winreg_Type *type_p,
4082 uint8_t **data_p,
4083 uint32_t *needed_p)
4085 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
4086 NULL, type_p, data_p, needed_p);
4089 static bool test_get_environment(struct torture_context *tctx,
4090 struct dcerpc_binding_handle *b,
4091 struct policy_handle *handle,
4092 const char **architecture)
4094 DATA_BLOB blob;
4095 enum winreg_Type type;
4096 uint8_t *data;
4097 uint32_t needed;
4099 torture_assert(tctx,
4100 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
4101 "failed to get Architecture");
4103 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
4105 blob = data_blob_const(data, needed);
4106 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
4108 return true;
4111 static bool test_GetPrinterData_list(struct torture_context *tctx,
4112 void *private_data)
4114 struct test_spoolss_context *ctx =
4115 talloc_get_type_abort(private_data, struct test_spoolss_context);
4116 struct dcerpc_pipe *p = ctx->spoolss_pipe;
4117 struct dcerpc_binding_handle *b = p->binding_handle;
4118 const char *list[] = {
4119 "W3SvcInstalled",
4120 "BeepEnabled",
4121 "EventLog",
4122 /* "NetPopup", not on w2k8 */
4123 /* "NetPopupToComputer", not on w2k8 */
4124 "MajorVersion",
4125 "MinorVersion",
4126 "DefaultSpoolDirectory",
4127 "Architecture",
4128 "DsPresent",
4129 "OSVersion",
4130 /* "OSVersionEx", not on s3 */
4131 "DNSMachineName"
4133 int i;
4135 for (i=0; i < ARRAY_SIZE(list); i++) {
4136 enum winreg_Type type = REG_NONE;
4137 enum winreg_Type type_ex1 = REG_NONE;
4138 enum winreg_Type type_ex2 = REG_NONE;
4139 uint8_t *data;
4140 uint8_t *data_ex1 = NULL;
4141 uint8_t *data_ex2 = NULL;
4142 uint32_t needed;
4143 uint32_t needed_ex1 = 0;
4144 uint32_t needed_ex2 = 0;
4146 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4147 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4148 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex1, &data_ex1, &needed_ex1),
4149 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4150 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "", list[i], &type_ex2, &data_ex2, &needed_ex2),
4151 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4152 torture_assert_int_equal(tctx, type, type_ex1, "type mismatch");
4153 torture_assert_int_equal(tctx, type, type_ex2, "type mismatch");
4154 torture_assert_int_equal(tctx, needed, needed_ex1, "needed mismatch");
4155 torture_assert_int_equal(tctx, needed, needed_ex2, "needed mismatch");
4156 torture_assert_mem_equal(tctx, data, data_ex1, needed, "data mismatch");
4157 torture_assert_mem_equal(tctx, data, data_ex2, needed, "data mismatch");
4160 return true;
4163 static bool test_EnumPrinterData(struct torture_context *tctx,
4164 struct dcerpc_pipe *p,
4165 struct policy_handle *handle,
4166 uint32_t enum_index,
4167 uint32_t value_offered,
4168 uint32_t data_offered,
4169 enum winreg_Type *type_p,
4170 uint32_t *value_needed_p,
4171 uint32_t *data_needed_p,
4172 const char **value_name_p,
4173 uint8_t **data_p,
4174 WERROR *result_p)
4176 struct spoolss_EnumPrinterData r;
4177 uint32_t data_needed;
4178 uint32_t value_needed;
4179 enum winreg_Type type;
4180 struct dcerpc_binding_handle *b = p->binding_handle;
4182 r.in.handle = handle;
4183 r.in.enum_index = enum_index;
4184 r.in.value_offered = value_offered;
4185 r.in.data_offered = data_offered;
4186 r.out.data_needed = &data_needed;
4187 r.out.value_needed = &value_needed;
4188 r.out.type = &type;
4189 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4190 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4192 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4194 torture_assert_ntstatus_ok(tctx,
4195 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4196 "EnumPrinterData failed");
4198 if (type_p) {
4199 *type_p = type;
4201 if (value_needed_p) {
4202 *value_needed_p = value_needed;
4204 if (data_needed_p) {
4205 *data_needed_p = data_needed;
4207 if (value_name_p) {
4208 *value_name_p = r.out.value_name;
4210 if (data_p) {
4211 *data_p = r.out.data;
4213 if (result_p) {
4214 *result_p = r.out.result;
4217 return true;
4221 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4222 struct dcerpc_pipe *p,
4223 struct policy_handle *handle)
4225 uint32_t enum_index = 0;
4226 enum winreg_Type type;
4227 uint32_t value_needed;
4228 uint32_t data_needed;
4229 uint8_t *data;
4230 const char *value_name;
4231 WERROR result;
4233 torture_comment(tctx, "Testing EnumPrinterData\n");
4235 do {
4236 torture_assert(tctx,
4237 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4238 &type, &value_needed, &data_needed,
4239 &value_name, &data, &result),
4240 "EnumPrinterData failed");
4242 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4243 break;
4246 torture_assert(tctx,
4247 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4248 &type, &value_needed, &data_needed,
4249 &value_name, &data, &result),
4250 "EnumPrinterData failed");
4252 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4253 break;
4256 enum_index++;
4258 } while (W_ERROR_IS_OK(result));
4260 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4262 return true;
4265 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4266 struct dcerpc_binding_handle *b,
4267 struct policy_handle *handle,
4268 const char *key_name,
4269 uint32_t *count_p,
4270 struct spoolss_PrinterEnumValues **info_p)
4272 struct spoolss_EnumPrinterDataEx r;
4273 struct spoolss_PrinterEnumValues *info;
4274 uint32_t needed;
4275 uint32_t count;
4277 r.in.handle = handle;
4278 r.in.key_name = key_name;
4279 r.in.offered = 0;
4280 r.out.needed = &needed;
4281 r.out.count = &count;
4282 r.out.info = &info;
4284 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4286 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4287 "EnumPrinterDataEx failed");
4288 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4289 r.in.offered = needed;
4290 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4291 "EnumPrinterDataEx failed");
4294 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4296 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4298 if (count_p) {
4299 *count_p = count;
4301 if (info_p) {
4302 *info_p = info;
4305 return true;
4308 static bool test_SetPrinterData(struct torture_context *tctx,
4309 struct dcerpc_binding_handle *b,
4310 struct policy_handle *handle,
4311 const char *value_name,
4312 enum winreg_Type type,
4313 uint8_t *data,
4314 uint32_t offered);
4315 static bool test_DeletePrinterData(struct torture_context *tctx,
4316 struct dcerpc_binding_handle *b,
4317 struct policy_handle *handle,
4318 const char *value_name);
4320 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4321 struct dcerpc_pipe *p,
4322 struct policy_handle *handle)
4324 uint32_t count;
4325 struct spoolss_PrinterEnumValues *info;
4326 int i;
4327 uint32_t value_needed, data_needed;
4328 uint32_t value_offered, data_offered;
4329 WERROR result;
4330 struct dcerpc_binding_handle *b = p->binding_handle;
4332 enum winreg_Type type;
4333 DATA_BLOB blob;
4335 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4337 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4338 type = REG_SZ;
4340 torture_assert(tctx,
4341 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4342 "SetPrinterData failed");
4344 blob = data_blob_string_const("torture_data2");
4346 torture_assert(tctx,
4347 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4348 "SetPrinterData failed");
4350 blob = data_blob_talloc(tctx, NULL, 4);
4351 SIVAL(blob.data, 0, 0x11223344);
4353 torture_assert(tctx,
4354 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4355 "SetPrinterData failed");
4357 torture_assert(tctx,
4358 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4359 "failed to call EnumPrinterDataEx");
4361 /* get the max sizes for value and data */
4363 torture_assert(tctx,
4364 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4365 NULL, &value_needed, &data_needed,
4366 NULL, NULL, &result),
4367 "EnumPrinterData failed");
4368 torture_assert_werr_ok(tctx, result, "unexpected result");
4370 /* check if the reply from the EnumPrinterData really matches max values */
4372 for (i=0; i < count; i++) {
4373 if (info[i].value_name_len > value_needed) {
4374 torture_fail(tctx,
4375 talloc_asprintf(tctx,
4376 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4377 info[i].value_name_len, value_needed));
4379 if (info[i].data_length > data_needed) {
4380 torture_fail(tctx,
4381 talloc_asprintf(tctx,
4382 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4383 info[i].data_length, data_needed));
4387 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4388 * sort or not sort the replies by value name, we should be able to do
4389 * the following entry comparison */
4391 data_offered = data_needed;
4392 value_offered = value_needed;
4394 for (i=0; i < count; i++) {
4396 const char *value_name;
4397 uint8_t *data;
4399 torture_assert(tctx,
4400 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4401 &type, &value_needed, &data_needed,
4402 &value_name, &data, &result),
4403 "EnumPrinterData failed");
4405 if (i -1 == count) {
4406 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4407 "unexpected result");
4408 break;
4409 } else {
4410 torture_assert_werr_ok(tctx, result, "unexpected result");
4413 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4414 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4415 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4416 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4417 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4420 torture_assert(tctx,
4421 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4422 "DeletePrinterData failed");
4423 torture_assert(tctx,
4424 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4425 "DeletePrinterData failed");
4426 torture_assert(tctx,
4427 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4428 "DeletePrinterData failed");
4430 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4432 return true;
4435 static bool test_DeletePrinterData(struct torture_context *tctx,
4436 struct dcerpc_binding_handle *b,
4437 struct policy_handle *handle,
4438 const char *value_name)
4440 NTSTATUS status;
4441 struct spoolss_DeletePrinterData r;
4443 r.in.handle = handle;
4444 r.in.value_name = value_name;
4446 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4447 r.in.value_name);
4449 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4451 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4452 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4454 return true;
4457 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4458 struct dcerpc_binding_handle *b,
4459 struct policy_handle *handle,
4460 const char *key_name,
4461 const char *value_name)
4463 struct spoolss_DeletePrinterDataEx r;
4465 r.in.handle = handle;
4466 r.in.key_name = key_name;
4467 r.in.value_name = value_name;
4469 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4470 r.in.key_name, r.in.value_name);
4472 torture_assert_ntstatus_ok(tctx,
4473 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4474 "DeletePrinterDataEx failed");
4475 torture_assert_werr_ok(tctx, r.out.result,
4476 "DeletePrinterDataEx failed");
4478 return true;
4481 static bool test_DeletePrinterKey(struct torture_context *tctx,
4482 struct dcerpc_binding_handle *b,
4483 struct policy_handle *handle,
4484 const char *key_name)
4486 struct spoolss_DeletePrinterKey r;
4488 r.in.handle = handle;
4489 r.in.key_name = key_name;
4491 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4493 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4494 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4495 return true;
4498 torture_assert_ntstatus_ok(tctx,
4499 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4500 "DeletePrinterKey failed");
4501 torture_assert_werr_ok(tctx, r.out.result,
4502 "DeletePrinterKey failed");
4504 return true;
4507 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4508 struct dcerpc_binding_handle *b,
4509 struct policy_handle *handle)
4511 struct winreg_OpenHKLM r;
4513 r.in.system_name = NULL;
4514 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4515 r.out.handle = handle;
4517 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4519 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4520 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4522 return true;
4525 static void init_winreg_String(struct winreg_String *name, const char *s)
4527 name->name = s;
4528 if (s) {
4529 name->name_len = 2 * (strlen_m(s) + 1);
4530 name->name_size = name->name_len;
4531 } else {
4532 name->name_len = 0;
4533 name->name_size = 0;
4537 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4538 struct dcerpc_binding_handle *b,
4539 struct policy_handle *hive_handle,
4540 const char *keyname,
4541 uint32_t options,
4542 struct policy_handle *key_handle)
4544 struct winreg_OpenKey r;
4546 r.in.parent_handle = hive_handle;
4547 init_winreg_String(&r.in.keyname, keyname);
4548 r.in.options = options;
4549 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4550 r.out.handle = key_handle;
4552 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4554 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4555 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4557 return true;
4560 static bool test_winreg_OpenKey(struct torture_context *tctx,
4561 struct dcerpc_binding_handle *b,
4562 struct policy_handle *hive_handle,
4563 const char *keyname,
4564 struct policy_handle *key_handle)
4566 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4567 REG_OPTION_NON_VOLATILE, key_handle);
4570 static bool test_winreg_CloseKey(struct torture_context *tctx,
4571 struct dcerpc_binding_handle *b,
4572 struct policy_handle *handle)
4574 struct winreg_CloseKey r;
4576 r.in.handle = handle;
4577 r.out.handle = handle;
4579 torture_comment(tctx, "Testing winreg_CloseKey\n");
4581 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4582 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4584 return true;
4587 bool test_winreg_QueryValue(struct torture_context *tctx,
4588 struct dcerpc_binding_handle *b,
4589 struct policy_handle *handle,
4590 const char *value_name,
4591 enum winreg_Type *type_p,
4592 uint32_t *data_size_p,
4593 uint32_t *data_length_p,
4594 uint8_t **data_p)
4596 struct winreg_QueryValue r;
4597 enum winreg_Type type = REG_NONE;
4598 uint32_t data_size = 0;
4599 uint32_t data_length = 0;
4600 struct winreg_String valuename;
4601 uint8_t *data = NULL;
4603 init_winreg_String(&valuename, value_name);
4605 data = talloc_zero_array(tctx, uint8_t, 0);
4607 r.in.handle = handle;
4608 r.in.value_name = &valuename;
4609 r.in.type = &type;
4610 r.in.data_size = &data_size;
4611 r.in.data_length = &data_length;
4612 r.in.data = data;
4613 r.out.type = &type;
4614 r.out.data = data;
4615 r.out.data_size = &data_size;
4616 r.out.data_length = &data_length;
4618 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4620 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4621 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4622 *r.in.data_size = *r.out.data_size;
4623 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4624 r.in.data = data;
4625 r.out.data = data;
4626 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4628 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4630 if (type_p) {
4631 *type_p = *r.out.type;
4633 if (data_size_p) {
4634 *data_size_p = *r.out.data_size;
4636 if (data_length_p) {
4637 *data_length_p = *r.out.data_length;
4639 if (data_p) {
4640 *data_p = r.out.data;
4643 return true;
4646 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4647 struct dcerpc_binding_handle *b,
4648 struct policy_handle *handle,
4649 const char *printer_name,
4650 const char *key_name,
4651 const char *value_name,
4652 enum winreg_Type *w_type,
4653 uint32_t *w_size,
4654 uint32_t *w_length,
4655 uint8_t **w_data)
4657 const char *printer_key;
4658 struct policy_handle key_handle;
4660 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4661 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4663 torture_assert(tctx,
4664 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4666 torture_assert(tctx,
4667 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4669 torture_assert(tctx,
4670 test_winreg_CloseKey(tctx, b, &key_handle), "");
4672 return true;
4675 static bool test_GetForm_winreg(struct torture_context *tctx,
4676 struct dcerpc_binding_handle *b,
4677 struct policy_handle *handle,
4678 const char *key_name,
4679 const char *form_name,
4680 enum winreg_Type *w_type,
4681 uint32_t *w_size,
4682 uint32_t *w_length,
4683 uint8_t **w_data)
4685 struct policy_handle key_handle;
4687 torture_assert(tctx,
4688 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4690 torture_assert(tctx,
4691 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4693 torture_assert(tctx,
4694 test_winreg_CloseKey(tctx, b, &key_handle), "");
4696 return true;
4699 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4700 struct dcerpc_binding_handle *b,
4701 struct policy_handle *handle,
4702 const char *symlink_keyname,
4703 const char *symlink_destination)
4705 /* check if the first key is a symlink to the second key */
4707 enum winreg_Type w_type;
4708 uint32_t w_size;
4709 uint32_t w_length;
4710 uint8_t *w_data;
4711 struct policy_handle key_handle;
4712 DATA_BLOB blob;
4713 const char *str;
4715 if (torture_setting_bool(tctx, "samba3", false)) {
4716 torture_skip(tctx, "skip winreg symlink test against samba");
4719 torture_assert(tctx,
4720 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4721 "failed to open key link");
4723 torture_assert(tctx,
4724 test_winreg_QueryValue(tctx, b, &key_handle,
4725 "SymbolicLinkValue",
4726 &w_type, &w_size, &w_length, &w_data),
4727 "failed to query for 'SymbolicLinkValue' attribute");
4729 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4731 blob = data_blob(w_data, w_size);
4732 str = reg_val_data_string(tctx, REG_SZ, blob);
4734 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4736 torture_assert(tctx,
4737 test_winreg_CloseKey(tctx, b, &key_handle),
4738 "failed to close key link");
4740 return true;
4743 static const char *strip_unc(const char *unc)
4745 char *name;
4747 if (!unc) {
4748 return NULL;
4751 if (unc[0] == '\\' && unc[1] == '\\') {
4752 unc +=2;
4755 name = strchr(unc, '\\');
4756 if (name) {
4757 return name+1;
4760 return unc;
4763 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4764 struct dcerpc_binding_handle *b,
4765 struct policy_handle *handle,
4766 const char *printer_name,
4767 struct dcerpc_binding_handle *winreg_handle,
4768 struct policy_handle *hive_handle)
4770 union spoolss_PrinterInfo info;
4771 const char *keys[] = {
4772 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4773 TOP_LEVEL_PRINT_PRINTERS_KEY
4775 int i;
4776 const char *printername, *sharename;
4778 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4780 torture_assert(tctx,
4781 test_GetPrinter_level(tctx, b, handle, 2, &info),
4782 "failed to get printer info level 2");
4784 printername = strip_unc(info.info2.printername);
4785 sharename = strip_unc(info.info2.sharename);
4787 #define test_sz(wname, iname) \
4788 do {\
4789 DATA_BLOB blob;\
4790 const char *str;\
4791 enum winreg_Type w_type;\
4792 uint32_t w_size;\
4793 uint32_t w_length;\
4794 uint8_t *w_data;\
4795 torture_assert(tctx,\
4796 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4797 &w_type, &w_size, &w_length, &w_data),\
4798 "failed to query winreg");\
4799 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4800 blob = data_blob(w_data, w_size);\
4801 str = reg_val_data_string(tctx, REG_SZ, blob);\
4802 if (w_size == 2 && iname == NULL) {\
4803 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4804 } else {\
4805 torture_assert_str_equal(tctx, str, iname,\
4806 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4808 } while(0);
4810 #define test_dword(wname, iname) \
4811 do {\
4812 uint32_t value;\
4813 enum winreg_Type w_type;\
4814 uint32_t w_size;\
4815 uint32_t w_length;\
4816 uint8_t *w_data;\
4817 torture_assert(tctx,\
4818 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4819 &w_type, &w_size, &w_length, &w_data),\
4820 "failed to query winreg");\
4821 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4822 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4823 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4824 value = IVAL(w_data, 0);\
4825 torture_assert_int_equal(tctx, value, iname,\
4826 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4827 } while(0);
4829 #define test_binary(wname, iname) \
4830 do {\
4831 enum winreg_Type w_type;\
4832 uint32_t w_size;\
4833 uint32_t w_length;\
4834 uint8_t *w_data;\
4835 torture_assert(tctx,\
4836 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4837 &w_type, &w_size, &w_length, &w_data),\
4838 "failed to query winreg");\
4839 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4840 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4841 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4842 "binary unequal");\
4843 } while(0);
4846 #define test_dm(wname, iname) \
4847 do {\
4848 DATA_BLOB blob;\
4849 struct spoolss_DeviceMode dm;\
4850 enum ndr_err_code ndr_err;\
4851 enum winreg_Type w_type;\
4852 uint32_t w_size;\
4853 uint32_t w_length;\
4854 uint8_t *w_data;\
4855 torture_assert(tctx,\
4856 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4857 &w_type, &w_size, &w_length, &w_data),\
4858 "failed to query winreg");\
4859 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4860 blob = data_blob(w_data, w_size);\
4861 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4862 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4863 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4864 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4865 "dm unequal");\
4866 } while(0);
4868 #define test_sd(wname, iname) \
4869 do {\
4870 DATA_BLOB blob;\
4871 struct security_descriptor sd;\
4872 enum ndr_err_code ndr_err;\
4873 enum winreg_Type w_type;\
4874 uint32_t w_size;\
4875 uint32_t w_length;\
4876 uint8_t *w_data;\
4877 torture_assert(tctx,\
4878 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4879 &w_type, &w_size, &w_length, &w_data),\
4880 "failed to query winreg");\
4881 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4882 blob = data_blob(w_data, w_size);\
4883 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4884 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4885 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4886 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4887 "sd unequal");\
4888 } while(0);
4890 #define test_multi_sz(wname, iname) \
4891 do {\
4892 DATA_BLOB blob;\
4893 const char **array;\
4894 enum winreg_Type w_type;\
4895 uint32_t w_size;\
4896 uint32_t w_length;\
4897 uint8_t *w_data;\
4898 int i;\
4899 torture_assert(tctx,\
4900 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4901 &w_type, &w_size, &w_length, &w_data),\
4902 "failed to query winreg");\
4903 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4904 blob = data_blob(w_data, w_size);\
4905 torture_assert(tctx, \
4906 pull_reg_multi_sz(tctx, &blob, &array),\
4907 "failed to pull multi sz");\
4908 for (i=0; array[i] != NULL; i++) {\
4909 torture_assert_str_equal(tctx, array[i], iname[i],\
4910 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4912 } while(0);
4914 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4915 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4916 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4918 torture_warning(tctx, "failed to check for winreg symlink");
4921 for (i=0; i < ARRAY_SIZE(keys); i++) {
4923 const char *printer_key;
4924 struct policy_handle key_handle;
4926 printer_key = talloc_asprintf(tctx, "%s\\%s",
4927 keys[i], printer_name);
4929 torture_assert(tctx,
4930 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4932 test_sz("Name", printername);
4933 test_sz("Share Name", sharename);
4934 test_sz("Port", info.info2.portname);
4935 test_sz("Printer Driver", info.info2.drivername);
4936 test_sz("Description", info.info2.comment);
4937 test_sz("Location", info.info2.location);
4938 test_sz("Separator File", info.info2.sepfile);
4939 test_sz("Print Processor", info.info2.printprocessor);
4940 test_sz("Datatype", info.info2.datatype);
4941 test_sz("Parameters", info.info2.parameters);
4942 /* winreg: 0, spoolss not */
4943 /* test_dword("Attributes", info.info2.attributes); */
4944 test_dword("Priority", info.info2.priority);
4945 test_dword("Default Priority", info.info2.defaultpriority);
4946 /* winreg: 60, spoolss: 0 */
4947 /* test_dword("StartTime", info.info2.starttime); */
4948 /* test_dword("UntilTime", info.info2.untiltime); */
4949 /* winreg != spoolss */
4950 /* test_dword("Status", info.info2.status); */
4951 test_dm("Default DevMode", info.info2.devmode);
4952 test_sd("Security", info.info2.secdesc);
4954 torture_assert(tctx,
4955 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4958 #undef test_dm
4960 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4962 return true;
4965 static bool test_GetPrintserverInfo_winreg(struct torture_context *tctx,
4966 struct dcerpc_binding_handle *b,
4967 struct policy_handle *handle,
4968 struct dcerpc_binding_handle *winreg_handle,
4969 struct policy_handle *hive_handle)
4971 union spoolss_PrinterInfo info;
4972 struct policy_handle key_handle;
4974 torture_comment(tctx,
4975 "Testing Printserver Info and winreg consistency\n");
4977 torture_assert(tctx,
4978 test_GetPrinter_level(tctx, b, handle, 3, &info),
4979 "failed to get printer info level 2");
4981 torture_assert(tctx,
4982 test_winreg_OpenKey(tctx, winreg_handle, hive_handle,
4983 TOP_LEVEL_CONTROL_KEY, &key_handle), "");
4985 test_sd("ServerSecurityDescriptor", info.info3.secdesc);
4987 torture_assert(tctx,
4988 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4990 #undef test_sd
4992 torture_comment(tctx,
4993 "Printserver Info and winreg consistency test succeeded\n\n");
4995 return true;
4999 static bool test_PrintProcessors(struct torture_context *tctx,
5000 struct dcerpc_binding_handle *b,
5001 const char *environment,
5002 struct dcerpc_binding_handle *winreg_handle,
5003 struct policy_handle *hive_handle)
5005 union spoolss_PrintProcessorInfo *info;
5006 uint32_t count;
5007 int i;
5009 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
5011 torture_assert(tctx,
5012 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
5013 "failed to enum print processors level 1");
5015 for (i=0; i < count; i++) {
5017 const char *processor_key;
5018 struct policy_handle key_handle;
5020 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
5021 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5022 environment,
5023 info[i].info1.print_processor_name);
5025 torture_assert(tctx,
5026 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
5028 /* nothing to check in there so far */
5030 torture_assert(tctx,
5031 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5034 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
5036 return true;
5039 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5040 struct dcerpc_binding_handle *b,
5041 struct policy_handle *handle,
5042 const char *driver_name,
5043 const char *architecture,
5044 uint32_t level,
5045 uint32_t client_major_version,
5046 uint32_t client_minor_version,
5047 union spoolss_DriverInfo *info_p,
5048 WERROR *result);
5050 static const char *strip_path(const char *path)
5052 char *p;
5054 if (path == NULL) {
5055 return NULL;
5058 p = strrchr(path, '\\');
5059 if (p) {
5060 return p+1;
5063 return path;
5066 static const char **strip_paths(const char **path_array)
5068 int i;
5070 if (path_array == NULL) {
5071 return NULL;
5074 for (i=0; path_array[i] != NULL; i++) {
5075 path_array[i] = strip_path(path_array[i]);
5078 return path_array;
5081 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
5083 time_t t;
5084 struct tm *tm;
5086 if (nt == 0) {
5087 return talloc_strdup(mem_ctx, "01/01/1601");
5090 t = nt_time_to_unix(nt);
5091 tm = localtime(&t);
5093 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
5094 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
5097 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
5099 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
5100 (unsigned)((v >> 48) & 0xFFFF),
5101 (unsigned)((v >> 32) & 0xFFFF),
5102 (unsigned)((v >> 16) & 0xFFFF),
5103 (unsigned)(v & 0xFFFF));
5106 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
5107 struct dcerpc_binding_handle *b,
5108 struct policy_handle *handle,
5109 const char *printer_name,
5110 const char *driver_name,
5111 const char *environment,
5112 enum spoolss_DriverOSVersion version,
5113 struct dcerpc_binding_handle *winreg_handle,
5114 struct policy_handle *hive_handle,
5115 const char *server_name_slash)
5117 WERROR result = WERR_OK;
5118 union spoolss_DriverInfo info;
5119 const char *driver_key;
5120 struct policy_handle key_handle;
5122 const char *driver_path;
5123 const char *data_file;
5124 const char *config_file;
5125 const char *help_file;
5126 const char **dependent_files;
5128 const char *driver_date;
5129 const char *inbox_driver_date;
5131 const char *driver_version;
5132 const char *inbox_driver_version;
5134 ZERO_STRUCT(key_handle);
5136 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
5138 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
5139 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5140 environment,
5141 version,
5142 driver_name);
5144 torture_assert(tctx,
5145 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
5146 "failed to open driver key");
5148 if (torture_setting_bool(tctx, "samba3", false) ||
5149 torture_setting_bool(tctx, "w2k3", false)) {
5150 goto try_level6;
5153 if (handle) {
5154 torture_assert(tctx,
5155 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
5156 "failed to get driver info level 8");
5157 } else {
5158 torture_assert(tctx,
5159 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
5160 "failed to get driver info level 8");
5163 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
5164 goto try_level6;
5167 driver_path = strip_path(info.info8.driver_path);
5168 data_file = strip_path(info.info8.data_file);
5169 config_file = strip_path(info.info8.config_file);
5170 help_file = strip_path(info.info8.help_file);
5171 dependent_files = strip_paths(info.info8.dependent_files);
5173 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5174 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5176 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5177 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5179 test_sz("Configuration File", config_file);
5180 test_sz("Data File", data_file);
5181 test_sz("Datatype", info.info8.default_datatype);
5182 test_sz("Driver", driver_path);
5183 test_sz("DriverDate", driver_date);
5184 test_sz("DriverVersion", driver_version);
5185 test_sz("HardwareID", info.info8.hardware_id);
5186 test_sz("Help File", help_file);
5187 test_sz("InfPath", info.info8.inf_path);
5188 test_sz("Manufacturer", info.info8.manufacturer_name);
5189 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5190 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5191 test_sz("Monitor", info.info8.monitor_name);
5192 test_sz("OEM URL", info.info8.manufacturer_url);
5193 test_sz("Print Processor", info.info8.print_processor);
5194 test_sz("Provider", info.info8.provider);
5195 test_sz("VendorSetup", info.info8.vendor_setup);
5196 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5197 test_multi_sz("Dependent Files", dependent_files);
5198 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5199 test_multi_sz("Previous Names", info.info8.previous_names);
5200 /* test_dword("Attributes", ?); */
5201 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5202 test_dword("Version", info.info8.version);
5203 /* test_dword("TempDir", ?); */
5205 try_level6:
5207 if (handle) {
5208 torture_assert(tctx,
5209 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5210 "failed to get driver info level 6");
5211 } else {
5212 torture_assert(tctx,
5213 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5214 "failed to get driver info level 6");
5217 driver_path = strip_path(info.info6.driver_path);
5218 data_file = strip_path(info.info6.data_file);
5219 config_file = strip_path(info.info6.config_file);
5220 help_file = strip_path(info.info6.help_file);
5221 dependent_files = strip_paths(info.info6.dependent_files);
5223 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5225 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5227 test_sz("Configuration File", config_file);
5228 test_sz("Data File", data_file);
5229 test_sz("Datatype", info.info6.default_datatype);
5230 test_sz("Driver", driver_path);
5231 if (torture_setting_bool(tctx, "w2k3", false)) {
5232 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5233 push_nttime(blob.data, 0, info.info6.driver_date);
5234 test_binary("DriverDate", blob);
5235 SBVAL(blob.data, 0, info.info6.driver_version);
5236 test_binary("DriverVersion", blob);
5237 } else {
5238 test_sz("DriverDate", driver_date);
5239 test_sz("DriverVersion", driver_version);
5241 test_sz("HardwareID", info.info6.hardware_id);
5242 test_sz("Help File", help_file);
5243 test_sz("Manufacturer", info.info6.manufacturer_name);
5244 test_sz("Monitor", info.info6.monitor_name);
5245 test_sz("OEM URL", info.info6.manufacturer_url);
5246 test_sz("Provider", info.info6.provider);
5247 test_multi_sz("Dependent Files", dependent_files);
5248 test_multi_sz("Previous Names", info.info6.previous_names);
5249 /* test_dword("Attributes", ?); */
5250 test_dword("Version", info.info6.version);
5251 /* test_dword("TempDir", ?); */
5253 if (handle) {
5254 torture_assert(tctx,
5255 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5256 "failed to get driver info level 3");
5257 } else {
5258 torture_assert(tctx,
5259 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5260 "failed to get driver info level 3");
5263 driver_path = strip_path(info.info3.driver_path);
5264 data_file = strip_path(info.info3.data_file);
5265 config_file = strip_path(info.info3.config_file);
5266 help_file = strip_path(info.info3.help_file);
5267 dependent_files = strip_paths(info.info3.dependent_files);
5269 test_sz("Configuration File", config_file);
5270 test_sz("Data File", data_file);
5271 test_sz("Datatype", info.info3.default_datatype);
5272 test_sz("Driver", driver_path);
5273 test_sz("Help File", help_file);
5274 test_sz("Monitor", info.info3.monitor_name);
5275 test_multi_sz("Dependent Files", dependent_files);
5276 /* test_dword("Attributes", ?); */
5277 test_dword("Version", info.info3.version);
5278 /* test_dword("TempDir", ?); */
5281 torture_assert(tctx,
5282 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5284 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5286 return true;
5289 #undef test_sz
5290 #undef test_dword
5292 static bool test_SetPrinterData(struct torture_context *tctx,
5293 struct dcerpc_binding_handle *b,
5294 struct policy_handle *handle,
5295 const char *value_name,
5296 enum winreg_Type type,
5297 uint8_t *data,
5298 uint32_t offered)
5300 struct spoolss_SetPrinterData r;
5302 r.in.handle = handle;
5303 r.in.value_name = value_name;
5304 r.in.type = type;
5305 r.in.data = data;
5306 r.in.offered = offered;
5308 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5309 r.in.value_name);
5311 torture_assert_ntstatus_ok(tctx,
5312 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5313 "SetPrinterData failed");
5314 torture_assert_werr_ok(tctx, r.out.result,
5315 "SetPrinterData failed");
5317 return true;
5320 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5321 struct dcerpc_binding_handle *b,
5322 struct policy_handle *handle,
5323 const char *printer_name,
5324 struct dcerpc_binding_handle *winreg_handle,
5325 struct policy_handle *hive_handle)
5327 const char *values[] = {
5328 "spootyfoot",
5329 "spooty\\foot",
5330 #if 0
5331 /* FIXME: not working with s3 atm. */
5332 "spooty,foot",
5333 "spooty,fo,ot",
5334 #endif
5335 "spooty foot",
5336 #if 0
5337 /* FIXME: not working with s3 atm. */
5338 "spooty\\fo,ot",
5339 "spooty,fo\\ot"
5340 #endif
5342 int i;
5344 for (i=0; i < ARRAY_SIZE(values); i++) {
5346 enum winreg_Type type, expected_type = REG_SZ;
5347 DATA_BLOB blob;
5348 uint8_t *data;
5349 uint32_t needed;
5351 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5352 type = REG_SZ;
5354 torture_assert(tctx,
5355 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5356 "SetPrinterData failed");
5358 torture_assert(tctx,
5359 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5360 "GetPrinterData failed");
5362 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5363 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5364 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5366 if (winreg_handle && hive_handle) {
5368 enum winreg_Type w_type;
5369 uint32_t w_size;
5370 uint32_t w_length;
5371 uint8_t *w_data;
5373 torture_assert(tctx,
5374 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5375 printer_name, "PrinterDriverData", values[i],
5376 &w_type, &w_size, &w_length, &w_data), "");
5378 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5379 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5380 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5381 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5384 torture_assert(tctx,
5385 test_DeletePrinterData(tctx, b, handle, values[i]),
5386 "DeletePrinterData failed");
5389 return true;
5393 static bool test_EnumPrinterKey(struct torture_context *tctx,
5394 struct dcerpc_binding_handle *b,
5395 struct policy_handle *handle,
5396 const char *key_name,
5397 const char ***array);
5399 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5400 struct dcerpc_binding_handle *b,
5401 struct policy_handle *handle,
5402 const char *key_name,
5403 const char *value_name,
5404 enum winreg_Type type,
5405 uint8_t *data,
5406 uint32_t offered)
5408 NTSTATUS status;
5409 struct spoolss_SetPrinterDataEx r;
5411 r.in.handle = handle;
5412 r.in.key_name = key_name;
5413 r.in.value_name = value_name;
5414 r.in.type = type;
5415 r.in.data = data;
5416 r.in.offered = offered;
5418 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5419 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5421 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5423 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5424 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5426 return true;
5429 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5430 struct dcerpc_pipe *p,
5431 struct policy_handle *handle)
5433 struct dcerpc_binding_handle *b = p->binding_handle;
5434 const char *value_name = "dog";
5435 const char *keys[] = {
5436 "torturedataex",
5437 "torture data ex",
5438 "torturedataex_with_subkey\\subkey",
5439 "torturedataex_with_subkey\\subkey:0",
5440 "torturedataex_with_subkey\\subkey:1",
5441 "torturedataex_with_subkey\\subkey\\subsubkey",
5442 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5443 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5444 "torture,data",
5445 "torture,data,ex",
5446 "torture,data\\ex",
5447 "torture\\data,ex",
5448 "torture/data",
5449 "torture/data ex",
5450 "torture/data ex/sub",
5451 "torture//data",
5452 "torture//data ex",
5453 "torture//data ex/sub",
5454 "torture//data ex//sub",
5456 int i;
5458 for (i=0; i < ARRAY_SIZE(keys); i++) {
5460 char *c;
5461 const char *key;
5462 enum winreg_Type type;
5463 DATA_BLOB blob_in, blob_out;
5464 const char **subkeys;
5465 uint32_t ecount;
5466 struct spoolss_PrinterEnumValues *einfo;
5467 uint32_t needed;
5469 blob_in = data_blob_talloc(tctx, NULL, 42);
5471 generate_random_buffer(blob_in.data, blob_in.length);
5473 torture_assert(tctx,
5474 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5475 "failed to call SetPrinterDataEx");
5477 torture_assert(tctx,
5478 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5479 "failed to call GetPrinterDataEx");
5481 blob_out.length = needed;
5482 torture_assert(tctx,
5483 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5484 "failed to call EnumPrinterDataEx");
5486 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5487 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5488 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5490 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5491 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5492 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5493 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5494 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5495 if (einfo[0].data_length > 0) {
5496 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5499 key = talloc_strdup(tctx, keys[i]);
5501 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5502 return false;
5505 c = strchr(key, '\\');
5506 if (c) {
5507 int k;
5509 /* we have subkeys */
5511 *c = 0;
5513 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5514 return false;
5517 for (k=0; subkeys && subkeys[k]; k++) {
5519 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5521 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5522 return false;
5526 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5527 return false;
5530 } else {
5531 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5532 return false;
5537 return true;
5540 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5541 struct dcerpc_pipe *p,
5542 struct policy_handle *handle)
5544 struct dcerpc_binding_handle *b = p->binding_handle;
5545 const char *key = "torturedataex";
5546 const char *values[] = {
5547 "torture_value",
5548 "torture value",
5549 "torture,value",
5550 "torture/value",
5551 "torture\\value",
5552 "torture\\\\value"
5554 int i;
5556 for (i=0; i < ARRAY_SIZE(values); i++) {
5558 enum winreg_Type type = REG_NONE;
5559 DATA_BLOB blob_in = data_blob_null;
5560 DATA_BLOB blob_out = data_blob_null;
5561 uint32_t ecount;
5562 struct spoolss_PrinterEnumValues *einfo;
5563 uint32_t needed = 0;
5565 if (torture_setting_bool(tctx, "samba3", false)) {
5566 char *q;
5567 q = strrchr(values[i], ',');
5568 if (q) {
5569 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5570 values[i]);
5571 continue;
5575 blob_in = data_blob_talloc(tctx, NULL, 42);
5577 generate_random_buffer(blob_in.data, blob_in.length);
5579 torture_assert(tctx,
5580 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5581 "failed to call SetPrinterDataEx");
5583 torture_assert(tctx,
5584 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5585 "failed to call GetPrinterDataEx");
5587 blob_out.length = needed;
5588 torture_assert(tctx,
5589 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5590 "failed to call EnumPrinterDataEx");
5592 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5593 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5594 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5596 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5597 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5598 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5599 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5600 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5601 if (einfo[0].data_length > 0) {
5602 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5605 torture_assert(tctx,
5606 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5607 "failed to call DeletePrinterDataEx");
5610 return true;
5614 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5615 struct dcerpc_pipe *p,
5616 struct policy_handle *handle,
5617 const char *printername,
5618 struct dcerpc_binding_handle *winreg_handle,
5619 struct policy_handle *hive_handle)
5621 struct dcerpc_binding_handle *b = p->binding_handle;
5622 const char *value_name = "dog";
5623 const char *key_name = "torturedataex";
5624 enum winreg_Type types[] = {
5625 REG_SZ,
5626 REG_MULTI_SZ,
5627 REG_DWORD,
5628 REG_BINARY
5630 const char *str = "abcdefghi";
5631 int t, s;
5633 for (t=0; t < ARRAY_SIZE(types); t++) {
5634 for (s=0; s < strlen(str); s++) {
5636 enum winreg_Type type;
5637 const char *string = talloc_strndup(tctx, str, s);
5638 const char *array[2];
5639 DATA_BLOB blob = data_blob_string_const(string);
5640 DATA_BLOB data;
5641 uint8_t *data_out;
5642 uint32_t needed, offered = 0;
5643 uint32_t ecount;
5644 struct spoolss_PrinterEnumValues *einfo;
5646 array[0] = talloc_strdup(tctx, string);
5647 array[1] = NULL;
5649 if (types[t] == REG_DWORD) {
5650 s = 0xffff;
5653 switch (types[t]) {
5654 case REG_BINARY:
5655 data = blob;
5656 offered = blob.length;
5657 break;
5658 case REG_DWORD:
5659 data = data_blob_talloc(tctx, NULL, 4);
5660 SIVAL(data.data, 0, 0x12345678);
5661 offered = 4;
5662 break;
5663 case REG_SZ:
5664 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5665 type = REG_SZ;
5666 offered = data.length;
5667 /*strlen_m_term(data.string)*2;*/
5668 break;
5669 case REG_MULTI_SZ:
5670 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5671 type = REG_MULTI_SZ;
5672 offered = data.length;
5673 break;
5674 default:
5675 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5678 torture_assert(tctx,
5679 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5680 "failed to call SetPrinterDataEx");
5682 torture_assert(tctx,
5683 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5684 "failed to call GetPrinterDataEx");
5686 torture_assert(tctx,
5687 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5688 "failed to call EnumPrinterDataEx");
5690 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5691 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5692 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5694 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5695 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5696 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5697 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5698 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5699 if (einfo[0].data_length > 0) {
5700 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5703 if (winreg_handle && hive_handle) {
5704 enum winreg_Type w_type;
5705 uint32_t w_size;
5706 uint32_t w_length;
5707 uint8_t *w_data;
5709 torture_assert(tctx,
5710 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5711 printername, key_name, value_name,
5712 &w_type, &w_size, &w_length, &w_data), "");
5714 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5715 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5716 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5717 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5720 torture_assert(tctx,
5721 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5722 "failed to call DeletePrinterDataEx");
5726 return true;
5729 static bool test_PrinterData_winreg(struct torture_context *tctx,
5730 struct dcerpc_pipe *p,
5731 struct policy_handle *handle,
5732 const char *printer_name)
5734 struct dcerpc_binding_handle *b = p->binding_handle;
5735 struct dcerpc_pipe *p2;
5736 bool ret = true;
5737 struct policy_handle hive_handle;
5738 struct dcerpc_binding_handle *b2;
5740 torture_assert_ntstatus_ok(tctx,
5741 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5742 "could not open winreg pipe");
5743 b2 = p2->binding_handle;
5745 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5747 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5748 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5750 test_winreg_CloseKey(tctx, b2, &hive_handle);
5752 talloc_free(p2);
5754 return ret;
5757 static bool test_Forms_winreg(struct torture_context *tctx,
5758 struct dcerpc_binding_handle *b,
5759 struct policy_handle *handle,
5760 bool print_server,
5761 const char *printer_name)
5763 struct dcerpc_pipe *p2;
5764 bool ret = true;
5765 struct policy_handle hive_handle;
5766 struct dcerpc_binding_handle *b2;
5768 torture_assert_ntstatus_ok(tctx,
5769 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5770 "could not open winreg pipe");
5771 b2 = p2->binding_handle;
5773 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5775 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5777 test_winreg_CloseKey(tctx, b2, &hive_handle);
5779 talloc_free(p2);
5781 return ret;
5784 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5785 struct dcerpc_pipe *p,
5786 struct policy_handle *handle,
5787 const char *printer_name)
5789 struct dcerpc_binding_handle *b = p->binding_handle;
5790 struct dcerpc_pipe *p2;
5791 bool ret = true;
5792 struct policy_handle hive_handle;
5793 struct dcerpc_binding_handle *b2;
5795 torture_assert_ntstatus_ok(tctx,
5796 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5797 "could not open winreg pipe");
5798 b2 = p2->binding_handle;
5800 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5802 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5804 test_winreg_CloseKey(tctx, b2, &hive_handle);
5806 talloc_free(p2);
5808 return ret;
5811 static bool test_PrintserverInfo_winreg(struct torture_context *tctx,
5812 struct dcerpc_pipe *p,
5813 struct policy_handle *handle)
5815 struct dcerpc_binding_handle *b = p->binding_handle;
5816 struct dcerpc_pipe *p2;
5817 bool ret = true;
5818 struct policy_handle hive_handle;
5819 struct dcerpc_binding_handle *b2;
5821 torture_assert_ntstatus_ok(tctx,
5822 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5823 "could not open winreg pipe");
5824 b2 = p2->binding_handle;
5826 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5828 ret = test_GetPrintserverInfo_winreg(tctx, b, handle, b2, &hive_handle);
5830 test_winreg_CloseKey(tctx, b2, &hive_handle);
5832 talloc_free(p2);
5834 return ret;
5838 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5839 struct dcerpc_pipe *p,
5840 struct policy_handle *handle,
5841 const char *printer_name,
5842 const char *driver_name,
5843 const char *environment,
5844 enum spoolss_DriverOSVersion version)
5846 struct dcerpc_binding_handle *b = p->binding_handle;
5847 struct dcerpc_pipe *p2;
5848 bool ret = true;
5849 struct policy_handle hive_handle;
5850 struct dcerpc_binding_handle *b2;
5852 torture_assert_ntstatus_ok(tctx,
5853 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5854 "could not open winreg pipe");
5855 b2 = p2->binding_handle;
5857 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5859 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5861 test_winreg_CloseKey(tctx, b2, &hive_handle);
5863 talloc_free(p2);
5865 return ret;
5868 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5869 struct dcerpc_binding_handle *b,
5870 const char *environment)
5872 struct dcerpc_pipe *p2;
5873 bool ret = true;
5874 struct policy_handle hive_handle;
5875 struct dcerpc_binding_handle *b2;
5877 torture_assert_ntstatus_ok(tctx,
5878 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5879 "could not open winreg pipe");
5880 b2 = p2->binding_handle;
5882 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5884 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5886 test_winreg_CloseKey(tctx, b2, &hive_handle);
5888 talloc_free(p2);
5890 return ret;
5893 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5894 struct dcerpc_pipe *p,
5895 struct policy_handle *handle,
5896 const char *printer_name)
5898 struct spoolss_SetPrinterInfoCtr info_ctr;
5899 struct spoolss_DevmodeContainer devmode_ctr;
5900 struct sec_desc_buf secdesc_ctr;
5901 union spoolss_SetPrinterInfo sinfo;
5902 union spoolss_PrinterInfo info;
5903 struct dcerpc_binding_handle *b = p->binding_handle;
5904 const char *pname;
5906 ZERO_STRUCT(info_ctr);
5907 ZERO_STRUCT(devmode_ctr);
5908 ZERO_STRUCT(secdesc_ctr);
5910 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5912 torture_assert(tctx,
5913 test_GetPrinter_level(tctx, b, handle, 2, &info),
5914 "failed to query Printer level 2");
5916 torture_assert(tctx,
5917 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5918 "failed to convert");
5920 info_ctr.level = 2;
5921 info_ctr.info = sinfo;
5923 #define TEST_SZ(wname, iname) \
5924 do {\
5925 enum winreg_Type type;\
5926 uint8_t *data;\
5927 uint32_t needed;\
5928 DATA_BLOB blob;\
5929 const char *str;\
5930 torture_assert(tctx,\
5931 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5932 "failed to query");\
5933 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5934 blob = data_blob_const(data, needed);\
5935 torture_assert(tctx,\
5936 pull_reg_sz(tctx, &blob, &str),\
5937 "failed to pull REG_SZ");\
5938 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5939 } while(0);
5942 #define TEST_SET_SZ(wname, iname, val) \
5943 do {\
5944 enum winreg_Type type;\
5945 uint8_t *data;\
5946 uint32_t needed;\
5947 DATA_BLOB blob;\
5948 const char *str;\
5949 sinfo.info2->iname = val;\
5950 torture_assert(tctx,\
5951 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5952 "failed to call SetPrinter");\
5953 torture_assert(tctx,\
5954 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5955 "failed to query");\
5956 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5957 blob = data_blob_const(data, needed);\
5958 torture_assert(tctx,\
5959 pull_reg_sz(tctx, &blob, &str),\
5960 "failed to pull REG_SZ");\
5961 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5962 } while(0);
5964 #define TEST_SET_DWORD(wname, iname, val) \
5965 do {\
5966 enum winreg_Type type;\
5967 uint8_t *data;\
5968 uint32_t needed;\
5969 uint32_t value;\
5970 sinfo.info2->iname = val;\
5971 torture_assert(tctx,\
5972 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5973 "failed to call SetPrinter");\
5974 torture_assert(tctx,\
5975 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5976 "failed to query");\
5977 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5978 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5979 value = IVAL(data, 0); \
5980 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5981 } while(0);
5983 TEST_SET_SZ("description", comment, "newval");
5984 TEST_SET_SZ("location", location, "newval");
5985 TEST_SET_SZ("driverName", drivername, "newval");
5986 /* TEST_SET_DWORD("priority", priority, 25); */
5988 torture_assert(tctx,
5989 test_GetPrinter_level(tctx, b, handle, 2, &info),
5990 "failed to query Printer level 2");
5992 TEST_SZ("description", info.info2.comment);
5993 TEST_SZ("driverName", info.info2.drivername);
5994 TEST_SZ("location", info.info2.location);
5996 pname = strrchr(info.info2.printername, '\\');
5997 if (pname == NULL) {
5998 pname = info.info2.printername;
5999 } else {
6000 pname++;
6002 TEST_SZ("printerName", pname);
6003 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
6004 /* TEST_SZ("printShareName", info.info2.sharename); */
6006 /* FIXME gd: complete the list */
6008 #undef TEST_SZ
6009 #undef TEST_SET_SZ
6010 #undef TEST_DWORD
6012 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
6014 return true;
6017 static bool test_print_processors_winreg(struct torture_context *tctx,
6018 void *private_data)
6020 struct test_spoolss_context *ctx =
6021 talloc_get_type_abort(private_data, struct test_spoolss_context);
6022 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6023 struct dcerpc_binding_handle *b = p->binding_handle;
6025 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
6028 static bool test_AddPrintProcessor(struct torture_context *tctx,
6029 struct dcerpc_binding_handle *b,
6030 const char *environment,
6031 const char *path_name,
6032 const char *print_processor_name,
6033 WERROR expected_error)
6035 struct spoolss_AddPrintProcessor r;
6037 r.in.server = NULL;
6038 r.in.architecture = environment;
6039 r.in.path_name = path_name;
6040 r.in.print_processor_name = print_processor_name;
6042 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
6043 print_processor_name);
6045 torture_assert_ntstatus_ok(tctx,
6046 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
6047 "spoolss_AddPrintProcessor failed");
6048 torture_assert_werr_equal(tctx, r.out.result, expected_error,
6049 "spoolss_AddPrintProcessor failed");
6051 return true;
6054 static bool test_DeletePrintProcessor(struct torture_context *tctx,
6055 struct dcerpc_binding_handle *b,
6056 const char *environment,
6057 const char *print_processor_name,
6058 WERROR expected_error)
6060 struct spoolss_DeletePrintProcessor r;
6062 r.in.server = NULL;
6063 r.in.architecture = environment;
6064 r.in.print_processor_name = print_processor_name;
6066 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
6067 print_processor_name);
6069 torture_assert_ntstatus_ok(tctx,
6070 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
6071 "spoolss_DeletePrintProcessor failed");
6072 torture_assert_werr_equal(tctx, r.out.result, expected_error,
6073 "spoolss_DeletePrintProcessor failed");
6075 return true;
6078 static bool test_add_print_processor(struct torture_context *tctx,
6079 void *private_data)
6081 struct test_spoolss_context *ctx =
6082 talloc_get_type_abort(private_data, struct test_spoolss_context);
6083 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6084 struct dcerpc_binding_handle *b = p->binding_handle;
6085 int i;
6087 struct {
6088 const char *environment;
6089 const char *path_name;
6090 const char *print_processor_name;
6091 WERROR expected_add_result;
6092 WERROR expected_del_result;
6093 } tests[] = {
6095 .environment = ctx->environment,
6096 .path_name = "",
6097 .print_processor_name = "winprint",
6098 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
6099 .expected_del_result = WERR_CAN_NOT_COMPLETE
6101 .environment = ctx->environment,
6102 .path_name = "",
6103 .print_processor_name = "unknown",
6104 .expected_add_result = WERR_MOD_NOT_FOUND,
6105 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
6109 for (i=0; i < ARRAY_SIZE(tests); i++) {
6110 torture_assert(tctx,
6111 test_AddPrintProcessor(tctx, b,
6112 tests[i].environment,
6113 tests[i].path_name,
6114 tests[i].print_processor_name,
6115 tests[i].expected_add_result),
6116 "add print processor failed");
6117 torture_assert(tctx,
6118 test_DeletePrintProcessor(tctx, b,
6119 tests[i].environment,
6120 tests[i].print_processor_name,
6121 tests[i].expected_del_result),
6122 "delete print processor failed");
6125 return true;
6128 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
6129 struct dcerpc_binding_handle *b,
6130 struct policy_handle *handle,
6131 uint32_t *change_id)
6133 enum winreg_Type type;
6134 uint8_t *data;
6135 uint32_t needed;
6137 torture_assert(tctx,
6138 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
6139 "failed to call GetPrinterData");
6141 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6142 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6144 *change_id = IVAL(data, 0);
6146 return true;
6149 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
6150 struct dcerpc_pipe *p,
6151 struct policy_handle *handle,
6152 uint32_t *change_id)
6154 enum winreg_Type type = REG_NONE;
6155 uint8_t *data = NULL;
6156 uint32_t needed = 0;
6158 torture_assert(tctx,
6159 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
6160 "failed to call GetPrinterData");
6162 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6163 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6165 *change_id = IVAL(data, 0);
6167 return true;
6170 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
6171 struct dcerpc_binding_handle *b,
6172 struct policy_handle *handle,
6173 uint32_t *change_id)
6175 union spoolss_PrinterInfo info;
6177 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
6178 "failed to query Printer level 0");
6180 *change_id = info.info0.change_id;
6182 return true;
6185 static bool test_ChangeID(struct torture_context *tctx,
6186 struct dcerpc_pipe *p,
6187 struct policy_handle *handle)
6189 uint32_t change_id, change_id_ex, change_id_info;
6190 uint32_t change_id2, change_id_ex2, change_id_info2;
6191 union spoolss_PrinterInfo info;
6192 const char *comment;
6193 struct dcerpc_binding_handle *b = p->binding_handle;
6195 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
6197 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6198 "failed to query for ChangeID");
6199 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6200 "failed to query for ChangeID");
6201 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6202 "failed to query for ChangeID");
6204 torture_assert_int_equal(tctx, change_id, change_id_ex,
6205 "change_ids should all be equal");
6206 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6207 "change_ids should all be equal");
6210 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6212 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6213 "failed to query for ChangeID");
6214 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6215 "failed to query Printer level 2");
6216 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6217 "failed to query for ChangeID");
6218 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6219 "failed to query for ChangeID");
6220 torture_assert_int_equal(tctx, change_id, change_id_ex,
6221 "change_id should not have changed");
6222 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6223 "change_id should not have changed");
6226 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6228 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6229 "failed to query for ChangeID");
6230 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6231 "failed to query for ChangeID");
6232 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6233 "failed to query for ChangeID");
6234 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6235 "failed to query Printer level 2");
6236 comment = talloc_strdup(tctx, info.info2.comment);
6239 struct spoolss_SetPrinterInfoCtr info_ctr;
6240 struct spoolss_DevmodeContainer devmode_ctr;
6241 struct sec_desc_buf secdesc_ctr;
6242 union spoolss_SetPrinterInfo sinfo;
6244 ZERO_STRUCT(info_ctr);
6245 ZERO_STRUCT(devmode_ctr);
6246 ZERO_STRUCT(secdesc_ctr);
6249 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6250 sinfo.info2->comment = "torture_comment";
6252 info_ctr.level = 2;
6253 info_ctr.info = sinfo;
6255 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6256 "failed to call SetPrinter");
6258 sinfo.info2->comment = comment;
6260 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6261 "failed to call SetPrinter");
6265 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6266 "failed to query for ChangeID");
6267 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6268 "failed to query for ChangeID");
6269 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6270 "failed to query for ChangeID");
6272 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6273 "change_ids should all be equal");
6274 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6275 "change_ids should all be equal");
6277 torture_assert(tctx, (change_id < change_id2),
6278 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6279 change_id2, change_id));
6280 torture_assert(tctx, (change_id_ex < change_id_ex2),
6281 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6282 change_id_ex2, change_id_ex));
6283 torture_assert(tctx, (change_id_info < change_id_info2),
6284 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6285 change_id_info2, change_id_info));
6287 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6289 return true;
6292 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6293 struct dcerpc_pipe *p,
6294 struct policy_handle *handle)
6296 NTSTATUS status;
6297 struct cli_credentials *anon_creds;
6298 const struct dcerpc_binding *binding2;
6299 struct dcerpc_pipe *p2;
6300 struct spoolss_ClosePrinter cp;
6302 /* only makes sense on SMB */
6303 if (p->conn->transport.transport != NCACN_NP) {
6304 return true;
6307 torture_comment(tctx, "Testing close on secondary pipe\n");
6309 anon_creds = cli_credentials_init_anon(tctx);
6310 torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
6312 binding2 = p->binding;
6313 status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_spoolss,
6314 anon_creds, tctx->lp_ctx,
6315 tctx, &p2);
6316 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6318 cp.in.handle = handle;
6319 cp.out.handle = handle;
6321 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6322 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6323 "ERROR: Allowed close on secondary connection");
6325 talloc_free(p2);
6327 return true;
6330 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6331 struct dcerpc_binding_handle *b, const char *name)
6333 NTSTATUS status;
6334 struct spoolss_OpenPrinter op;
6335 struct spoolss_OpenPrinterEx opEx;
6336 struct policy_handle handle;
6337 bool ret = true;
6339 op.in.printername = name;
6340 op.in.datatype = NULL;
6341 op.in.devmode_ctr.devmode= NULL;
6342 op.in.access_mask = 0;
6343 op.out.handle = &handle;
6345 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6347 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6348 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6349 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6350 "unexpected result");
6352 if (W_ERROR_IS_OK(op.out.result)) {
6353 ret &=test_ClosePrinter(tctx, b, &handle);
6356 opEx.in.printername = name;
6357 opEx.in.datatype = NULL;
6358 opEx.in.devmode_ctr.devmode = NULL;
6359 opEx.in.access_mask = 0;
6360 opEx.in.userlevel_ctr.level = 1;
6361 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6362 opEx.out.handle = &handle;
6364 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6366 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6367 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6368 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAMETER,
6369 "unexpected result");
6371 if (W_ERROR_IS_OK(opEx.out.result)) {
6372 ret &=test_ClosePrinter(tctx, b, &handle);
6375 return ret;
6378 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6379 void *private_data)
6381 struct test_spoolss_context *ctx =
6382 talloc_get_type_abort(private_data, struct test_spoolss_context);
6384 const char *badnames[] = {
6385 "__INVALID_PRINTER__",
6386 "\\\\__INVALID_HOST__",
6388 "\\\\\\",
6389 "\\\\\\__INVALID_PRINTER__"
6391 const char *badname;
6392 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6393 const char *server_name = dcerpc_server_name(p);
6394 struct dcerpc_binding_handle *b = p->binding_handle;
6395 int i;
6397 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6398 torture_assert(tctx,
6399 test_OpenPrinter_badname(tctx, b, badnames[i]),
6400 "");
6403 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6404 torture_assert(tctx,
6405 test_OpenPrinter_badname(tctx, b, badname),
6406 "");
6408 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6409 torture_assert(tctx,
6410 test_OpenPrinter_badname(tctx, b, badname),
6411 "");
6413 return true;
6416 static bool test_OpenPrinter(struct torture_context *tctx,
6417 struct dcerpc_pipe *p,
6418 const char *name,
6419 const char *environment,
6420 bool open_only)
6422 NTSTATUS status;
6423 struct spoolss_OpenPrinter r;
6424 struct policy_handle handle;
6425 bool ret = true;
6426 struct dcerpc_binding_handle *b = p->binding_handle;
6428 r.in.printername = name;
6429 r.in.datatype = NULL;
6430 r.in.devmode_ctr.devmode= NULL;
6431 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6432 r.out.handle = &handle;
6434 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6436 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6438 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6440 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6442 if (open_only) {
6443 goto close_printer;
6446 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6447 ret = false;
6450 if (!torture_setting_bool(tctx, "samba3", false)) {
6451 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6452 ret = false;
6456 close_printer:
6457 if (!test_ClosePrinter(tctx, b, &handle)) {
6458 ret = false;
6461 return ret;
6464 static bool test_OpenPrinterEx(struct torture_context *tctx,
6465 struct dcerpc_binding_handle *b,
6466 const char *printername,
6467 const char *datatype,
6468 struct spoolss_DeviceMode *devmode,
6469 uint32_t access_mask,
6470 struct spoolss_UserLevelCtr *userlevel_ctr,
6471 struct policy_handle *handle,
6472 WERROR expected_result)
6474 struct spoolss_OpenPrinterEx r;
6476 r.in.printername = printername;
6477 r.in.datatype = datatype;
6478 r.in.devmode_ctr.devmode= devmode;
6479 r.in.access_mask = access_mask;
6480 r.in.userlevel_ctr = *userlevel_ctr;
6481 r.out.handle = handle;
6483 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6485 torture_assert_ntstatus_ok(tctx,
6486 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6487 "OpenPrinterEx failed");
6489 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6490 "OpenPrinterEx failed");
6492 return true;
6495 static bool call_OpenPrinterEx(struct torture_context *tctx,
6496 struct dcerpc_pipe *p,
6497 const char *name,
6498 struct spoolss_DeviceMode *devmode,
6499 struct policy_handle *handle)
6501 struct spoolss_UserLevelCtr userlevel_ctr;
6502 struct spoolss_UserLevel1 userlevel1;
6503 struct dcerpc_binding_handle *b = p->binding_handle;
6505 userlevel1.size = 1234;
6506 userlevel1.client = "hello";
6507 userlevel1.user = "spottyfoot!";
6508 userlevel1.build = 1;
6509 userlevel1.major = 2;
6510 userlevel1.minor = 3;
6511 userlevel1.processor = 4;
6513 userlevel_ctr.level = 1;
6514 userlevel_ctr.user_info.level1 = &userlevel1;
6516 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6517 SEC_FLAG_MAXIMUM_ALLOWED,
6518 &userlevel_ctr,
6519 handle,
6520 WERR_OK);
6523 static bool test_printer_rename(struct torture_context *tctx,
6524 void *private_data)
6526 struct torture_printer_context *t =
6527 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6528 struct dcerpc_pipe *p = t->spoolss_pipe;
6530 bool ret = true;
6531 union spoolss_PrinterInfo info;
6532 union spoolss_SetPrinterInfo sinfo;
6533 struct spoolss_SetPrinterInfoCtr info_ctr;
6534 struct spoolss_DevmodeContainer devmode_ctr;
6535 struct sec_desc_buf secdesc_ctr;
6536 const char *printer_name;
6537 const char *printer_name_orig;
6538 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6539 struct policy_handle new_handle;
6540 const char *q;
6541 struct dcerpc_binding_handle *b = p->binding_handle;
6543 ZERO_STRUCT(devmode_ctr);
6544 ZERO_STRUCT(secdesc_ctr);
6546 torture_comment(tctx, "Testing Printer rename operations\n");
6548 torture_assert(tctx,
6549 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6550 "failed to call GetPrinter level 2");
6552 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6554 q = strrchr(info.info2.printername, '\\');
6555 if (q) {
6556 torture_warning(tctx,
6557 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6560 torture_assert(tctx,
6561 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6563 sinfo.info2->printername = printer_name_new;
6565 info_ctr.level = 2;
6566 info_ctr.info = sinfo;
6568 torture_assert(tctx,
6569 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6570 "failed to call SetPrinter level 2");
6572 torture_assert(tctx,
6573 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6574 "failed to call GetPrinter level 2");
6576 printer_name = talloc_strdup(tctx, info.info2.printername);
6578 q = strrchr(info.info2.printername, '\\');
6579 if (q) {
6580 torture_warning(tctx,
6581 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6582 q++;
6583 printer_name = q;
6586 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6587 "new printer name was not set");
6589 /* samba currently cannot fully rename printers */
6590 if (!torture_setting_bool(tctx, "samba3", false)) {
6591 torture_assert(tctx,
6592 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6593 "still can open printer with oldname after rename");
6594 } else {
6595 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6598 torture_assert(tctx,
6599 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6600 "failed to open printer with new name");
6602 torture_assert(tctx,
6603 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6604 "failed to call GetPrinter level 2");
6606 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6607 "new printer name was not set");
6609 torture_assert(tctx,
6610 test_ClosePrinter(tctx, b, &new_handle),
6611 "failed to close printer");
6613 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6615 return ret;
6618 static bool test_openprinter(struct torture_context *tctx,
6619 struct dcerpc_binding_handle *b,
6620 const char *real_printername)
6622 struct spoolss_UserLevelCtr userlevel_ctr;
6623 struct policy_handle handle;
6624 struct spoolss_UserLevel1 userlevel1;
6625 const char *printername = NULL;
6626 int i;
6628 struct {
6629 const char *suffix;
6630 WERROR expected_result;
6631 } tests[] = {
6633 .suffix = "rubbish",
6634 .expected_result = WERR_INVALID_PRINTER_NAME
6636 .suffix = ", LocalOnl",
6637 .expected_result = WERR_INVALID_PRINTER_NAME
6639 .suffix = ", localOnly",
6640 .expected_result = WERR_INVALID_PRINTER_NAME
6642 .suffix = ", localonl",
6643 .expected_result = WERR_INVALID_PRINTER_NAME
6645 .suffix = ",LocalOnl",
6646 .expected_result = WERR_INVALID_PRINTER_NAME
6648 .suffix = ",localOnl2",
6649 .expected_result = WERR_INVALID_PRINTER_NAME
6651 .suffix = ", DrvConver2t",
6652 .expected_result = WERR_INVALID_PRINTER_NAME
6654 .suffix = ", drvconvert",
6655 .expected_result = WERR_INVALID_PRINTER_NAME
6657 .suffix = ",drvconvert",
6658 .expected_result = WERR_INVALID_PRINTER_NAME
6660 .suffix = ", DrvConvert",
6661 .expected_result = WERR_OK
6663 .suffix = " , DrvConvert",
6664 .expected_result = WERR_INVALID_PRINTER_NAME
6666 .suffix = ",DrvConvert",
6667 .expected_result = WERR_OK
6669 .suffix = ", DrvConvertsadfasdf",
6670 .expected_result = WERR_OK
6672 .suffix = ",DrvConvertasdfasd",
6673 .expected_result = WERR_OK
6675 .suffix = ", LocalOnly",
6676 .expected_result = WERR_OK
6678 .suffix = " , LocalOnly",
6679 .expected_result = WERR_INVALID_PRINTER_NAME
6681 .suffix = ",LocalOnly",
6682 .expected_result = WERR_OK
6684 .suffix = ", LocalOnlysagi4gjfkd",
6685 .expected_result = WERR_OK
6687 .suffix = ",LocalOnlysagi4gjfkd",
6688 .expected_result = WERR_OK
6692 userlevel1.size = 1234;
6693 userlevel1.client = "hello";
6694 userlevel1.user = "spottyfoot!";
6695 userlevel1.build = 1;
6696 userlevel1.major = 2;
6697 userlevel1.minor = 3;
6698 userlevel1.processor = 4;
6700 userlevel_ctr.level = 1;
6701 userlevel_ctr.user_info.level1 = &userlevel1;
6703 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6705 torture_assert(tctx,
6706 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6707 &userlevel_ctr, &handle,
6708 WERR_OK),
6709 "OpenPrinterEx failed");
6710 test_ClosePrinter(tctx, b, &handle);
6712 for (i=0; i < ARRAY_SIZE(tests); i++) {
6714 printername = talloc_asprintf(tctx, "%s%s",
6715 real_printername,
6716 tests[i].suffix);
6718 torture_assert(tctx,
6719 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6720 &userlevel_ctr, &handle,
6721 tests[i].expected_result),
6722 "OpenPrinterEx failed");
6723 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6724 test_ClosePrinter(tctx, b, &handle);
6728 return true;
6732 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6733 struct dcerpc_pipe *p,
6734 const char *name,
6735 const char *environment)
6737 struct policy_handle handle;
6738 bool ret = true;
6739 struct dcerpc_binding_handle *b = p->binding_handle;
6741 if (!test_openprinter(tctx, b, name)) {
6742 return false;
6745 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6746 return false;
6749 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6750 ret = false;
6753 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6754 ret = false;
6757 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6758 ret = false;
6761 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6762 ret = false;
6765 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6766 ret = false;
6769 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6770 ret = false;
6773 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6774 ret = false;
6777 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6778 ret = false;
6781 if (!test_printer_all_keys(tctx, b, &handle)) {
6782 ret = false;
6785 if (!test_PausePrinter(tctx, b, &handle)) {
6786 ret = false;
6789 if (!test_DoPrintTest(tctx, b, &handle)) {
6790 ret = false;
6793 if (!test_ResumePrinter(tctx, b, &handle)) {
6794 ret = false;
6797 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6798 ret = false;
6801 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6802 ret = false;
6805 if (!torture_setting_bool(tctx, "samba3", false)) {
6806 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6807 ret = false;
6811 if (!test_ClosePrinter(tctx, b, &handle)) {
6812 ret = false;
6815 return ret;
6818 static bool test_EnumPrinters_old(struct torture_context *tctx,
6819 void *private_data)
6821 struct test_spoolss_context *ctx =
6822 talloc_get_type_abort(private_data, struct test_spoolss_context);
6823 struct spoolss_EnumPrinters r;
6824 NTSTATUS status;
6825 uint16_t levels[] = {1, 2, 4, 5};
6826 int i;
6827 bool ret = true;
6828 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6829 struct dcerpc_binding_handle *b = p->binding_handle;
6831 for (i=0;i<ARRAY_SIZE(levels);i++) {
6832 union spoolss_PrinterInfo *info;
6833 int j;
6834 uint32_t needed;
6835 uint32_t count;
6837 r.in.flags = PRINTER_ENUM_LOCAL;
6838 r.in.server = "";
6839 r.in.level = levels[i];
6840 r.in.buffer = NULL;
6841 r.in.offered = 0;
6842 r.out.needed = &needed;
6843 r.out.count = &count;
6844 r.out.info = &info;
6846 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6848 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6849 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6851 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6852 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6853 r.in.buffer = &blob;
6854 r.in.offered = needed;
6855 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6858 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6860 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6862 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6864 if (!info) {
6865 torture_comment(tctx, "No printers returned\n");
6866 return true;
6869 for (j=0;j<count;j++) {
6870 if (r.in.level == 1) {
6871 char *unc = talloc_strdup(tctx, info[j].info1.name);
6872 char *slash, *name, *full_name;
6873 name = unc;
6874 if (unc[0] == '\\' && unc[1] == '\\') {
6875 unc +=2;
6877 slash = strchr(unc, '\\');
6878 if (slash) {
6879 slash++;
6880 name = slash;
6882 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6883 dcerpc_server_name(p), name);
6884 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6885 ret = false;
6887 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6888 ret = false;
6890 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6891 ret = false;
6893 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6894 ret = false;
6900 return ret;
6903 static bool test_EnumPrinters_level(struct torture_context *tctx,
6904 struct dcerpc_binding_handle *b,
6905 uint32_t flags,
6906 const char *servername,
6907 uint32_t level,
6908 uint32_t *count_p,
6909 union spoolss_PrinterInfo **info_p)
6911 struct spoolss_EnumPrinters r;
6912 union spoolss_PrinterInfo *info;
6913 uint32_t needed;
6914 uint32_t count;
6916 r.in.flags = flags;
6917 r.in.server = servername;
6918 r.in.level = level;
6919 r.in.buffer = NULL;
6920 r.in.offered = 0;
6921 r.out.needed = &needed;
6922 r.out.count = &count;
6923 r.out.info = &info;
6925 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6926 r.in.server, r.in.level);
6928 torture_assert_ntstatus_ok(tctx,
6929 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6930 "EnumPrinters failed");
6931 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6932 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6933 r.in.buffer = &blob;
6934 r.in.offered = needed;
6935 torture_assert_ntstatus_ok(tctx,
6936 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6937 "EnumPrinters failed");
6940 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6942 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6944 if (count_p) {
6945 *count_p = count;
6947 if (info_p) {
6948 *info_p = info;
6951 return true;
6954 static const char *get_short_printername(struct torture_context *tctx,
6955 const char *name)
6957 const char *short_name;
6959 if (name[0] == '\\' && name[1] == '\\') {
6960 name += 2;
6961 short_name = strchr(name, '\\');
6962 if (short_name) {
6963 return talloc_strdup(tctx, short_name+1);
6967 return name;
6970 static const char *get_full_printername(struct torture_context *tctx,
6971 const char *name)
6973 const char *full_name = talloc_strdup(tctx, name);
6974 char *p;
6976 if (name && name[0] == '\\' && name[1] == '\\') {
6977 name += 2;
6978 p = strchr(name, '\\');
6979 if (p) {
6980 return full_name;
6984 return NULL;
6987 static bool test_OnePrinter_servername(struct torture_context *tctx,
6988 struct dcerpc_pipe *p,
6989 struct dcerpc_binding_handle *b,
6990 const char *servername,
6991 const char *printername)
6993 union spoolss_PrinterInfo info;
6994 const char *short_name = get_short_printername(tctx, printername);
6995 const char *full_name = get_full_printername(tctx, printername);
6997 if (short_name) {
6998 struct policy_handle handle;
6999 torture_assert(tctx,
7000 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
7001 "failed to open printer");
7003 torture_assert(tctx,
7004 test_GetPrinter_level(tctx, b, &handle, 2, &info),
7005 "failed to get printer info");
7007 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
7008 "unexpected servername");
7009 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
7010 "unexpected printername");
7012 if (info.info2.devmode) {
7013 const char *expected_devicename;
7014 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
7015 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
7016 "unexpected devicemode devicename");
7019 torture_assert(tctx,
7020 test_ClosePrinter(tctx, b, &handle),
7021 "failed to close printer");
7024 if (full_name) {
7025 struct policy_handle handle;
7027 torture_assert(tctx,
7028 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
7029 "failed to open printer");
7031 torture_assert(tctx,
7032 test_GetPrinter_level(tctx, b, &handle, 2, &info),
7033 "failed to get printer info");
7035 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
7036 "unexpected servername");
7037 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
7038 "unexpected printername");
7040 if (info.info2.devmode) {
7041 const char *expected_devicename;
7042 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
7043 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
7044 "unexpected devicemode devicename");
7047 torture_assert(tctx,
7048 test_ClosePrinter(tctx, b, &handle),
7049 "failed to close printer");
7052 return true;
7055 static bool test_EnumPrinters_servername(struct torture_context *tctx,
7056 void *private_data)
7058 struct test_spoolss_context *ctx =
7059 talloc_get_type_abort(private_data, struct test_spoolss_context);
7060 int i;
7061 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7062 struct dcerpc_binding_handle *b = p->binding_handle;
7063 uint32_t count;
7064 union spoolss_PrinterInfo *info;
7065 const char *servername;
7066 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
7068 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
7070 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7072 torture_assert(tctx,
7073 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
7074 "failed to enumerate printers");
7076 for (i=0; i < count; i++) {
7078 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
7079 "unexpected servername");
7081 torture_assert(tctx,
7082 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7083 "failed to check printer");
7086 servername = "";
7088 torture_assert(tctx,
7089 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
7090 "failed to enumerate printers");
7092 for (i=0; i < count; i++) {
7094 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
7095 "unexpected servername");
7097 torture_assert(tctx,
7098 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7099 "failed to check printer");
7103 return true;
7106 #if 0
7107 static bool test_GetPrinterDriver(struct torture_context *tctx,
7108 struct dcerpc_binding_handle *b,
7109 struct policy_handle *handle,
7110 const char *driver_name)
7112 struct spoolss_GetPrinterDriver r;
7113 uint32_t needed;
7115 r.in.handle = handle;
7116 r.in.architecture = "W32X86";
7117 r.in.level = 1;
7118 r.in.buffer = NULL;
7119 r.in.offered = 0;
7120 r.out.needed = &needed;
7122 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
7124 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7125 "failed to call GetPrinterDriver");
7126 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7127 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7128 r.in.buffer = &blob;
7129 r.in.offered = needed;
7130 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7131 "failed to call GetPrinterDriver");
7134 torture_assert_werr_ok(tctx, r.out.result,
7135 "failed to call GetPrinterDriver");
7137 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7139 return true;
7141 #endif
7143 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
7144 struct dcerpc_binding_handle *b,
7145 struct policy_handle *handle,
7146 const char *driver_name,
7147 const char *architecture,
7148 uint32_t level,
7149 uint32_t client_major_version,
7150 uint32_t client_minor_version,
7151 union spoolss_DriverInfo *info_p,
7152 WERROR *result_p)
7155 struct spoolss_GetPrinterDriver2 r;
7156 uint32_t needed;
7157 uint32_t server_major_version;
7158 uint32_t server_minor_version;
7160 r.in.handle = handle;
7161 r.in.architecture = architecture;
7162 r.in.client_major_version = client_major_version;
7163 r.in.client_minor_version = client_minor_version;
7164 r.in.buffer = NULL;
7165 r.in.offered = 0;
7166 r.in.level = level;
7167 r.out.needed = &needed;
7168 r.out.server_major_version = &server_major_version;
7169 r.out.server_minor_version = &server_minor_version;
7171 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
7172 driver_name, r.in.level);
7174 torture_assert_ntstatus_ok(tctx,
7175 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7176 "failed to call GetPrinterDriver2");
7177 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7178 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7179 r.in.buffer = &blob;
7180 r.in.offered = needed;
7181 torture_assert_ntstatus_ok(tctx,
7182 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7183 "failed to call GetPrinterDriver2");
7186 if (result_p) {
7187 *result_p = r.out.result;
7190 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
7191 switch (r.in.level) {
7192 case 101:
7193 case 8:
7194 torture_comment(tctx,
7195 "level %d not implemented, not considering as an error\n",
7196 r.in.level);
7197 return true;
7198 default:
7199 break;
7203 torture_assert_werr_ok(tctx, r.out.result,
7204 "failed to call GetPrinterDriver2");
7206 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7208 if (info_p) {
7209 *info_p = *r.out.info;
7212 return true;
7215 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7216 struct dcerpc_binding_handle *b,
7217 struct policy_handle *handle,
7218 const char *driver_name,
7219 const char *architecture)
7221 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7222 int i;
7225 for (i=0;i<ARRAY_SIZE(levels);i++) {
7227 torture_assert(tctx,
7228 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7229 "");
7232 return true;
7235 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7236 void *private_data)
7238 struct test_spoolss_context *ctx =
7239 talloc_get_type_abort(private_data, struct test_spoolss_context);
7240 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7241 int i;
7242 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7243 struct dcerpc_binding_handle *b = p->binding_handle;
7244 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7246 for (i=0;i<ARRAY_SIZE(levels);i++) {
7248 uint32_t count;
7249 union spoolss_DriverInfo *info;
7251 torture_assert(tctx,
7252 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7253 "failed to enumerate drivers");
7255 if (!info) {
7256 torture_comment(tctx, "No printer drivers returned\n");
7257 break;
7261 return true;
7264 static bool test_DeletePrinter(struct torture_context *tctx,
7265 struct dcerpc_binding_handle *b,
7266 struct policy_handle *handle)
7268 struct spoolss_DeletePrinter r;
7270 torture_comment(tctx, "Testing DeletePrinter\n");
7272 r.in.handle = handle;
7274 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7275 "failed to delete printer");
7276 torture_assert_werr_ok(tctx, r.out.result,
7277 "failed to delete printer");
7279 return true;
7282 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7283 struct dcerpc_binding_handle *b,
7284 uint32_t flags,
7285 uint32_t level,
7286 const char *name,
7287 bool *found)
7289 struct spoolss_EnumPrinters e;
7290 uint32_t count;
7291 union spoolss_PrinterInfo *info;
7292 uint32_t needed;
7293 int i;
7295 *found = false;
7297 e.in.flags = flags;
7298 e.in.server = NULL;
7299 e.in.level = level;
7300 e.in.buffer = NULL;
7301 e.in.offered = 0;
7302 e.out.count = &count;
7303 e.out.info = &info;
7304 e.out.needed = &needed;
7306 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7307 "failed to enum printers");
7309 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7310 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7311 e.in.buffer = &blob;
7312 e.in.offered = needed;
7314 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7315 "failed to enum printers");
7318 torture_assert_werr_ok(tctx, e.out.result,
7319 "failed to enum printers");
7321 for (i=0; i < count; i++) {
7323 const char *current = NULL;
7324 const char *q;
7326 switch (level) {
7327 case 1:
7328 current = info[i].info1.name;
7329 break;
7332 if (strequal(current, name)) {
7333 *found = true;
7334 break;
7337 q = strrchr(current, '\\');
7338 if (q) {
7339 if (!e.in.server) {
7340 torture_warning(tctx,
7341 "server returns printername %s incl. servername although we did not set servername", current);
7343 q++;
7344 if (strequal(q, name)) {
7345 *found = true;
7346 break;
7351 return true;
7354 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7355 struct dcerpc_pipe *p,
7356 const char *printername,
7357 bool ex)
7359 WERROR result;
7360 struct spoolss_AddPrinter r;
7361 struct spoolss_AddPrinterEx rex;
7362 struct spoolss_SetPrinterInfoCtr info_ctr;
7363 struct spoolss_SetPrinterInfo1 info1;
7364 struct spoolss_DevmodeContainer devmode_ctr;
7365 struct sec_desc_buf secdesc_ctr;
7366 struct spoolss_UserLevelCtr userlevel_ctr;
7367 struct policy_handle handle;
7368 bool found = false;
7369 struct dcerpc_binding_handle *b = p->binding_handle;
7371 ZERO_STRUCT(devmode_ctr);
7372 ZERO_STRUCT(secdesc_ctr);
7373 ZERO_STRUCT(userlevel_ctr);
7374 ZERO_STRUCT(info1);
7376 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7377 ex ? "Ex":"", printername);
7379 /* try to add printer to wellknown printer list (level 1) */
7381 userlevel_ctr.level = 1;
7383 info_ctr.info.info1 = &info1;
7384 info_ctr.level = 1;
7386 rex.in.server = NULL;
7387 rex.in.info_ctr = &info_ctr;
7388 rex.in.devmode_ctr = &devmode_ctr;
7389 rex.in.secdesc_ctr = &secdesc_ctr;
7390 rex.in.userlevel_ctr = &userlevel_ctr;
7391 rex.out.handle = &handle;
7393 r.in.server = NULL;
7394 r.in.info_ctr = &info_ctr;
7395 r.in.devmode_ctr = &devmode_ctr;
7396 r.in.secdesc_ctr = &secdesc_ctr;
7397 r.out.handle = &handle;
7399 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7400 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7401 "failed to add printer");
7402 result = ex ? rex.out.result : r.out.result;
7403 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7404 "unexpected result code");
7406 info1.name = printername;
7407 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7409 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7410 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7411 "failed to add printer");
7412 result = ex ? rex.out.result : r.out.result;
7413 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7414 "unexpected result code");
7416 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7417 better do a real check to see the printer is really there */
7419 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7420 PRINTER_ENUM_NETWORK, 1,
7421 printername,
7422 &found),
7423 "failed to enum printers");
7425 torture_assert(tctx, found, "failed to find newly added printer");
7427 info1.flags = 0;
7429 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7430 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7431 "failed to add printer");
7432 result = ex ? rex.out.result : r.out.result;
7433 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7434 "unexpected result code");
7436 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7437 better do a real check to see the printer has really been removed
7438 from the well known printer list */
7440 found = false;
7442 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7443 PRINTER_ENUM_NETWORK, 1,
7444 printername,
7445 &found),
7446 "failed to enum printers");
7447 #if 0
7448 torture_assert(tctx, !found, "printer still in well known printer list");
7449 #endif
7450 return true;
7453 static bool test_AddPrinter_normal(struct torture_context *tctx,
7454 struct dcerpc_pipe *p,
7455 struct policy_handle *handle_p,
7456 const char *printername,
7457 const char *drivername,
7458 const char *portname,
7459 struct spoolss_DeviceMode *devmode,
7460 bool ex)
7462 WERROR result;
7463 struct spoolss_AddPrinter r;
7464 struct spoolss_AddPrinterEx rex;
7465 struct spoolss_SetPrinterInfoCtr info_ctr;
7466 struct spoolss_SetPrinterInfo2 info2;
7467 struct spoolss_DevmodeContainer devmode_ctr;
7468 struct sec_desc_buf secdesc_ctr;
7469 struct spoolss_UserLevelCtr userlevel_ctr;
7470 struct policy_handle handle;
7471 bool found = false;
7472 bool existing_printer_deleted = false;
7473 struct dcerpc_binding_handle *b = p->binding_handle;
7475 ZERO_STRUCT(devmode_ctr);
7476 ZERO_STRUCT(secdesc_ctr);
7477 ZERO_STRUCT(userlevel_ctr);
7479 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7480 ex ? "Ex":"", printername);
7482 devmode_ctr.devmode = devmode;
7484 userlevel_ctr.level = 1;
7486 rex.in.server = NULL;
7487 rex.in.info_ctr = &info_ctr;
7488 rex.in.devmode_ctr = &devmode_ctr;
7489 rex.in.secdesc_ctr = &secdesc_ctr;
7490 rex.in.userlevel_ctr = &userlevel_ctr;
7491 rex.out.handle = &handle;
7493 r.in.server = NULL;
7494 r.in.info_ctr = &info_ctr;
7495 r.in.devmode_ctr = &devmode_ctr;
7496 r.in.secdesc_ctr = &secdesc_ctr;
7497 r.out.handle = &handle;
7499 again:
7501 /* try to add printer to printer list (level 2) */
7503 ZERO_STRUCT(info2);
7505 info_ctr.info.info2 = &info2;
7506 info_ctr.level = 2;
7508 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7509 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7510 "failed to add printer");
7511 result = ex ? rex.out.result : r.out.result;
7512 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7513 "unexpected result code");
7515 info2.printername = printername;
7517 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7518 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7519 "failed to add printer");
7520 result = ex ? rex.out.result : r.out.result;
7522 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7523 struct policy_handle printer_handle;
7525 if (existing_printer_deleted) {
7526 torture_fail(tctx, "already deleted printer still existing?");
7529 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7530 "failed to open printer handle");
7532 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7533 "failed to delete printer");
7535 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7536 "failed to close server handle");
7538 existing_printer_deleted = true;
7540 goto again;
7543 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7544 "unexpected result code");
7546 info2.portname = portname;
7548 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7549 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7550 "failed to add printer");
7551 result = ex ? rex.out.result : r.out.result;
7552 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7553 "unexpected result code");
7555 info2.drivername = drivername;
7557 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7558 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7559 "failed to add printer");
7560 result = ex ? rex.out.result : r.out.result;
7562 /* w2k8r2 allows one to add printer w/o defining printprocessor */
7564 if (!W_ERROR_IS_OK(result)) {
7565 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7566 "unexpected result code");
7568 info2.printprocessor = "winprint";
7570 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7571 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7572 "failed to add printer");
7573 result = ex ? rex.out.result : r.out.result;
7574 torture_assert_werr_ok(tctx, result,
7575 "failed to add printer");
7578 *handle_p = handle;
7580 /* we are paranoid, really check if the printer is there now */
7582 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7583 PRINTER_ENUM_LOCAL, 1,
7584 printername,
7585 &found),
7586 "failed to enum printers");
7587 torture_assert(tctx, found, "failed to find newly added printer");
7589 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7590 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7591 "failed to add printer");
7592 result = ex ? rex.out.result : r.out.result;
7593 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7594 "unexpected result code");
7596 return true;
7599 static bool test_printer_info(struct torture_context *tctx,
7600 void *private_data)
7602 struct torture_printer_context *t =
7603 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7604 struct dcerpc_pipe *p = t->spoolss_pipe;
7605 struct dcerpc_binding_handle *b = p->binding_handle;
7607 bool ret = true;
7609 if (torture_setting_bool(tctx, "samba3", false)) {
7610 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7613 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7614 ret = false;
7617 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7618 ret = false;
7621 return ret;
7624 static bool test_EnumPrinterKey(struct torture_context *tctx,
7625 struct dcerpc_binding_handle *b,
7626 struct policy_handle *handle,
7627 const char *key_name,
7628 const char ***array)
7630 struct spoolss_EnumPrinterKey r;
7631 uint32_t needed = 0;
7632 union spoolss_KeyNames key_buffer;
7633 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7634 uint32_t _ndr_size;
7635 int i;
7637 r.in.handle = handle;
7638 r.in.key_name = key_name;
7639 r.out.key_buffer = &key_buffer;
7640 r.out.needed = &needed;
7641 r.out._ndr_size = &_ndr_size;
7643 for (i=0; i < ARRAY_SIZE(offered); i++) {
7645 if (offered[i] < 0 && needed) {
7646 if (needed <= 4) {
7647 continue;
7649 r.in.offered = needed + offered[i];
7650 } else {
7651 r.in.offered = offered[i];
7654 ZERO_STRUCT(key_buffer);
7656 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7658 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7659 "failed to call EnumPrinterKey");
7660 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7662 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7663 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7664 _ndr_size, r.in.offered/2));
7666 r.in.offered = needed;
7667 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7668 "failed to call EnumPrinterKey");
7671 if (offered[i] > 0) {
7672 torture_assert_werr_ok(tctx, r.out.result,
7673 "failed to call EnumPrinterKey");
7676 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7677 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7678 _ndr_size, r.in.offered/2));
7680 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7681 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7683 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7684 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7686 if (key_buffer.string_array) {
7687 uint32_t calc_needed = 0;
7688 int s;
7689 for (s=0; key_buffer.string_array[s]; s++) {
7690 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7692 if (!key_buffer.string_array[0]) {
7693 calc_needed += 2;
7695 calc_needed += 2;
7697 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7698 "EnumPrinterKey unexpected size");
7702 if (array) {
7703 *array = key_buffer.string_array;
7706 return true;
7709 bool test_printer_all_keys(struct torture_context *tctx,
7710 struct dcerpc_binding_handle *b,
7711 struct policy_handle *handle)
7713 const char **key_array = NULL;
7714 int i;
7716 torture_comment(tctx, "Testing Printer Keys\n");
7718 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7719 "failed to call test_EnumPrinterKey");
7721 for (i=0; key_array && key_array[i]; i++) {
7722 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7723 "failed to call test_EnumPrinterKey");
7725 for (i=0; key_array && key_array[i]; i++) {
7726 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7727 "failed to call test_EnumPrinterDataEx");
7730 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7732 return true;
7735 static bool test_openprinter_wrap(struct torture_context *tctx,
7736 void *private_data)
7738 struct torture_printer_context *t =
7739 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7740 struct dcerpc_pipe *p = t->spoolss_pipe;
7741 struct dcerpc_binding_handle *b = p->binding_handle;
7742 const char *printername = t->info2.printername;
7744 return test_openprinter(tctx, b, printername);
7747 static bool test_csetprinter(struct torture_context *tctx,
7748 void *private_data)
7750 struct torture_printer_context *t =
7751 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7752 struct dcerpc_pipe *p = t->spoolss_pipe;
7754 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7755 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7756 const char *portname = t->info2.portname;
7758 union spoolss_PrinterInfo info;
7759 struct policy_handle new_handle, new_handle2;
7760 struct dcerpc_binding_handle *b = p->binding_handle;
7762 torture_comment(tctx, "Testing c_setprinter\n");
7764 torture_assert(tctx,
7765 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7766 "failed to get level 0 printer info");
7767 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7768 info.info0.c_setprinter);
7770 /* check if c_setprinter on 1st handle increases after a printer has
7771 * been added */
7773 torture_assert(tctx,
7774 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7775 "failed to add new printer");
7776 torture_assert(tctx,
7777 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7778 "failed to get level 0 printer info");
7779 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7780 info.info0.c_setprinter);
7782 /* check if c_setprinter on new handle increases after a printer has
7783 * been added */
7785 torture_assert(tctx,
7786 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7787 "failed to get level 0 printer info");
7788 torture_comment(tctx, "csetprinter on created handle: %d\n",
7789 info.info0.c_setprinter);
7791 /* open the new printer and check if c_setprinter increases */
7793 torture_assert(tctx,
7794 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7795 "failed to open created printer");
7796 torture_assert(tctx,
7797 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7798 "failed to get level 0 printer info");
7799 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7800 info.info0.c_setprinter);
7802 /* cleanup */
7804 torture_assert(tctx,
7805 test_ClosePrinter(tctx, b, &new_handle2),
7806 "failed to close printer");
7807 torture_assert(tctx,
7808 test_DeletePrinter(tctx, b, &new_handle),
7809 "failed to delete new printer");
7811 return true;
7814 static bool compose_local_driver_directory(struct torture_context *tctx,
7815 const char *environment,
7816 const char *local_dir,
7817 const char **path)
7819 char *p;
7821 p = strrchr(local_dir, '/');
7822 if (!p) {
7823 return NULL;
7825 p++;
7827 if (strequal(environment, SPOOLSS_ARCHITECTURE_x64)) {
7828 if (!strequal(p, "x64")) {
7829 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7831 } else if (strequal(environment, SPOOLSS_ARCHITECTURE_NT_X86)) {
7832 if (!strequal(p, "i386")) {
7833 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7835 } else {
7836 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7839 return true;
7842 #if 0
7843 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7844 const char *devicename)
7846 struct spoolss_DeviceMode *r;
7848 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7849 if (r == NULL) {
7850 return NULL;
7853 r->devicename = talloc_strdup(r, devicename);
7854 r->specversion = DMSPEC_NT4_AND_ABOVE;
7855 r->driverversion = 0x0600;
7856 r->size = 0x00dc;
7857 r->__driverextra_length = 0;
7858 r->fields = DEVMODE_FORMNAME |
7859 DEVMODE_TTOPTION |
7860 DEVMODE_PRINTQUALITY |
7861 DEVMODE_DEFAULTSOURCE |
7862 DEVMODE_COPIES |
7863 DEVMODE_SCALE |
7864 DEVMODE_PAPERSIZE |
7865 DEVMODE_ORIENTATION;
7866 r->orientation = DMORIENT_PORTRAIT;
7867 r->papersize = DMPAPER_LETTER;
7868 r->paperlength = 0;
7869 r->paperwidth = 0;
7870 r->scale = 100;
7871 r->copies = 55;
7872 r->defaultsource = DMBIN_FORMSOURCE;
7873 r->printquality = DMRES_HIGH;
7874 r->color = DMRES_MONOCHROME;
7875 r->duplex = DMDUP_SIMPLEX;
7876 r->yresolution = 0;
7877 r->ttoption = DMTT_SUBDEV;
7878 r->collate = DMCOLLATE_FALSE;
7879 r->formname = talloc_strdup(r, "Letter");
7881 return r;
7883 #endif
7885 static bool test_architecture_buffer(struct torture_context *tctx,
7886 void *private_data)
7888 struct test_spoolss_context *ctx =
7889 talloc_get_type_abort(private_data, struct test_spoolss_context);
7891 struct spoolss_OpenPrinterEx r;
7892 struct spoolss_UserLevel1 u1;
7893 struct policy_handle handle;
7894 uint32_t architectures[] = {
7895 PROCESSOR_ARCHITECTURE_INTEL,
7896 PROCESSOR_ARCHITECTURE_IA64,
7897 PROCESSOR_ARCHITECTURE_AMD64
7899 uint32_t needed[3];
7900 int i;
7901 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7902 struct dcerpc_binding_handle *b = p->binding_handle;
7904 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7906 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7908 u1.size = 0;
7909 u1.client = NULL;
7910 u1.user = NULL;
7911 u1.build = 0;
7912 u1.major = 3;
7913 u1.minor = 0;
7914 u1.processor = architectures[i];
7916 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7917 r.in.datatype = NULL;
7918 r.in.devmode_ctr.devmode= NULL;
7919 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7920 r.in.userlevel_ctr.level = 1;
7921 r.in.userlevel_ctr.user_info.level1 = &u1;
7922 r.out.handle = &handle;
7924 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7925 torture_assert_werr_ok(tctx, r.out.result, "");
7928 struct spoolss_EnumPrinters e;
7929 uint32_t count;
7930 union spoolss_PrinterInfo *info;
7932 e.in.flags = PRINTER_ENUM_LOCAL;
7933 e.in.server = NULL;
7934 e.in.level = 2;
7935 e.in.buffer = NULL;
7936 e.in.offered = 0;
7937 e.out.count = &count;
7938 e.out.info = &info;
7939 e.out.needed = &needed[i];
7941 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7942 #if 0
7943 torture_comment(tctx, "needed was %d\n", needed[i]);
7944 #endif
7947 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7950 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7951 if (needed[i-1] != needed[i]) {
7952 torture_fail(tctx,
7953 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7954 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7958 return true;
7961 static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
7962 struct dcerpc_pipe *p,
7963 const char *architecture,
7964 const char *guid_str,
7965 const char **package_id)
7967 struct spoolss_GetCorePrinterDrivers r;
7968 struct spoolss_CorePrinterDriver core_printer_drivers;
7969 DATA_BLOB blob;
7970 const char **s;
7971 struct dcerpc_binding_handle *b = p->binding_handle;
7972 struct GUID guid;
7974 s = talloc_zero_array(tctx, const char *, 2);
7976 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7977 r.in.architecture = "foobar";
7978 r.in.core_driver_size = 0;
7979 r.in.core_driver_dependencies = "";
7980 r.in.core_printer_driver_count = 0;
7981 r.out.core_printer_drivers = &core_printer_drivers;
7983 torture_assert_ntstatus_ok(tctx,
7984 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
7985 "spoolss_GetCorePrinterDrivers failed");
7986 torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
7987 "spoolss_GetCorePrinterDrivers failed");
7989 guid = GUID_random();
7990 s[0] = GUID_string2(tctx, &guid);
7992 torture_assert(tctx,
7993 push_reg_multi_sz(tctx, &blob, s),
7994 "push_reg_multi_sz failed");
7996 r.in.core_driver_size = blob.length;
7997 r.in.core_driver_dependencies = s[0];
7998 r.in.core_printer_driver_count = 1;
7999 r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
8001 torture_assert_ntstatus_ok(tctx,
8002 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8003 "spoolss_GetCorePrinterDrivers failed");
8004 torture_assert_werr_equal(tctx,
8005 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
8006 "spoolss_GetCorePrinterDrivers failed");
8008 r.in.architecture = architecture;
8010 torture_assert_ntstatus_ok(tctx,
8011 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8012 "spoolss_GetCorePrinterDrivers failed");
8013 torture_assert_werr_equal(tctx,
8014 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
8015 "spoolss_GetCorePrinterDrivers failed");
8017 s[0] = talloc_strdup(s, guid_str);
8019 torture_assert(tctx,
8020 push_reg_multi_sz(tctx, &blob, s),
8021 "push_reg_multi_sz failed");
8023 r.in.core_driver_size = blob.length;
8024 r.in.core_driver_dependencies = s[0];
8025 r.in.core_printer_driver_count = 1;
8026 r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
8028 torture_assert_ntstatus_ok(tctx,
8029 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8030 "spoolss_GetCorePrinterDrivers failed");
8031 torture_assert_hresult_ok(tctx, r.out.result,
8032 "spoolss_GetCorePrinterDrivers failed");
8034 if (package_id) {
8035 *package_id = r.out.core_printer_drivers[0].szPackageID;
8038 return true;
8041 static bool test_get_core_printer_drivers(struct torture_context *tctx,
8042 void *private_data)
8044 struct test_spoolss_context *ctx =
8045 talloc_get_type_abort(private_data, struct test_spoolss_context);
8047 const char *architectures[] = {
8048 SPOOLSS_ARCHITECTURE_NT_X86,
8049 SPOOLSS_ARCHITECTURE_x64
8051 int i;
8052 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8054 for (i=0; i < ARRAY_SIZE(architectures); i++) {
8056 torture_comment(tctx, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
8057 architectures[i],
8058 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
8060 torture_assert(tctx,
8061 test_get_core_printer_drivers_arch_guid(tctx, p,
8062 architectures[i],
8063 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
8064 NULL),
8065 "");
8068 return true;
8071 static bool test_get_printer_driver_package_path(struct torture_context *tctx,
8072 void *private_data)
8074 struct test_spoolss_context *ctx =
8075 talloc_get_type_abort(private_data, struct test_spoolss_context);
8077 const char *architectures[] = {
8078 SPOOLSS_ARCHITECTURE_NT_X86,
8079 SPOOLSS_ARCHITECTURE_x64
8081 int i;
8082 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8083 struct dcerpc_binding_handle *b = p->binding_handle;
8085 for (i=0; i < ARRAY_SIZE(architectures); i++) {
8086 struct spoolss_GetPrinterDriverPackagePath r;
8087 uint32_t required = 0;
8088 const char *package_id = NULL;
8090 test_get_core_printer_drivers_arch_guid(tctx, p,
8091 architectures[i],
8092 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
8093 &package_id),
8095 torture_comment(tctx, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
8096 architectures[i], package_id);
8098 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8099 r.in.architecture = "foobar";
8100 r.in.language = NULL;
8101 r.in.package_id = "";
8102 r.in.driver_package_cab_size = 0;
8103 r.in.driver_package_cab = NULL;
8105 r.out.required = &required;
8106 r.out.driver_package_cab = NULL;
8108 torture_assert_ntstatus_ok(tctx,
8109 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8110 "spoolss_GetPrinterDriverPackagePath failed");
8111 torture_assert_werr_equal(tctx,
8112 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
8113 "spoolss_GetPrinterDriverPackagePath failed");
8115 r.in.architecture = architectures[i];
8117 torture_assert_ntstatus_ok(tctx,
8118 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8119 "spoolss_GetPrinterDriverPackagePath failed");
8120 torture_assert_werr_equal(tctx,
8121 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
8122 "spoolss_GetPrinterDriverPackagePath failed");
8124 r.in.package_id = package_id;
8126 torture_assert_ntstatus_ok(tctx,
8127 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8128 "spoolss_GetPrinterDriverPackagePath failed");
8129 torture_assert_hresult_ok(tctx, r.out.result,
8130 "spoolss_GetPrinterDriverPackagePath failed");
8132 r.in.driver_package_cab_size = required;
8133 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
8134 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
8136 torture_assert_ntstatus_ok(tctx,
8137 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8138 "spoolss_GetPrinterDriverPackagePath failed");
8139 torture_assert_hresult_ok(tctx, r.out.result,
8140 "spoolss_GetPrinterDriverPackagePath failed");
8142 r.in.servername = NULL;
8144 torture_assert_ntstatus_ok(tctx,
8145 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8146 "spoolss_GetPrinterDriverPackagePath failed");
8147 torture_assert_werr_equal(tctx,
8148 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INSUFFICIENT_BUFFER,
8149 "spoolss_GetPrinterDriverPackagePath failed");
8151 r.in.driver_package_cab_size = required;
8152 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
8153 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
8155 torture_assert_ntstatus_ok(tctx,
8156 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8157 "spoolss_GetPrinterDriverPackagePath failed");
8158 torture_assert_hresult_ok(tctx, r.out.result,
8159 "spoolss_GetPrinterDriverPackagePath failed");
8163 return true;
8166 static bool test_get_printer_printserverhandle(struct torture_context *tctx,
8167 void *private_data)
8169 struct test_spoolss_context *ctx =
8170 talloc_get_type_abort(private_data, struct test_spoolss_context);
8172 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8173 struct dcerpc_binding_handle *b = p->binding_handle;
8174 uint32_t levels[] = {0, 1, 2, /* 3,*/ 4, 5, 6, 7, 8};
8175 int i;
8177 for (i=0;i<ARRAY_SIZE(levels);i++) {
8179 torture_assert(tctx,
8180 test_GetPrinter_level_exp(tctx, b, &ctx->server_handle,
8181 levels[i], WERR_INVALID_LEVEL,
8182 NULL),
8183 "failed to call GetPrinter");
8186 torture_assert(tctx,
8187 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, NULL),
8188 "failed to call GetPrinter");
8190 return true;
8193 #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
8195 static bool test_set_printer_printserverhandle(struct torture_context *tctx,
8196 void *private_data)
8198 struct test_spoolss_context *ctx =
8199 talloc_get_type_abort(private_data, struct test_spoolss_context);
8201 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8202 struct dcerpc_binding_handle *b = p->binding_handle;
8203 union spoolss_PrinterInfo info;
8204 struct spoolss_SetPrinterInfoCtr info_ctr;
8205 struct spoolss_SetPrinterInfo3 info3;
8206 struct spoolss_DevmodeContainer devmode_ctr;
8207 struct sec_desc_buf secdesc_ctr;
8208 struct security_descriptor *sd;
8209 struct security_ace *ace;
8210 struct dom_sid sid;
8211 int i;
8213 torture_assert(tctx,
8214 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
8215 "failed to call GetPrinter");
8217 secdesc_ctr.sd = info.info3.secdesc;
8218 secdesc_ctr.sd->owner_sid = NULL;
8219 secdesc_ctr.sd->group_sid = NULL;
8221 sd = security_descriptor_copy(tctx, secdesc_ctr.sd);
8222 if (sd == NULL) {
8223 return false;
8226 ace = security_ace_create(tctx,
8227 TEST_SID,
8228 SEC_ACE_TYPE_ACCESS_ALLOWED,
8229 SEC_STD_REQUIRED,
8230 SEC_ACE_FLAG_CONTAINER_INHERIT);
8231 torture_assert(tctx, ace, "failed to create ace");
8233 torture_assert_ntstatus_ok(tctx,
8234 security_descriptor_dacl_add(sd, ace),
8235 "failed to add ace");
8237 secdesc_ctr.sd = sd;
8239 info3.sec_desc_ptr = 0;
8241 info_ctr.level = 3;
8242 info_ctr.info.info3 = &info3;
8244 ZERO_STRUCT(devmode_ctr);
8246 torture_assert(tctx,
8247 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
8248 &devmode_ctr, &secdesc_ctr, 0),
8249 "failed to call SetPrinter");
8251 torture_assert(tctx,
8252 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
8253 "failed to call GetPrinter");
8255 for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
8256 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
8257 break;
8261 if (i == info.info3.secdesc->dacl->num_aces) {
8262 torture_fail(tctx, "ace not present");
8265 torture_assert(tctx,
8266 dom_sid_parse(TEST_SID, &sid),
8267 "failed to parse sid");
8269 torture_assert_ntstatus_ok(tctx,
8270 security_descriptor_dacl_del(info.info3.secdesc, &sid),
8271 "failed to remove ace from sd");
8273 secdesc_ctr.sd = info.info3.secdesc;
8275 torture_assert(tctx,
8276 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
8277 &devmode_ctr, &secdesc_ctr, 0),
8278 "failed to call SetPrinter");
8280 torture_assert(tctx,
8281 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
8282 "failed to call GetPrinter");
8284 for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
8285 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
8286 torture_fail(tctx, "ace still present");
8290 return true;
8294 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
8295 void *private_data)
8297 struct test_spoolss_context *ctx =
8298 talloc_get_type_abort(private_data, struct test_spoolss_context);
8299 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8300 struct dcerpc_binding_handle *b = p->binding_handle;
8302 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
8305 static bool test_PrintServer_Forms(struct torture_context *tctx,
8306 void *private_data)
8308 struct test_spoolss_context *ctx =
8309 talloc_get_type_abort(private_data, struct test_spoolss_context);
8310 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8311 struct dcerpc_binding_handle *b = p->binding_handle;
8313 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
8316 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
8317 void *private_data)
8319 struct test_spoolss_context *ctx =
8320 talloc_get_type_abort(private_data, struct test_spoolss_context);
8321 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8322 struct dcerpc_binding_handle *b = p->binding_handle;
8324 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
8327 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
8329 NTSTATUS status;
8331 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
8333 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
8335 torture_assert(tctx,
8336 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
8337 "failed to open printserver");
8338 torture_assert(tctx,
8339 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
8340 "failed to get environment");
8342 return true;
8345 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
8347 struct test_spoolss_context *t;
8349 *data = t = talloc_zero(tctx, struct test_spoolss_context);
8351 return torture_rpc_spoolss_setup_common(tctx, t);
8354 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
8356 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
8358 return true;
8361 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
8363 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
8364 bool ret;
8366 ret = torture_rpc_spoolss_teardown_common(tctx, t);
8367 talloc_free(t);
8369 return ret;
8372 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
8374 struct dcerpc_pipe *p;
8375 struct dcerpc_binding_handle *b;
8376 const char *server_name_slash;
8377 const char *driver_name;
8378 const char *printer_name;
8379 const char *port_name;
8381 torture_assert_ntstatus_ok(tctx,
8382 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
8383 "Error connecting to server");
8385 p = t->spoolss_pipe;
8386 b = p->binding_handle;
8387 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8389 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
8390 t->driver.info8.driver_name = TORTURE_DRIVER;
8391 t->driver.info8.driver_path = "pscript5.dll";
8392 t->driver.info8.data_file = "cups6.ppd";
8393 t->driver.info8.config_file = "ps5ui.dll";
8394 t->driver.info8.help_file = "pscript.hlp";
8395 t->driver.info8.default_datatype = "RAW";
8396 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
8397 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
8398 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
8399 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
8400 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
8401 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
8402 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
8403 t->driver.info8.dependent_files->string[5] = "cups6.ini";
8404 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
8405 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
8407 t->driver.local.driver_directory= "/usr/share/cups/drivers";
8409 t->info2.portname = "LPT1:";
8411 printer_name = t->info2.printername;
8412 port_name = t->info2.portname;
8414 torture_assert(tctx,
8415 fillup_printserver_info(tctx, p, &t->driver),
8416 "failed to fillup printserver info");
8418 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
8420 torture_assert(tctx,
8421 compose_local_driver_directory(tctx, t->driver.remote.environment,
8422 t->driver.local.driver_directory,
8423 &t->driver.local.driver_directory),
8424 "failed to compose local driver directory");
8426 t->info2.drivername = "Microsoft XPS Document Writer";
8428 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8429 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
8430 t->info2.drivername, t->driver.remote.environment);
8431 t->have_driver = true;
8432 goto try_add;
8435 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8436 t->info2.drivername, t->driver.remote.environment);
8438 t->info2.drivername = "Microsoft XPS Document Writer v4";
8440 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8441 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8442 t->info2.drivername, t->driver.remote.environment);
8443 t->have_driver = true;
8444 goto try_add;
8447 torture_comment(tctx, "trying to upload own driver\n");
8449 if (!directory_exist(t->driver.local.driver_directory)) {
8450 torture_warning(tctx, "no local driver is available!");
8451 t->have_driver = false;
8452 goto try_add;
8455 torture_assert(tctx,
8456 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
8457 "failed to upload printer driver");
8459 torture_assert(tctx,
8460 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
8461 "failed to add driver");
8463 t->added_driver = true;
8464 t->have_driver = true;
8466 try_add:
8467 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8469 if (t->wellknown) {
8470 torture_assert(tctx,
8471 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
8472 "failed to add wellknown printer");
8473 } else {
8474 torture_assert(tctx,
8475 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
8476 "failed to add printer");
8479 return true;
8482 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
8484 struct torture_printer_context *t;
8486 *data = t = talloc_zero(tctx, struct torture_printer_context);
8488 t->ex = false;
8489 t->wellknown = false;
8490 t->info2.printername = TORTURE_PRINTER;
8491 t->devmode = NULL;
8493 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8496 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
8498 struct torture_printer_context *t;
8500 *data = t = talloc_zero(tctx, struct torture_printer_context);
8502 t->ex = true;
8503 t->wellknown = false;
8504 t->info2.printername = TORTURE_PRINTER_EX;
8505 t->devmode = NULL;
8507 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8510 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
8512 struct torture_printer_context *t;
8514 *data = t = talloc_zero(tctx, struct torture_printer_context);
8516 t->ex = false;
8517 t->wellknown = true;
8518 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
8519 t->devmode = NULL;
8521 /* FIXME */
8522 if (t->wellknown) {
8523 torture_skip(tctx, "skipping AddPrinter level 1");
8526 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8529 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
8531 struct torture_printer_context *t;
8533 *data = t = talloc_zero(tctx, struct torture_printer_context);
8535 t->ex = true;
8536 t->wellknown = true;
8537 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8538 t->devmode = NULL;
8540 /* FIXME */
8541 if (t->wellknown) {
8542 torture_skip(tctx, "skipping AddPrinterEx level 1");
8545 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8548 #if 0
8549 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8551 struct torture_printer_context *t;
8553 *data = t = talloc_zero(tctx, struct torture_printer_context);
8555 t->ex = true;
8556 t->wellknown = false;
8557 t->info2.printername = TORTURE_PRINTER_EX;
8558 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8560 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8562 #endif
8564 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8565 struct dcerpc_binding_handle *b,
8566 const char *server,
8567 const char *driver,
8568 const char *environment,
8569 uint32_t delete_flags,
8570 uint32_t version,
8571 WERROR expected_result);
8573 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8575 bool found = false;
8576 struct dcerpc_pipe *p = t->spoolss_pipe;
8577 struct dcerpc_binding_handle *b = NULL;
8578 const char *server_name_slash;
8579 bool ok = true;
8581 if (p == NULL) {
8582 return true;
8584 b = p->binding_handle;
8586 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8588 if (!t->wellknown) {
8589 const char *printer_name = t->info2.printername;
8591 torture_assert_goto(tctx,
8592 test_DeletePrinter(tctx, b, &t->handle),
8594 remove_driver,
8595 "failed to delete printer");
8597 torture_assert_goto(tctx,
8598 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8599 printer_name, &found),
8601 remove_driver,
8602 "failed to enumerate printers");
8604 torture_assert_goto(tctx,
8605 !found,
8607 remove_driver,
8608 "deleted printer still there");
8612 remove_driver:
8613 if (t->added_driver) {
8614 ok = remove_printer_driver(tctx,
8615 dcerpc_server_name(p),
8616 &t->driver);
8617 if (!ok) {
8618 torture_warning(tctx,
8619 "failed to remove printer driver\n");
8622 ok = test_DeletePrinterDriverEx_exp(tctx, b,
8623 server_name_slash,
8624 t->driver.info8.driver_name,
8625 t->driver.info8.architecture,
8626 DPD_DELETE_ALL_FILES,
8627 t->driver.info8.version,
8628 WERR_OK);
8629 if (!ok) {
8630 torture_warning(tctx,
8631 "failed to delete printer driver via "
8632 "spoolss\n");
8636 return ok;
8639 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8641 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8642 bool ret;
8644 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8645 talloc_free(t);
8647 return ret;
8650 static bool test_print_test(struct torture_context *tctx,
8651 void *private_data)
8653 struct torture_printer_context *t =
8654 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8655 struct dcerpc_pipe *p = t->spoolss_pipe;
8656 struct dcerpc_binding_handle *b = p->binding_handle;
8658 torture_assert(tctx,
8659 test_PausePrinter(tctx, b, &t->handle),
8660 "failed to pause printer");
8662 torture_assert(tctx,
8663 test_DoPrintTest(tctx, b, &t->handle),
8664 "failed to do print test");
8666 torture_assert(tctx,
8667 test_ResumePrinter(tctx, b, &t->handle),
8668 "failed to resume printer");
8670 return true;
8673 static bool test_print_test_extended(struct torture_context *tctx,
8674 void *private_data)
8676 struct torture_printer_context *t =
8677 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8678 struct dcerpc_pipe *p = t->spoolss_pipe;
8679 struct dcerpc_binding_handle *b = p->binding_handle;
8680 bool ret = true;
8682 torture_assert(tctx,
8683 test_PausePrinter(tctx, b, &t->handle),
8684 "failed to pause printer");
8686 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8687 if (ret == false) {
8688 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8689 if (torture_setting_bool(tctx, "samba3", false)) {
8690 torture_comment(tctx, "non-critical for samba3\n");
8691 ret = true;
8692 tctx->last_result = TORTURE_SKIP;
8696 torture_assert(tctx,
8697 test_ResumePrinter(tctx, b, &t->handle),
8698 "failed to resume printer");
8700 return ret;
8703 static bool test_print_test_properties(struct torture_context *tctx,
8704 void *private_data)
8706 struct torture_printer_context *t =
8707 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8708 struct dcerpc_pipe *p = t->spoolss_pipe;
8709 struct dcerpc_binding_handle *b = p->binding_handle;
8711 if (torture_setting_bool(tctx, "samba3", false)) {
8712 torture_skip(tctx, "skip printer job property tests against samba");
8715 torture_assert(tctx,
8716 test_PausePrinter(tctx, b, &t->handle),
8717 "failed to pause printer");
8719 torture_assert(tctx,
8720 test_DoPrintTest_properties(tctx, b, &t->handle),
8721 "failed to test print job properties");
8723 torture_assert(tctx,
8724 test_ResumePrinter(tctx, b, &t->handle),
8725 "failed to resume printer");
8727 return true;
8730 /* use smbd file IO to spool a print job */
8731 static bool test_print_test_smbd(struct torture_context *tctx,
8732 void *private_data)
8734 struct torture_printer_context *t =
8735 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8736 struct dcerpc_pipe *p = t->spoolss_pipe;
8737 struct dcerpc_binding_handle *b = p->binding_handle;
8738 NTSTATUS status;
8739 uint32_t count;
8740 union spoolss_JobInfo *info = NULL;
8741 int i;
8743 struct smb2_tree *tree;
8744 struct smb2_handle job_h;
8745 struct smbcli_options options;
8746 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8748 * Do not test against the dynamically added printers, printing via
8749 * smbd means that a different spoolss process may handle the
8750 * OpenPrinter request to the one that handled the AddPrinter request.
8751 * This currently leads to an ugly race condition where one process
8752 * sees the new printer and one doesn't.
8754 const char *share = TORTURE_PRINTER_STATIC1;
8756 torture_comment(tctx, "Testing smbd job spooling\n");
8757 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8759 status = smb2_connect(mem_ctx,
8760 torture_setting_string(tctx, "host", NULL),
8761 lpcfg_smb_ports(tctx->lp_ctx),
8762 share,
8763 lpcfg_resolve_context(tctx->lp_ctx),
8764 popt_get_cmdline_credentials(),
8765 &tree,
8766 tctx->ev,
8767 &options,
8768 lpcfg_socket_options(tctx->lp_ctx),
8769 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8770 if (!NT_STATUS_IS_OK(status)) {
8771 printf("Failed to connect to SMB2 printer %s - %s\n",
8772 share, nt_errstr(status));
8773 return false;
8776 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8777 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8779 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8780 sizeof("exciting print job data"));
8781 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8783 /* check back end spoolss job was created */
8784 torture_assert(tctx,
8785 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8786 &count, &info),
8787 "EnumJobs level 1 failed");
8789 for (i = 0; i < count; i++) {
8790 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8791 break;
8794 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8796 status = smb2_util_close(tree, job_h);
8797 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8799 /* disconnect from printer share */
8800 talloc_free(mem_ctx);
8802 return true;
8805 static bool test_print_test_purge(struct torture_context *tctx,
8806 void *private_data)
8808 struct torture_printer_context *t =
8809 (struct torture_printer_context *)talloc_get_type_abort(private_data,
8810 struct torture_printer_context);
8811 struct dcerpc_pipe *p = t->spoolss_pipe;
8812 struct dcerpc_binding_handle *b = p->binding_handle;
8813 uint32_t num_jobs = 8;
8814 uint32_t *job_ids;
8815 int i;
8816 bool ret = true;
8817 uint32_t count;
8818 union spoolss_JobInfo *info;
8820 torture_assert(tctx,
8821 test_PausePrinter(tctx, b, &t->handle),
8822 "failed to pause printer");
8824 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
8825 for (i=0; i < num_jobs; i++) {
8826 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
8827 "TorturePrintJob",
8828 &job_ids[i]);
8829 torture_assert(tctx, ret, "failed to add print job");
8832 torture_assert(tctx,
8833 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8834 &count, &info),
8835 "EnumJobs level 1 failed");
8837 torture_assert_int_equal(tctx, count, num_jobs,
8838 "unexpected number of jobs in queue");
8840 torture_assert(tctx,
8841 test_printer_purge(tctx, b, &t->handle),
8842 "failed to purge printer");
8844 torture_assert(tctx,
8845 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8846 &count, &info),
8847 "EnumJobs level 1 failed");
8849 torture_assert_int_equal(tctx, count, 0,
8850 "unexpected number of jobs in queue");
8852 torture_assert(tctx,
8853 test_ResumePrinter(tctx, b, &t->handle),
8854 "failed to resume printer");
8856 return true;
8859 static bool test_printer_sd(struct torture_context *tctx,
8860 void *private_data)
8862 struct torture_printer_context *t =
8863 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8864 struct dcerpc_pipe *p = t->spoolss_pipe;
8865 struct dcerpc_binding_handle *b = p->binding_handle;
8867 torture_assert(tctx,
8868 test_PrinterInfo_SD(tctx, b, &t->handle),
8869 "failed to test security descriptors");
8871 return true;
8874 static bool test_printer_dm(struct torture_context *tctx,
8875 void *private_data)
8877 struct torture_printer_context *t =
8878 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8879 struct dcerpc_pipe *p = t->spoolss_pipe;
8881 torture_assert(tctx,
8882 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8883 "failed to test devicemodes");
8885 return true;
8888 static bool test_printer_info_winreg(struct torture_context *tctx,
8889 void *private_data)
8891 struct torture_printer_context *t =
8892 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8893 struct dcerpc_pipe *p = t->spoolss_pipe;
8895 torture_assert(tctx,
8896 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8897 "failed to test printer info winreg");
8899 return true;
8902 static bool test_printserver_info_winreg(struct torture_context *tctx,
8903 void *private_data)
8905 struct test_spoolss_context *t =
8906 (struct test_spoolss_context *)talloc_get_type_abort(private_data, struct test_spoolss_context);
8907 struct dcerpc_pipe *p = t->spoolss_pipe;
8909 torture_assert(tctx,
8910 test_PrintserverInfo_winreg(tctx, p, &t->server_handle),
8911 "failed to test printserver info winreg");
8913 return true;
8917 static bool test_printer_change_id(struct torture_context *tctx,
8918 void *private_data)
8920 struct torture_printer_context *t =
8921 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8922 struct dcerpc_pipe *p = t->spoolss_pipe;
8924 torture_assert(tctx,
8925 test_ChangeID(tctx, p, &t->handle),
8926 "failed to test change id");
8928 return true;
8931 static bool test_printer_keys(struct torture_context *tctx,
8932 void *private_data)
8934 struct torture_printer_context *t =
8935 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8936 struct dcerpc_pipe *p = t->spoolss_pipe;
8937 struct dcerpc_binding_handle *b = p->binding_handle;
8939 torture_assert(tctx,
8940 test_printer_all_keys(tctx, b, &t->handle),
8941 "failed to test printer keys");
8943 return true;
8946 static bool test_printer_data_consistency(struct torture_context *tctx,
8947 void *private_data)
8949 struct torture_printer_context *t =
8950 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8951 struct dcerpc_pipe *p = t->spoolss_pipe;
8953 torture_assert(tctx,
8954 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8955 "failed to test printer data consistency");
8957 return true;
8960 static bool test_printer_data_keys(struct torture_context *tctx,
8961 void *private_data)
8963 struct torture_printer_context *t =
8964 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8965 struct dcerpc_pipe *p = t->spoolss_pipe;
8967 torture_assert(tctx,
8968 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8969 "failed to test printer data keys");
8971 return true;
8974 static bool test_printer_data_values(struct torture_context *tctx,
8975 void *private_data)
8977 struct torture_printer_context *t =
8978 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8979 struct dcerpc_pipe *p = t->spoolss_pipe;
8981 torture_assert(tctx,
8982 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8983 "failed to test printer data values");
8985 return true;
8988 static bool test_printer_data_set(struct torture_context *tctx,
8989 void *private_data)
8991 struct torture_printer_context *t =
8992 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8993 struct dcerpc_pipe *p = t->spoolss_pipe;
8995 torture_assert(tctx,
8996 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8997 "failed to test printer data set");
8999 return true;
9002 static bool test_printer_data_winreg(struct torture_context *tctx,
9003 void *private_data)
9005 struct torture_printer_context *t =
9006 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9007 struct dcerpc_pipe *p = t->spoolss_pipe;
9009 torture_assert(tctx,
9010 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
9011 "failed to test printer data winreg");
9013 return true;
9016 static bool test_printer_data_dsspooler(struct torture_context *tctx,
9017 void *private_data)
9019 struct torture_printer_context *t =
9020 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9021 struct dcerpc_pipe *p = t->spoolss_pipe;
9023 torture_assert(tctx,
9024 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
9025 "failed to test printer data winreg dsspooler");
9027 return true;
9030 static bool test_printer_ic(struct torture_context *tctx,
9031 void *private_data)
9033 struct torture_printer_context *t =
9034 talloc_get_type_abort(private_data,
9035 struct torture_printer_context);
9036 struct dcerpc_pipe *p = t->spoolss_pipe;
9037 struct dcerpc_binding_handle *b = p->binding_handle;
9038 struct policy_handle gdi_handle;
9040 if (torture_setting_bool(tctx, "samba3", false)) {
9041 torture_skip(tctx, "skip printer information context tests against samba");
9045 struct spoolss_CreatePrinterIC r;
9046 struct spoolss_DevmodeContainer devmode_ctr;
9048 ZERO_STRUCT(devmode_ctr);
9050 r.in.handle = &t->handle;
9051 r.in.devmode_ctr = &devmode_ctr;
9052 r.out.gdi_handle = &gdi_handle;
9054 torture_assert_ntstatus_ok(tctx,
9055 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
9056 "CreatePrinterIC failed");
9057 torture_assert_werr_ok(tctx, r.out.result,
9058 "CreatePrinterIC failed");
9062 struct spoolss_PlayGDIScriptOnPrinterIC r;
9063 DATA_BLOB in,out;
9064 int i;
9065 uint32_t num_fonts = 0;
9067 in = data_blob_string_const("");
9069 r.in.gdi_handle = &gdi_handle;
9070 r.in.pIn = in.data;
9071 r.in.cIn = in.length;
9072 r.in.ul = 0;
9074 for (i = 0; i < 4; i++) {
9076 out = data_blob_talloc_zero(tctx, i);
9078 r.in.cOut = out.length;
9079 r.out.pOut = out.data;
9081 torture_assert_ntstatus_ok(tctx,
9082 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
9083 "PlayGDIScriptOnPrinterIC failed");
9084 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_ENOUGH_MEMORY,
9085 "PlayGDIScriptOnPrinterIC failed");
9088 out = data_blob_talloc_zero(tctx, 4);
9090 r.in.cOut = out.length;
9091 r.out.pOut = out.data;
9093 torture_assert_ntstatus_ok(tctx,
9094 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
9095 "PlayGDIScriptOnPrinterIC failed");
9096 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9097 "PlayGDIScriptOnPrinterIC failed");
9099 /* now we should have the required length, so retry with a
9100 * buffer which is large enough to carry all font ids */
9102 num_fonts = IVAL(r.out.pOut, 0);
9104 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
9106 out = data_blob_talloc_zero(tctx,
9107 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
9109 r.in.cOut = out.length;
9110 r.out.pOut = out.data;
9112 torture_assert_ntstatus_ok(tctx,
9113 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
9114 "PlayGDIScriptOnPrinterIC failed");
9115 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9116 "PlayGDIScriptOnPrinterIC failed");
9121 struct spoolss_DeletePrinterIC r;
9123 r.in.gdi_handle = &gdi_handle;
9124 r.out.gdi_handle = &gdi_handle;
9126 torture_assert_ntstatus_ok(tctx,
9127 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
9128 "DeletePrinterIC failed");
9129 torture_assert_werr_ok(tctx, r.out.result,
9130 "DeletePrinterIC failed");
9134 return true;
9137 static bool test_printer_bidi(struct torture_context *tctx,
9138 void *private_data)
9140 struct torture_printer_context *t =
9141 talloc_get_type_abort(private_data,
9142 struct torture_printer_context);
9143 struct dcerpc_pipe *p = t->spoolss_pipe;
9144 struct dcerpc_binding_handle *b = p->binding_handle;
9145 struct spoolss_SendRecvBidiData r;
9146 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
9147 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
9149 if (torture_setting_bool(tctx, "samba3", false)) {
9150 torture_skip(tctx, "skip printer bidirectional tests against samba");
9153 ZERO_STRUCT(bidi_req);
9155 r.in.hPrinter = t->handle;
9156 r.in.pAction = "foobar";
9157 r.in.pReqData = &bidi_req;
9158 r.out.ppRespData = &bidi_rep;
9160 torture_assert_ntstatus_ok(tctx,
9161 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
9162 "SendRecvBidiData failed");
9163 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
9164 "SendRecvBidiData failed");
9166 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
9167 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
9170 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
9172 torture_assert_ntstatus_ok(tctx,
9173 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
9174 "SendRecvBidiData failed");
9175 torture_assert_werr_ok(tctx, r.out.result,
9176 "SendRecvBidiData failed");
9178 return true;
9181 static bool test_printer_set_publish(struct torture_context *tctx,
9182 struct dcerpc_binding_handle *b,
9183 struct policy_handle *handle)
9185 union spoolss_PrinterInfo info;
9186 struct spoolss_SetPrinterInfo7 info7;
9187 struct spoolss_SetPrinterInfoCtr info_ctr;
9188 struct spoolss_DevmodeContainer devmode_ctr;
9189 struct sec_desc_buf secdesc_ctr;
9191 info7.guid = "";
9192 info7.action = DSPRINT_PUBLISH;
9194 ZERO_STRUCT(info_ctr);
9195 ZERO_STRUCT(devmode_ctr);
9196 ZERO_STRUCT(secdesc_ctr);
9197 info_ctr.level = 7;
9198 info_ctr.info.info7 = &info7;
9200 torture_assert(tctx,
9201 test_SetPrinter(tctx, b, handle, &info_ctr,
9202 &devmode_ctr, &secdesc_ctr, 0), "");
9204 torture_assert(tctx,
9205 test_GetPrinter_level(tctx, b, handle, 2, &info),
9206 "");
9207 torture_assert(tctx,
9208 (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
9209 "info2 publish flag not set");
9210 torture_assert(tctx,
9211 test_GetPrinter_level(tctx, b, handle, 7, &info),
9212 "");
9213 if (info.info7.action & DSPRINT_PENDING) {
9214 torture_comment(tctx, "publish is pending\n");
9215 torture_assert_int_equal(tctx,
9216 info.info7.action,
9217 (DSPRINT_PENDING | DSPRINT_PUBLISH),
9218 "info7 publish flag not set");
9219 } else {
9220 struct GUID guid;
9221 char *ref_guid;
9222 torture_assert_int_equal(tctx,
9223 info.info7.action,
9224 DSPRINT_PUBLISH,
9225 "info7 publish flag not set");
9227 /* GUID_from_string is able to parse both plain and
9228 * curly-braced guids */
9229 torture_assert_ntstatus_ok(tctx,
9230 GUID_from_string(info.info7.guid,
9231 &guid),
9232 "invalid published printer GUID");
9234 /* Build reference GUID string */
9235 ref_guid = GUID_string2(tctx, &guid);
9236 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
9237 ref_guid = talloc_strdup_upper(tctx, ref_guid);
9238 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
9239 torture_assert_str_equal(tctx, info.info7.guid, ref_guid,
9240 "invalid GUID format");
9243 return true;
9246 static bool test_printer_set_unpublish(struct torture_context *tctx,
9247 struct dcerpc_binding_handle *b,
9248 struct policy_handle *handle)
9250 union spoolss_PrinterInfo info;
9251 struct spoolss_SetPrinterInfo7 info7;
9252 struct spoolss_SetPrinterInfoCtr info_ctr;
9253 struct spoolss_DevmodeContainer devmode_ctr;
9254 struct sec_desc_buf secdesc_ctr;
9256 info7.action = DSPRINT_UNPUBLISH;
9257 info7.guid = "";
9259 ZERO_STRUCT(info_ctr);
9260 ZERO_STRUCT(devmode_ctr);
9261 ZERO_STRUCT(secdesc_ctr);
9262 info_ctr.level = 7;
9263 info_ctr.info.info7 = &info7;
9265 torture_assert(tctx,
9266 test_SetPrinter(tctx, b, handle, &info_ctr,
9267 &devmode_ctr, &secdesc_ctr, 0), "");
9269 torture_assert(tctx,
9270 test_GetPrinter_level(tctx, b, handle, 2, &info),
9271 "");
9272 torture_assert(tctx,
9273 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
9274 "info2 publish flag still set");
9275 torture_assert(tctx,
9276 test_GetPrinter_level(tctx, b, handle, 7, &info),
9277 "");
9279 if (info.info7.action & DSPRINT_PENDING) {
9280 struct GUID guid;
9281 torture_comment(tctx, "unpublish is pending\n");
9282 torture_assert_int_equal(tctx,
9283 info.info7.action,
9284 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
9285 "info7 unpublish flag not set");
9286 torture_assert_ntstatus_ok(tctx,
9287 GUID_from_string(info.info7.guid,
9288 &guid),
9289 "invalid printer GUID");
9290 } else {
9291 torture_assert_int_equal(tctx,
9292 info.info7.action, DSPRINT_UNPUBLISH,
9293 "info7 unpublish flag not set");
9296 return true;
9299 static bool test_printer_publish_toggle(struct torture_context *tctx,
9300 void *private_data)
9302 struct torture_printer_context *t =
9303 talloc_get_type_abort(private_data,
9304 struct torture_printer_context);
9305 struct dcerpc_pipe *p = t->spoolss_pipe;
9306 struct dcerpc_binding_handle *b = p->binding_handle;
9307 struct policy_handle *handle = &t->handle;
9308 union spoolss_PrinterInfo info7;
9309 union spoolss_PrinterInfo info2;
9311 /* check publish status via level 7 and level 2 */
9312 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
9313 "");
9314 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
9315 "");
9317 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
9318 torture_assert_int_equal(tctx,
9319 info7.info7.action, DSPRINT_PUBLISH,
9320 "info7 publish flag not set");
9321 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
9322 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
9323 } else {
9324 torture_assert_int_equal(tctx,
9325 info7.info7.action, DSPRINT_UNPUBLISH,
9326 "info7 unpublish flag not set");
9327 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
9328 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
9331 return true;
9334 static bool test_driver_info_winreg(struct torture_context *tctx,
9335 void *private_data)
9337 struct torture_printer_context *t =
9338 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9339 struct dcerpc_pipe *p = t->spoolss_pipe;
9340 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
9342 if (!t->have_driver) {
9343 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
9346 torture_assert(tctx,
9347 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
9348 "failed to test driver info winreg");
9350 return true;
9353 static bool test_print_job_enum(struct torture_context *tctx,
9354 void *private_data)
9356 struct torture_printer_context *t =
9357 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9358 struct dcerpc_pipe *p = t->spoolss_pipe;
9359 struct dcerpc_binding_handle *b = p->binding_handle;
9360 bool ret = true;
9361 uint32_t num_jobs = 8;
9362 uint32_t *job_ids;
9363 int i;
9364 union spoolss_JobInfo *info = NULL;
9365 uint32_t count;
9367 torture_assert(tctx,
9368 test_PausePrinter(tctx, b, &t->handle),
9369 "failed to pause printer");
9371 /* purge in case of any jobs from previous tests */
9372 torture_assert(tctx,
9373 test_printer_purge(tctx, b, &t->handle),
9374 "failed to purge printer");
9376 /* enum before jobs, valid level */
9377 torture_assert(tctx,
9378 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9379 &count, &info),
9380 "EnumJobs with valid level");
9381 torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
9382 torture_assert(tctx,
9383 test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
9384 &count, &info),
9385 "EnumJobs with valid level");
9386 torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
9387 /* enum before jobs, invalid level - expect failure */
9388 torture_assert(tctx,
9389 test_EnumJobs_args(tctx, b, &t->handle, 100,
9390 WERR_INVALID_LEVEL,
9391 &count, &info),
9392 "EnumJobs with invalid level");
9394 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
9396 for (i = 0; i < num_jobs; i++) {
9397 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
9398 "TorturePrintJob",
9399 &job_ids[i]);
9400 torture_assert(tctx, ret, "failed to add print job");
9403 /* enum after jobs, valid level */
9404 torture_assert(tctx,
9405 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9406 &count, &info),
9407 "EnumJobs with valid level");
9408 torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
9409 torture_assert(tctx,
9410 test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
9411 &count, &info),
9412 "EnumJobs with valid level");
9413 torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
9414 /* enum after jobs, invalid level - expect failure */
9415 torture_assert(tctx,
9416 test_EnumJobs_args(tctx, b, &t->handle, 100,
9417 WERR_INVALID_LEVEL,
9418 &count, &info),
9419 "EnumJobs with invalid level");
9421 for (i = 0; i < num_jobs; i++) {
9422 test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
9423 SPOOLSS_JOB_CONTROL_DELETE);
9426 torture_assert(tctx,
9427 test_ResumePrinter(tctx, b, &t->handle),
9428 "failed to resume printer");
9430 return true;
9433 static bool test_printer_log_jobinfo(struct torture_context *tctx,
9434 void *private_data)
9436 struct torture_printer_context *t =
9437 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9438 struct dcerpc_pipe *p = t->spoolss_pipe;
9439 struct dcerpc_binding_handle *b = p->binding_handle;
9440 struct spoolss_BranchOfficeJobDataContainer info;
9441 int i;
9443 struct spoolss_LogJobInfoForBranchOffice r;
9445 torture_comment(tctx, "Testing LogJobInfoForBranchOffice\n");
9447 info.cJobDataEntries = 0;
9448 info.JobData = NULL;
9450 r.in.hPrinter = &t->handle;
9451 r.in.pBranchOfficeJobDataContainer = &info;
9453 torture_assert_ntstatus_ok(tctx,
9454 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
9455 "LogJobInfoForBranchOffice failed");
9456 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
9457 "LogJobInfoForBranchOffice failed");
9459 info.cJobDataEntries = 1;
9460 info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
9462 info.JobData[0].eEventType = kLogOfflineFileFull;
9463 info.JobData[0].JobId = 42;
9464 info.JobData[0].JobInfo.LogOfflineFileFull.pMachineName = talloc_strdup(tctx, "mthelena");
9466 torture_assert_ntstatus_ok(tctx,
9467 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
9468 "LogJobInfoForBranchOffice failed");
9469 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9470 "LogJobInfoForBranchOffice failed");
9472 info.cJobDataEntries = 42;
9473 info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
9475 for (i=0; i < info.cJobDataEntries; i++) {
9476 info.JobData[i].eEventType = kLogOfflineFileFull;
9477 info.JobData[i].JobId = i;
9478 info.JobData[i].JobInfo.LogOfflineFileFull.pMachineName = talloc_asprintf(tctx, "torture_%d", i);
9481 torture_assert_ntstatus_ok(tctx,
9482 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
9483 "LogJobInfoForBranchOffice failed");
9484 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9485 "LogJobInfoForBranchOffice failed");
9487 return true;
9490 static bool test_printer_os_versions(struct torture_context *tctx,
9491 void *private_data)
9493 struct torture_printer_context *t =
9494 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9495 struct dcerpc_pipe *p = t->spoolss_pipe;
9496 struct dcerpc_binding_handle *b = p->binding_handle;
9497 union spoolss_PrinterInfo info;
9498 DATA_BLOB blob;
9499 uint8_t *data;
9500 uint32_t length;
9501 struct spoolss_OSVersion osversion;
9502 uint8_t os_major, os_minor;
9503 uint16_t os_build;
9504 struct policy_handle server_handle;
9506 torture_comment(tctx, "Testing OSVersion vs. PRINTER_INFO_STRESS\n");
9508 torture_assert(tctx,
9509 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
9510 "failed to get level 0 printer info");
9512 torture_assert(tctx,
9513 test_OpenPrinter_server(tctx, p, &server_handle),
9514 "failed to open printserver");
9516 torture_assert(tctx,
9517 test_GetPrinterData_checktype(tctx, b, &server_handle, "OSVersion",
9518 NULL, NULL, &data, &length),
9519 "failed to fetch OSVersion printer data");
9521 test_ClosePrinter(tctx, b, &server_handle);
9523 blob = data_blob_const(data, length);
9525 torture_assert_ndr_success(tctx,
9526 ndr_pull_struct_blob(&blob, tctx, &osversion,
9527 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion),
9528 "failed to pull OSVersion");
9530 os_major = CVAL(&info.info0.version, 0);
9531 os_minor = CVAL(&info.info0.version, 1);
9532 os_build = SVAL(&info.info0.version, 2);
9534 torture_assert_int_equal(tctx, os_major, osversion.major, "major");
9535 torture_assert_int_equal(tctx, os_minor, osversion.minor, "minor");
9536 torture_assert_int_equal(tctx, os_build, osversion.build, "build");
9538 return true;
9542 void torture_tcase_printer(struct torture_tcase *tcase)
9544 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
9545 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
9546 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
9547 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
9548 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
9549 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
9550 torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
9551 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
9552 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
9553 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
9554 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
9555 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
9556 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
9557 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
9558 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
9559 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
9560 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
9561 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
9562 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
9563 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
9564 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
9565 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
9566 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
9567 torture_tcase_add_simple_test(tcase, "publish_toggle",
9568 test_printer_publish_toggle);
9569 torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
9570 torture_tcase_add_simple_test(tcase, "log_jobinfo", test_printer_log_jobinfo);
9571 torture_tcase_add_simple_test(tcase, "os_versions", test_printer_os_versions);
9574 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
9576 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
9577 struct torture_tcase *tcase;
9579 tcase = torture_suite_add_tcase(suite, "addprinter");
9581 torture_tcase_set_fixture(tcase,
9582 torture_rpc_spoolss_printer_setup,
9583 torture_rpc_spoolss_printer_teardown);
9585 torture_tcase_printer(tcase);
9587 tcase = torture_suite_add_tcase(suite, "addprinterex");
9589 torture_tcase_set_fixture(tcase,
9590 torture_rpc_spoolss_printerex_setup,
9591 torture_rpc_spoolss_printer_teardown);
9593 torture_tcase_printer(tcase);
9595 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
9597 torture_tcase_set_fixture(tcase,
9598 torture_rpc_spoolss_printerwkn_setup,
9599 torture_rpc_spoolss_printer_teardown);
9601 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
9603 torture_tcase_set_fixture(tcase,
9604 torture_rpc_spoolss_printerexwkn_setup,
9605 torture_rpc_spoolss_printer_teardown);
9607 #if 0
9608 /* test is not correct */
9609 tcase = torture_suite_add_tcase(suite, "addprinterdm");
9611 torture_tcase_set_fixture(tcase,
9612 torture_rpc_spoolss_printerdm_setup,
9613 torture_rpc_spoolss_printer_teardown);
9615 torture_tcase_printer(tcase);
9616 #endif
9617 return suite;
9620 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
9622 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
9623 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
9625 torture_tcase_set_fixture(tcase,
9626 torture_rpc_spoolss_setup,
9627 torture_rpc_spoolss_teardown);
9629 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
9630 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
9631 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
9632 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
9633 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
9634 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
9635 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
9636 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
9637 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
9638 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
9639 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
9640 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
9641 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
9642 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
9643 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcessorDataTypes);
9644 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
9645 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
9646 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
9647 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
9648 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
9649 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
9650 torture_tcase_add_simple_test(tcase, "get_core_printer_drivers", test_get_core_printer_drivers);
9651 torture_tcase_add_simple_test(tcase, "get_printer_driver_package_path", test_get_printer_driver_package_path);
9652 torture_tcase_add_simple_test(tcase, "get_printer", test_get_printer_printserverhandle);
9653 torture_tcase_add_simple_test(tcase, "set_printer", test_set_printer_printserverhandle);
9654 torture_tcase_add_simple_test(tcase, "printserver_info_winreg", test_printserver_info_winreg);
9656 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
9658 return suite;
9661 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
9662 struct dcerpc_binding_handle *b,
9663 const char *server,
9664 const char *environment,
9665 const char **dir_p)
9667 struct spoolss_GetPrinterDriverDirectory r;
9668 uint32_t needed;
9670 r.in.server = server;
9671 r.in.environment = environment;
9672 r.in.level = 1;
9673 r.in.buffer = NULL;
9674 r.in.offered = 0;
9675 r.out.needed = &needed;
9677 torture_assert_ntstatus_ok(tctx,
9678 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9679 "failed to query driver directory");
9681 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
9682 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
9683 r.in.buffer = &blob;
9684 r.in.offered = needed;
9686 torture_assert_ntstatus_ok(tctx,
9687 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9688 "failed to query driver directory");
9691 torture_assert_werr_ok(tctx, r.out.result,
9692 "failed to query driver directory");
9694 if (dir_p) {
9695 *dir_p = r.out.info->info1.directory_name;
9698 return true;
9701 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9703 if (info_ctr == NULL) {
9704 return NULL;
9707 switch (info_ctr->level) {
9708 case 1:
9709 return info_ctr->info.info1->driver_name;
9710 case 2:
9711 return info_ctr->info.info2->driver_name;
9712 case 3:
9713 return info_ctr->info.info3->driver_name;
9714 case 4:
9715 return info_ctr->info.info4->driver_name;
9716 case 6:
9717 return info_ctr->info.info6->driver_name;
9718 case 8:
9719 return info_ctr->info.info8->driver_name;
9720 default:
9721 return NULL;
9725 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9727 if (info_ctr == NULL) {
9728 return NULL;
9731 switch (info_ctr->level) {
9732 case 2:
9733 return info_ctr->info.info2->architecture;
9734 case 3:
9735 return info_ctr->info.info3->architecture;
9736 case 4:
9737 return info_ctr->info.info4->architecture;
9738 case 6:
9739 return info_ctr->info.info6->architecture;
9740 case 8:
9741 return info_ctr->info.info8->architecture;
9742 default:
9743 return NULL;
9748 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
9749 struct dcerpc_binding_handle *b,
9750 const char *servername,
9751 struct spoolss_AddDriverInfoCtr *info_ctr,
9752 WERROR expected_result)
9754 struct spoolss_AddPrinterDriver r;
9755 const char *drivername = get_driver_from_info(info_ctr);
9756 const char *environment = get_environment_from_info(info_ctr);
9758 r.in.servername = servername;
9759 r.in.info_ctr = info_ctr;
9761 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9762 drivername, info_ctr->level, environment);
9764 torture_assert_ntstatus_ok(tctx,
9765 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
9766 "spoolss_AddPrinterDriver failed");
9767 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9768 "spoolss_AddPrinterDriver failed with unexpected result");
9770 return true;
9774 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
9775 struct dcerpc_binding_handle *b,
9776 const char *servername,
9777 struct spoolss_AddDriverInfoCtr *info_ctr,
9778 uint32_t flags,
9779 WERROR expected_result)
9781 struct spoolss_AddPrinterDriverEx r;
9782 const char *drivername = get_driver_from_info(info_ctr);
9783 const char *environment = get_environment_from_info(info_ctr);
9785 r.in.servername = servername;
9786 r.in.info_ctr = info_ctr;
9787 r.in.flags = flags;
9789 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9790 drivername, info_ctr->level, environment);
9792 torture_assert_ntstatus_ok(tctx,
9793 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
9794 "AddPrinterDriverEx failed");
9795 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9796 "AddPrinterDriverEx failed with unexpected result");
9798 return true;
9801 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9802 if (path && strlen(path)) {\
9803 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9806 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
9807 struct dcerpc_binding_handle *b,
9808 const char *server_name,
9809 struct spoolss_AddDriverInfo8 *r,
9810 uint32_t flags,
9811 bool ex,
9812 const char *remote_driver_dir)
9814 struct spoolss_AddDriverInfoCtr info_ctr;
9815 struct spoolss_AddDriverInfo1 info1;
9817 ZERO_STRUCT(info1);
9819 info_ctr.level = 1;
9820 info_ctr.info.info1 = &info1;
9822 if (ex) {
9823 torture_assert(tctx,
9824 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_LEVEL),
9825 "failed to test AddPrinterDriverEx level 1");
9826 } else {
9827 torture_assert(tctx,
9828 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
9829 "failed to test AddPrinterDriver level 1");
9832 info1.driver_name = r->driver_name;
9834 if (ex) {
9835 torture_assert(tctx,
9836 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_LEVEL),
9837 "failed to test AddPrinterDriverEx level 1");
9838 } else {
9839 torture_assert(tctx,
9840 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
9841 "failed to test AddPrinterDriver level 1");
9844 return true;
9847 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
9848 struct dcerpc_binding_handle *b,
9849 const char *server_name,
9850 struct spoolss_AddDriverInfo8 *r,
9851 uint32_t flags,
9852 bool ex,
9853 const char *remote_driver_dir)
9855 struct spoolss_AddDriverInfoCtr info_ctr;
9856 struct spoolss_AddDriverInfo2 info2;
9857 union spoolss_DriverInfo info;
9859 ZERO_STRUCT(info2);
9861 info_ctr.level = 2;
9862 info_ctr.info.info2 = &info2;
9864 if (ex) {
9865 torture_assert(tctx,
9866 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
9867 "failed to test AddPrinterDriverEx level 2");
9868 } else {
9869 torture_assert(tctx,
9870 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
9871 "failed to test AddPrinterDriver level 2");
9874 info2.driver_name = r->driver_name;
9876 if (ex) {
9877 torture_assert(tctx,
9878 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
9879 "failed to test AddPrinterDriverEx level 2");
9880 } else {
9881 torture_assert(tctx,
9882 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
9883 "failed to test AddPrinterDriver level 2");
9886 info2.version = r->version;
9888 if (ex) {
9889 torture_assert(tctx,
9890 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
9891 "failed to test AddPrinterDriverEx level 2");
9892 } else {
9893 torture_assert(tctx,
9894 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
9895 "failed to test AddPrinterDriver level 2");
9898 info2.architecture = r->architecture;
9900 if (ex) {
9901 torture_assert(tctx,
9902 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
9903 "failed to test AddPrinterDriverEx level 2");
9904 } else {
9905 torture_assert(tctx,
9906 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
9907 "failed to test AddPrinterDriver level 2");
9910 info2.driver_path = r->driver_path;
9912 if (ex) {
9913 torture_assert(tctx,
9914 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
9915 "failed to test AddPrinterDriverEx level 2");
9916 } else {
9917 torture_assert(tctx,
9918 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
9919 "failed to test AddPrinterDriver level 2");
9922 info2.data_file = r->data_file;
9924 if (ex) {
9925 torture_assert(tctx,
9926 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
9927 "failed to test AddPrinterDriverEx level 2");
9928 } else {
9929 torture_assert(tctx,
9930 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
9931 "failed to test AddPrinterDriver level 2");
9934 info2.config_file = r->config_file;
9936 if (ex) {
9937 torture_assert(tctx,
9938 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAMETER),
9939 "failed to test AddPrinterDriverEx");
9942 if (ex) {
9943 torture_assert(tctx,
9944 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9945 "failed to test AddPrinterDriverEx level 2");
9946 } else {
9947 torture_assert(tctx,
9948 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9949 "failed to test AddPrinterDriver level 2");
9952 torture_assert(tctx,
9953 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9954 "failed to find added printer driver");
9956 if (remote_driver_dir) {
9957 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9958 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9959 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9962 return true;
9965 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9966 struct dcerpc_binding_handle *b,
9967 const char *server_name,
9968 struct spoolss_AddDriverInfo8 *r,
9969 uint32_t flags,
9970 bool ex,
9971 const char *remote_driver_dir)
9973 struct spoolss_AddDriverInfoCtr info_ctr;
9974 struct spoolss_AddDriverInfo3 info3;
9975 union spoolss_DriverInfo info;
9977 info3.driver_name = r->driver_name;
9978 info3.version = r->version;
9979 info3.architecture = r->architecture;
9980 info3.driver_path = r->driver_path;
9981 info3.data_file = r->data_file;
9982 info3.config_file = r->config_file;
9983 info3.help_file = r->help_file;
9984 info3.monitor_name = r->monitor_name;
9985 info3.default_datatype = r->default_datatype;
9986 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9987 info3.dependent_files = r->dependent_files;
9989 info_ctr.level = 3;
9990 info_ctr.info.info3 = &info3;
9992 if (ex) {
9993 torture_assert(tctx,
9994 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9995 "failed to test AddPrinterDriverEx level 3");
9996 } else {
9997 torture_assert(tctx,
9998 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9999 "failed to test AddPrinterDriver level 3");
10002 torture_assert(tctx,
10003 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
10004 "failed to find added printer driver");
10006 if (remote_driver_dir) {
10007 int i;
10008 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
10009 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
10010 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
10011 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
10012 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
10013 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
10017 return true;
10020 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
10021 struct dcerpc_binding_handle *b,
10022 const char *server_name,
10023 struct spoolss_AddDriverInfo8 *r,
10024 uint32_t flags,
10025 bool ex,
10026 const char *remote_driver_dir)
10028 struct spoolss_AddDriverInfoCtr info_ctr;
10029 struct spoolss_AddDriverInfo4 info4;
10030 union spoolss_DriverInfo info;
10032 info4.version = r->version;
10033 info4.driver_name = r->driver_name;
10034 info4.architecture = r->architecture;
10035 info4.driver_path = r->driver_path;
10036 info4.data_file = r->data_file;
10037 info4.config_file = r->config_file;
10038 info4.help_file = r->help_file;
10039 info4.monitor_name = r->monitor_name;
10040 info4.default_datatype = r->default_datatype;
10041 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
10042 info4.dependent_files = r->dependent_files;
10043 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
10044 info4.previous_names = r->previous_names;
10046 info_ctr.level = 4;
10047 info_ctr.info.info4 = &info4;
10049 if (ex) {
10050 torture_assert(tctx,
10051 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10052 "failed to test AddPrinterDriverEx level 4");
10053 } else {
10054 torture_assert(tctx,
10055 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
10056 "failed to test AddPrinterDriver level 4");
10059 torture_assert(tctx,
10060 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
10061 "failed to find added printer driver");
10063 if (remote_driver_dir) {
10064 int i;
10065 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
10066 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
10067 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
10068 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
10069 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
10070 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
10074 return true;
10077 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
10078 struct dcerpc_binding_handle *b,
10079 const char *server_name,
10080 struct spoolss_AddDriverInfo8 *r,
10081 uint32_t flags,
10082 bool ex,
10083 const char *remote_driver_dir)
10085 struct spoolss_AddDriverInfoCtr info_ctr;
10086 struct spoolss_AddDriverInfo6 info6;
10087 union spoolss_DriverInfo info;
10089 info6.version = r->version;
10090 info6.driver_name = r->driver_name;
10091 info6.architecture = r->architecture;
10092 info6.driver_path = r->driver_path;
10093 info6.data_file = r->data_file;
10094 info6.config_file = r->config_file;
10095 info6.help_file = r->help_file;
10096 info6.monitor_name = r->monitor_name;
10097 info6.default_datatype = r->default_datatype;
10098 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
10099 info6.dependent_files = r->dependent_files;
10100 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
10101 info6.previous_names = r->previous_names;
10102 info6.driver_date = r->driver_date;
10103 info6.driver_version = r->driver_version;
10104 info6.manufacturer_name = r->manufacturer_name;
10105 info6.manufacturer_url = r->manufacturer_url;
10106 info6.hardware_id = r->hardware_id;
10107 info6.provider = r->provider;
10109 info_ctr.level = 6;
10110 info_ctr.info.info6 = &info6;
10112 if (ex) {
10113 torture_assert(tctx,
10114 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10115 "failed to test AddPrinterDriverEx level 6");
10116 } else {
10117 torture_assert(tctx,
10118 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
10119 "failed to test AddPrinterDriver level 6");
10122 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10124 if (!ex) {
10125 return true;
10128 torture_assert(tctx,
10129 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
10130 "failed to find added printer driver");
10132 if (remote_driver_dir) {
10133 int i;
10134 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
10135 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
10136 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
10137 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
10138 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
10139 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
10143 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
10144 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
10146 return true;
10149 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
10150 struct dcerpc_binding_handle *b,
10151 const char *server_name,
10152 struct spoolss_AddDriverInfo8 *r,
10153 uint32_t flags,
10154 bool ex,
10155 const char *remote_driver_dir)
10157 struct spoolss_AddDriverInfoCtr info_ctr;
10158 union spoolss_DriverInfo info;
10160 info_ctr.level = 8;
10161 info_ctr.info.info8 = r;
10163 if (ex) {
10164 torture_assert(tctx,
10165 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10166 "failed to test AddPrinterDriverEx level 8");
10167 } else {
10168 torture_assert(tctx,
10169 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
10170 "failed to test AddPrinterDriver level 8");
10173 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10175 if (!ex) {
10176 return true;
10179 torture_assert(tctx,
10180 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
10181 "failed to find added printer driver");
10183 if (remote_driver_dir) {
10184 int i;
10185 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
10186 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
10187 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
10188 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
10189 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
10190 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
10194 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
10195 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
10197 return true;
10200 #undef ASSERT_DRIVER_PATH
10202 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
10203 struct dcerpc_binding_handle *b,
10204 const char *server,
10205 const char *driver,
10206 const char *environment,
10207 WERROR expected_result)
10209 struct spoolss_DeletePrinterDriver r;
10211 r.in.server = server;
10212 r.in.architecture = environment;
10213 r.in.driver = driver;
10215 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
10217 torture_assert_ntstatus_ok(tctx,
10218 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
10219 "DeletePrinterDriver failed");
10220 torture_assert_werr_equal(tctx, r.out.result, expected_result,
10221 "DeletePrinterDriver failed with unexpected result");
10223 return true;
10226 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
10227 struct dcerpc_binding_handle *b,
10228 const char *server,
10229 const char *driver,
10230 const char *environment,
10231 uint32_t delete_flags,
10232 uint32_t version,
10233 WERROR expected_result)
10235 struct spoolss_DeletePrinterDriverEx r;
10237 r.in.server = server;
10238 r.in.architecture = environment;
10239 r.in.driver = driver;
10240 r.in.delete_flags = delete_flags;
10241 r.in.version = version;
10243 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
10245 torture_assert_ntstatus_ok(tctx,
10246 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
10247 "DeletePrinterDriverEx failed");
10248 torture_assert_werr_equal(tctx, r.out.result, expected_result,
10249 "DeletePrinterDriverEx failed with unexpected result");
10251 return true;
10254 static bool test_DeletePrinterDriver(struct torture_context *tctx,
10255 struct dcerpc_binding_handle *b,
10256 const char *server_name,
10257 const char *driver,
10258 const char *environment)
10260 torture_assert(tctx,
10261 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
10262 "failed to delete driver");
10264 torture_assert(tctx,
10265 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
10266 "failed to delete driver");
10268 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
10269 torture_fail(tctx, "deleted driver still enumerated");
10272 torture_assert(tctx,
10273 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
10274 "2nd delete failed");
10276 return true;
10279 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
10280 struct dcerpc_binding_handle *b,
10281 const char *server_name,
10282 const char *driver,
10283 const char *environment,
10284 uint32_t delete_flags,
10285 uint32_t version)
10287 torture_assert(tctx,
10288 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
10289 "failed to delete driver");
10291 torture_assert(tctx,
10292 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
10293 "failed to delete driver");
10295 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
10296 torture_fail(tctx, "deleted driver still enumerated");
10299 torture_assert(tctx,
10300 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
10301 "2nd delete failed");
10303 return true;
10306 static bool test_PrinterDriver_args(struct torture_context *tctx,
10307 struct dcerpc_binding_handle *b,
10308 const char *server_name,
10309 uint32_t level,
10310 struct spoolss_AddDriverInfo8 *r,
10311 uint32_t add_flags,
10312 uint32_t delete_flags,
10313 uint32_t delete_version,
10314 bool ex,
10315 const char *remote_driver_dir)
10317 bool ret = true;
10319 switch (level) {
10320 case 1:
10321 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10322 break;
10323 case 2:
10324 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10325 break;
10326 case 3:
10327 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10328 break;
10329 case 4:
10330 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10331 break;
10332 case 6:
10333 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10334 break;
10335 case 8:
10336 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10337 break;
10338 default:
10339 return false;
10342 if (ret == false) {
10343 return ret;
10346 if (level == 1) {
10347 return ret;
10350 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10352 if (!ex && (level == 6 || level == 8)) {
10353 return ret;
10357 struct dcerpc_pipe *p2;
10358 struct policy_handle hive_handle;
10359 struct dcerpc_binding_handle *b2;
10361 torture_assert_ntstatus_ok(tctx,
10362 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
10363 "could not open winreg pipe");
10364 b2 = p2->binding_handle;
10366 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
10368 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
10370 test_winreg_CloseKey(tctx, b2, &hive_handle);
10372 talloc_free(p2);
10375 if (ex) {
10376 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
10377 } else {
10378 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
10382 static bool fillup_printserver_info(struct torture_context *tctx,
10383 struct dcerpc_pipe *p,
10384 struct torture_driver_context *d)
10386 struct policy_handle server_handle;
10387 struct dcerpc_binding_handle *b = p->binding_handle;
10388 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10390 torture_assert(tctx,
10391 test_OpenPrinter_server(tctx, p, &server_handle),
10392 "failed to open printserver");
10393 torture_assert(tctx,
10394 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
10395 "failed to get environment");
10396 torture_assert(tctx,
10397 test_ClosePrinter(tctx, b, &server_handle),
10398 "failed to close printserver");
10400 torture_assert(tctx,
10401 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
10402 d->local.environment ? d->local.environment : d->remote.environment,
10403 &d->remote.driver_directory),
10404 "failed to get driver directory");
10406 return true;
10409 static const char *driver_directory_dir(const char *driver_directory)
10411 char *p;
10413 p = strrchr(driver_directory, '\\');
10414 if (p) {
10415 return p+1;
10418 return NULL;
10421 static const char *driver_directory_share(struct torture_context *tctx,
10422 const char *driver_directory)
10424 const char *p;
10425 char *tok;
10427 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
10428 driver_directory += 2;
10431 p = talloc_strdup(tctx, driver_directory);
10433 torture_assert(tctx,
10434 next_token_talloc(tctx, &p, &tok, "\\"),
10435 "cannot explode uri");
10436 torture_assert(tctx,
10437 next_token_talloc(tctx, &p, &tok, "\\"),
10438 "cannot explode uri");
10440 return tok;
10443 #define CREATE_PRINTER_DRIVER_PATH(_d, _file) \
10444 talloc_asprintf((_d), "%s\\%s\\%s", (_d)->remote.driver_directory, (_d)->remote.driver_upload_directory, (_file))
10447 static bool create_printer_driver_directory(struct torture_context *tctx,
10448 struct smbcli_state *cli,
10449 struct torture_driver_context *d)
10451 char *driver_dir;
10453 if (d->remote.driver_upload_directory == NULL) {
10454 return true;
10457 driver_dir = talloc_asprintf(tctx,
10458 "%s\\%s",
10459 driver_directory_dir(d->remote.driver_directory),
10460 d->remote.driver_upload_directory);
10461 torture_assert_not_null(tctx, driver_dir, "ENOMEM");
10463 torture_comment(tctx,
10464 "Create remote driver directory: %s\n",
10465 driver_dir);
10467 torture_assert_ntstatus_ok(tctx,
10468 smbcli_mkdir(cli->tree,
10469 driver_dir),
10470 "Failed to create driver directory");
10472 return true;
10475 static bool upload_printer_driver_file(struct torture_context *tctx,
10476 struct smbcli_state *cli,
10477 struct torture_driver_context *d,
10478 const char *file_name)
10480 FILE *f;
10481 int fnum;
10482 uint8_t *buf;
10483 int maxwrite = 64512;
10484 off_t nread = 0;
10485 size_t start = 0;
10486 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
10487 const char *remote_name;
10488 const char *local_name;
10489 const char *p;
10491 if (!file_name || strlen(file_name) == 0) {
10492 return true;
10495 p = strrchr(file_name, '\\');
10496 if (p == NULL) {
10497 p = file_name;
10498 } else {
10499 p++;
10502 local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, p);
10503 torture_assert_not_null(tctx, local_name, "ENOMEM");
10504 if (d->remote.driver_upload_directory != NULL) {
10505 remote_name = talloc_asprintf(tctx,
10506 "%s\\%s\\%s",
10507 remote_dir,
10508 d->remote.driver_upload_directory,
10510 } else {
10511 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, p);
10513 torture_assert_not_null(tctx, remote_name, "ENOMEM");
10515 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
10517 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
10518 if (fnum == -1) {
10519 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
10522 f = fopen(local_name, "r");
10523 if (f == NULL) {
10524 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
10527 buf = talloc_array(tctx, uint8_t, maxwrite);
10528 if (!buf) {
10529 fclose(f);
10530 return false;
10533 while (!feof(f)) {
10534 int n = maxwrite;
10535 int ret;
10537 if ((n = fread(buf, 1, n, f)) < 1) {
10538 if((n == 0) && feof(f))
10539 break; /* Empty local file. */
10541 torture_warning(tctx,
10542 "failed to read file: %s\n", strerror(errno));
10543 break;
10546 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
10548 if (n != ret) {
10549 torture_warning(tctx,
10550 "failed to write file: %s\n", smbcli_errstr(cli->tree));
10551 break;
10554 nread += n;
10557 fclose(f);
10559 torture_assert_ntstatus_ok(tctx,
10560 smbcli_close(cli->tree, fnum),
10561 "failed to close file");
10563 return true;
10566 static bool connect_printer_driver_share(struct torture_context *tctx,
10567 const char *server_name,
10568 const char *share_name,
10569 struct smbcli_state **cli)
10571 struct smbcli_options smb_options;
10572 struct smbcli_session_options smb_session_options;
10574 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
10575 share_name, server_name);
10577 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
10578 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
10580 torture_assert_ntstatus_ok(tctx,
10581 smbcli_full_connection(tctx, cli, server_name,
10582 lpcfg_smb_ports(tctx->lp_ctx),
10583 share_name, NULL,
10584 lpcfg_socket_options(tctx->lp_ctx),
10585 popt_get_cmdline_credentials(),
10586 lpcfg_resolve_context(tctx->lp_ctx),
10587 tctx->ev,
10588 &smb_options,
10589 &smb_session_options,
10590 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
10591 "failed to open driver share");
10593 return true;
10596 static bool upload_printer_driver(struct torture_context *tctx,
10597 const char *server_name,
10598 struct torture_driver_context *d)
10600 struct smbcli_state *cli;
10601 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10602 int i;
10604 torture_assert(tctx,
10605 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10606 "failed to connect to driver share");
10608 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
10609 server_name, share_name);
10611 torture_assert(tctx,
10612 create_printer_driver_directory(tctx, cli, d),
10613 "failed to create driver directory");
10615 torture_assert(tctx,
10616 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10617 "failed to upload driver_path");
10618 torture_assert(tctx,
10619 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
10620 "failed to upload data_file");
10621 torture_assert(tctx,
10622 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
10623 "failed to upload config_file");
10624 torture_assert(tctx,
10625 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
10626 "failed to upload help_file");
10627 if (d->info8.dependent_files) {
10628 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10629 torture_assert(tctx,
10630 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10631 "failed to upload dependent_files");
10635 talloc_free(cli);
10637 return true;
10640 static bool check_printer_driver_file(struct torture_context *tctx,
10641 struct smbcli_state *cli,
10642 struct torture_driver_context *d,
10643 const char *file_name)
10645 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
10646 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
10647 remote_arch_dir,
10648 d->info8.version,
10649 file_name);
10650 int fnum;
10652 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
10654 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
10656 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
10657 if (fnum == -1) {
10658 return false;
10661 torture_assert_ntstatus_ok(tctx,
10662 smbcli_close(cli->tree, fnum),
10663 "failed to close driver file");
10665 return true;
10668 static bool check_printer_driver_files(struct torture_context *tctx,
10669 const char *server_name,
10670 struct torture_driver_context *d,
10671 bool expect_exist)
10673 struct smbcli_state *cli;
10674 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10675 int i;
10677 torture_assert(tctx,
10678 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10679 "failed to connect to driver share");
10681 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
10682 (expect_exist ? "": "non-"),
10683 server_name, share_name);
10685 if (d->info8.driver_path && d->info8.driver_path[0]) {
10686 torture_assert(tctx,
10687 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
10688 "failed driver_path check");
10690 if (d->info8.data_file && d->info8.data_file[0]) {
10691 torture_assert(tctx,
10692 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
10693 "failed data_file check");
10695 if (d->info8.config_file && d->info8.config_file[0]) {
10696 torture_assert(tctx,
10697 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
10698 "failed config_file check");
10700 if (d->info8.help_file && d->info8.help_file[0]) {
10701 torture_assert(tctx,
10702 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
10703 "failed help_file check");
10705 if (d->info8.dependent_files) {
10706 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10707 torture_assert(tctx,
10708 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
10709 "failed dependent_files check");
10713 talloc_free(cli);
10715 return true;
10718 static bool remove_printer_driver_file(struct torture_context *tctx,
10719 struct smbcli_state *cli,
10720 struct torture_driver_context *d,
10721 const char *file_name)
10723 const char *remote_name;
10724 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
10726 if (!file_name || strlen(file_name) == 0) {
10727 return true;
10730 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
10732 torture_comment(tctx, "Removing %s\n", remote_name);
10734 torture_assert_ntstatus_ok(tctx,
10735 smbcli_unlink(cli->tree, remote_name),
10736 "failed to unlink");
10738 return true;
10741 static bool remove_printer_driver(struct torture_context *tctx,
10742 const char *server_name,
10743 struct torture_driver_context *d)
10745 struct smbcli_state *cli;
10746 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10747 int i;
10749 torture_assert(tctx,
10750 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10751 "failed to connect to driver share");
10753 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
10754 server_name, share_name);
10756 torture_assert(tctx,
10757 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10758 "failed to remove driver_path");
10759 torture_assert(tctx,
10760 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
10761 "failed to remove data_file");
10762 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
10763 torture_assert(tctx,
10764 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
10765 "failed to remove config_file");
10767 torture_assert(tctx,
10768 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
10769 "failed to remove help_file");
10770 if (d->info8.dependent_files) {
10771 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10772 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
10773 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
10774 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
10775 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
10776 continue;
10778 torture_assert(tctx,
10779 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10780 "failed to remove dependent_files");
10784 talloc_free(cli);
10786 return true;
10790 static bool test_add_driver_arg(struct torture_context *tctx,
10791 struct dcerpc_pipe *p,
10792 struct torture_driver_context *d)
10794 bool ret = true;
10795 struct dcerpc_binding_handle *b = p->binding_handle;
10796 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10797 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
10798 int i;
10799 struct spoolss_AddDriverInfo8 info8;
10800 uint32_t add_flags = APD_COPY_NEW_FILES;
10801 uint32_t delete_flags = 0;
10803 ZERO_STRUCT(info8);
10805 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10806 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
10808 torture_assert(tctx,
10809 fillup_printserver_info(tctx, p, d),
10810 "failed to fillup printserver info");
10812 if (!directory_exist(d->local.driver_directory)) {
10813 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10816 torture_assert(tctx,
10817 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10818 "failed to upload printer driver");
10820 info8 = d->info8;
10821 if (d->info8.dependent_files) {
10822 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
10823 if (d->info8.dependent_files->string) {
10824 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10826 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
10827 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10828 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
10833 for (i=0; i < ARRAY_SIZE(levels); i++) {
10835 if (torture_setting_bool(tctx, "samba3", false)) {
10836 switch (levels[i]) {
10837 case 2:
10838 case 4:
10839 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10840 continue;
10841 default:
10842 break;
10845 if (torture_setting_bool(tctx, "w2k3", false)) {
10846 switch (levels[i]) {
10847 case 8:
10848 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10849 continue;
10850 default:
10851 break;
10855 torture_comment(tctx,
10856 "Testing PrinterDriver%s '%s' add & delete level %d\n",
10857 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10859 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);
10862 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
10863 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
10864 if (d->info8.config_file) {
10865 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
10867 if (d->info8.help_file) {
10868 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
10870 if (d->info8.dependent_files && d->info8.dependent_files->string) {
10871 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10872 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
10876 for (i=0; i < ARRAY_SIZE(levels); i++) {
10878 if (torture_setting_bool(tctx, "samba3", false)) {
10879 switch (levels[i]) {
10880 case 2:
10881 case 4:
10882 continue;
10883 default:
10884 break;
10887 if (torture_setting_bool(tctx, "w2k3", false)) {
10888 switch (levels[i]) {
10889 case 8:
10890 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10891 continue;
10892 default:
10893 break;
10897 torture_comment(tctx,
10898 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10899 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10901 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);
10904 torture_assert(tctx,
10905 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10906 "failed to remove printer driver");
10908 torture_comment(tctx, "\n");
10910 return ret;
10913 static bool test_add_driver_ex_64(struct torture_context *tctx,
10914 struct dcerpc_pipe *p)
10916 struct torture_driver_context *d;
10918 d = talloc_zero(tctx, struct torture_driver_context);
10920 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10921 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10923 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10924 d->info8.driver_name = TORTURE_DRIVER_EX;
10925 d->info8.architecture = d->local.environment;
10926 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10927 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10928 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10929 d->ex = true;
10931 return test_add_driver_arg(tctx, p, d);
10934 static bool test_add_driver_ex_32(struct torture_context *tctx,
10935 struct dcerpc_pipe *p)
10937 struct torture_driver_context *d;
10939 d = talloc_zero(tctx, struct torture_driver_context);
10941 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
10942 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10944 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10945 d->info8.driver_name = TORTURE_DRIVER_EX;
10946 d->info8.architecture = d->local.environment;
10947 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10948 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10949 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10950 d->ex = true;
10952 return test_add_driver_arg(tctx, p, d);
10955 static bool test_add_driver_64(struct torture_context *tctx,
10956 struct dcerpc_pipe *p)
10958 struct torture_driver_context *d;
10960 d = talloc_zero(tctx, struct torture_driver_context);
10962 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10963 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10965 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10966 d->info8.driver_name = TORTURE_DRIVER_ADD;
10967 d->info8.architecture = d->local.environment;
10968 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10969 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10970 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10971 d->ex = false;
10973 return test_add_driver_arg(tctx, p, d);
10976 static bool test_add_driver_32(struct torture_context *tctx,
10977 struct dcerpc_pipe *p)
10979 struct torture_driver_context *d;
10981 d = talloc_zero(tctx, struct torture_driver_context);
10983 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
10984 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10986 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10987 d->info8.driver_name = TORTURE_DRIVER_ADD;
10988 d->info8.architecture = d->local.environment;
10989 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10990 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10991 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10992 d->ex = false;
10994 return test_add_driver_arg(tctx, p, d);
10997 static bool test_add_driver_adobe(struct torture_context *tctx,
10998 struct dcerpc_pipe *p)
11000 struct torture_driver_context *d;
11002 if (!torture_setting_bool(tctx, "samba3", false)) {
11003 torture_skip(tctx, "skipping adobe test which only works against samba3");
11006 d = talloc_zero(tctx, struct torture_driver_context);
11008 d->local.environment = talloc_strdup(d, "Windows 4.0");
11009 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
11011 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
11012 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
11013 d->info8.architecture = d->local.environment;
11014 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
11015 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
11016 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
11017 #if 0
11018 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
11019 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
11020 #endif
11021 d->ex = false;
11023 return test_add_driver_arg(tctx, p, d);
11026 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
11027 struct dcerpc_pipe *p)
11029 struct torture_driver_context *d;
11030 struct spoolss_StringArray *a;
11032 if (!torture_setting_bool(tctx, "samba3", false)) {
11033 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
11036 d = talloc_zero(tctx, struct torture_driver_context);
11038 d->local.environment = talloc_strdup(d, "Windows 4.0");
11039 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
11041 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
11042 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
11043 d->info8.architecture = d->local.environment;
11044 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
11045 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
11046 d->info8.config_file = NULL;
11047 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
11048 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
11049 d->info8.default_datatype = talloc_strdup(d, "RAW");
11051 a = talloc_zero(d, struct spoolss_StringArray);
11052 a->string = talloc_zero_array(a, const char *, 7);
11053 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
11054 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
11055 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
11056 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
11057 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
11058 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
11060 d->info8.dependent_files = a;
11061 d->ex = false;
11063 return test_add_driver_arg(tctx, p, d);
11066 static bool test_add_driver_timestamps(struct torture_context *tctx,
11067 struct dcerpc_pipe *p)
11069 struct torture_driver_context *d;
11070 struct timeval t = timeval_current();
11072 d = talloc_zero(tctx, struct torture_driver_context);
11074 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
11075 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
11077 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11078 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
11079 d->info8.architecture = d->local.environment;
11080 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11081 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11082 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11083 d->info8.driver_date = timeval_to_nttime(&t);
11084 d->ex = true;
11086 torture_assert(tctx,
11087 test_add_driver_arg(tctx, p, d),
11088 "");
11090 unix_to_nt_time(&d->info8.driver_date, 1);
11092 torture_assert(tctx,
11093 test_add_driver_arg(tctx, p, d),
11094 "");
11096 return true;
11099 static bool test_multiple_drivers(struct torture_context *tctx,
11100 struct dcerpc_pipe *p)
11102 struct torture_driver_context *d;
11103 struct dcerpc_binding_handle *b = p->binding_handle;
11104 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11105 int i;
11106 struct spoolss_AddDriverInfo8 info8;
11107 uint32_t add_flags = APD_COPY_NEW_FILES;
11108 uint32_t delete_flags = 0;
11110 d = talloc_zero(tctx, struct torture_driver_context);
11112 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
11113 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
11115 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11116 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11117 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11118 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11119 d->info8.architecture = d->local.environment;
11120 d->ex = true;
11122 torture_assert(tctx,
11123 fillup_printserver_info(tctx, p, d),
11124 "failed to fillup printserver info");
11126 if (!directory_exist(d->local.driver_directory)) {
11127 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11130 torture_assert(tctx,
11131 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11132 "failed to upload printer driver");
11134 info8 = d->info8;
11136 for (i=0; i < 3; i++) {
11137 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
11139 torture_assert(tctx,
11140 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
11141 "failed to add driver");
11144 torture_assert(tctx,
11145 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
11146 "failed to delete driver");
11148 torture_assert(tctx,
11149 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
11150 "torture_test_driver_1 no longer on the server");
11152 torture_assert(tctx,
11153 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
11154 "torture_test_driver_2 no longer on the server");
11156 torture_assert(tctx,
11157 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
11158 "failed to delete driver");
11160 torture_assert(tctx,
11161 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
11162 "torture_test_driver_2 no longer on the server");
11164 torture_assert(tctx,
11165 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
11166 "failed to delete driver");
11168 torture_assert(tctx,
11169 remove_printer_driver(tctx, dcerpc_server_name(p), d),
11170 "failed to remove printer driver");
11172 return true;
11175 static bool test_driver_copy_from_directory(struct torture_context *tctx,
11176 struct dcerpc_pipe *p,
11177 const char *architecture)
11179 struct torture_driver_context *d;
11180 struct spoolss_StringArray *a;
11181 uint32_t add_flags = APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY|APD_RETURN_BLOCKING_STATUS_CODE;
11182 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
11183 struct dcerpc_binding_handle *b = p->binding_handle;
11184 const char *server_name_slash = talloc_asprintf(tctx,
11185 "\\\\%s",
11186 dcerpc_server_name(p));
11187 struct GUID guid = GUID_random();
11188 bool ok = false;
11190 d = talloc_zero(tctx, struct torture_driver_context);
11191 torture_assert_not_null(tctx, d, "ENOMEM");
11193 d->local.environment = talloc_strdup(d, architecture);
11194 torture_assert_not_null_goto(tctx, d->local.environment, ok, done, "ENOMEM");
11196 if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
11197 d->local.driver_directory =
11198 talloc_strdup(d, "/usr/share/cups/drivers/x64");
11199 } else {
11200 d->local.driver_directory =
11201 talloc_strdup(d, "/usr/share/cups/drivers/i386");
11203 torture_assert_not_null_goto(tctx, d->local.driver_directory, ok, done, "ENOMEM");
11205 d->remote.driver_upload_directory = GUID_string2(d, &guid);
11206 torture_assert_not_null_goto(tctx, d->remote.driver_upload_directory, ok, done, "ENOMEM");
11208 torture_assert(tctx,
11209 fillup_printserver_info(tctx, p, d),
11210 "failed to fillup printserver info");
11212 d->ex = true;
11213 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11214 d->info8.driver_name = TORTURE_DRIVER_COPY_DIR;
11215 d->info8.architecture = d->local.environment;
11217 d->info8.driver_path = CREATE_PRINTER_DRIVER_PATH(d, "pscript5.dll");
11218 torture_assert_not_null_goto(tctx, d->info8.driver_path, ok, done, "ENOMEM");
11219 d->info8.data_file = CREATE_PRINTER_DRIVER_PATH(d, "cups6.ppd");
11220 torture_assert_not_null_goto(tctx, d->info8.data_file, ok, done, "ENOMEM");
11221 d->info8.config_file = CREATE_PRINTER_DRIVER_PATH(d, "cupsui6.dll");
11222 torture_assert_not_null_goto(tctx, d->info8.config_file, ok, done, "ENOMEM");
11223 d->info8.help_file = CREATE_PRINTER_DRIVER_PATH(d, "pscript.hlp");
11224 torture_assert_not_null_goto(tctx, d->info8.help_file, ok, done, "ENOMEM");
11226 a = talloc_zero(d, struct spoolss_StringArray);
11227 torture_assert_not_null_goto(tctx, a, ok, done, "ENOMEM");
11228 a->string = talloc_zero_array(a, const char *, 3);
11229 torture_assert_not_null_goto(tctx, a->string, ok, done, "ENOMEM");
11230 a->string[0] = CREATE_PRINTER_DRIVER_PATH(d, "cups6.inf");
11231 torture_assert_not_null_goto(tctx, a->string[0], ok, done, "ENOMEM");
11232 a->string[1] = CREATE_PRINTER_DRIVER_PATH(d, "cups6.ini");
11233 torture_assert_not_null_goto(tctx, a->string[1], ok, done, "ENOMEM");
11235 d->info8.dependent_files = a;
11237 if (!directory_exist(d->local.driver_directory)) {
11238 torture_skip(tctx,
11239 "Skipping Printer Driver test as no local drivers "
11240 "are available");
11243 torture_assert(tctx,
11244 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11245 "failed to upload printer driver");
11247 torture_assert(tctx,
11248 test_AddPrinterDriver_args_level_3(tctx,
11250 server_name_slash,
11251 &d->info8,
11252 add_flags,
11253 true,
11254 NULL),
11255 "failed to add driver");
11257 torture_assert(tctx,
11258 test_DeletePrinterDriverEx(tctx,
11260 server_name_slash,
11261 d->info8.driver_name,
11262 d->local.environment,
11263 delete_flags,
11264 d->info8.version),
11265 "failed to delete driver");
11267 torture_assert(tctx,
11268 check_printer_driver_files(tctx,
11269 dcerpc_server_name(p),
11271 false),
11272 "printer driver file check failed");
11274 ok = true;
11275 done:
11276 talloc_free(d);
11277 return ok;
11280 static bool test_driver_copy_from_directory_64(struct torture_context *tctx,
11281 struct dcerpc_pipe *p)
11283 return test_driver_copy_from_directory(tctx, p, SPOOLSS_ARCHITECTURE_x64);
11286 static bool test_driver_copy_from_directory_32(struct torture_context *tctx,
11287 struct dcerpc_pipe *p)
11289 return test_driver_copy_from_directory(tctx, p, SPOOLSS_ARCHITECTURE_NT_X86);
11292 static bool test_del_driver_all_files(struct torture_context *tctx,
11293 struct dcerpc_pipe *p)
11295 struct torture_driver_context *d;
11296 struct spoolss_StringArray *a;
11297 uint32_t add_flags = APD_COPY_NEW_FILES;
11298 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
11299 struct dcerpc_binding_handle *b = p->binding_handle;
11300 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11302 d = talloc_zero(tctx, struct torture_driver_context);
11304 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
11305 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
11307 d->ex = true;
11308 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11309 d->info8.driver_name = TORTURE_DRIVER_DELETER;
11310 d->info8.architecture = d->local.environment;
11311 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11312 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11313 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11314 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
11316 a = talloc_zero(d, struct spoolss_StringArray);
11317 a->string = talloc_zero_array(a, const char *, 3);
11318 a->string[0] = talloc_strdup(a->string, "cups6.inf");
11319 a->string[1] = talloc_strdup(a->string, "cups6.ini");
11321 d->info8.dependent_files = a;
11323 torture_assert(tctx,
11324 fillup_printserver_info(tctx, p, d),
11325 "failed to fillup printserver info");
11327 if (!directory_exist(d->local.driver_directory)) {
11328 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11331 torture_assert(tctx,
11332 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11333 "failed to upload printer driver");
11335 torture_assert(tctx,
11336 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
11337 "failed to add driver");
11339 torture_assert(tctx,
11340 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
11341 d->info8.driver_name,
11342 d->info8.architecture,
11343 delete_flags,
11344 d->info8.version),
11345 "failed to delete driver");
11347 torture_assert(tctx,
11348 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
11349 "printer driver file check failed");
11351 talloc_free(d);
11352 return true;
11355 static bool test_del_driver_unused_files(struct torture_context *tctx,
11356 struct dcerpc_pipe *p)
11358 struct torture_driver_context *d1;
11359 struct torture_driver_context *d2;
11360 uint32_t add_flags = APD_COPY_NEW_FILES;
11361 struct dcerpc_binding_handle *b = p->binding_handle;
11362 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11364 d1 = talloc_zero(tctx, struct torture_driver_context);
11365 d1->ex = true;
11367 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
11368 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
11370 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11371 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
11372 d1->info8.architecture = NULL;
11373 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
11374 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
11375 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
11376 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
11377 d1->info8.architecture = d1->local.environment;
11379 d2 = talloc_zero(tctx, struct torture_driver_context);
11380 d2->ex = true;
11382 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
11383 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
11385 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11386 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
11387 d2->info8.architecture = NULL;
11388 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
11389 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
11390 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
11391 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
11392 d2->info8.architecture = d2->local.environment;
11394 torture_assert(tctx,
11395 fillup_printserver_info(tctx, p, d1),
11396 "failed to fillup printserver info");
11397 torture_assert(tctx,
11398 fillup_printserver_info(tctx, p, d2),
11399 "failed to fillup printserver info");
11401 if (!directory_exist(d1->local.driver_directory)) {
11402 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11405 torture_assert(tctx,
11406 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
11407 "failed to upload printer driver");
11408 torture_assert(tctx,
11409 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
11410 "failed to add driver");
11412 torture_assert(tctx,
11413 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
11414 "failed to upload printer driver");
11415 torture_assert(tctx,
11416 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
11417 "failed to add driver");
11419 /* some files are in use by a separate driver, should fail */
11420 torture_assert(tctx,
11421 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
11422 d1->info8.driver_name,
11423 d1->info8.architecture,
11424 DPD_DELETE_ALL_FILES,
11425 d1->info8.version,
11426 WERR_PRINTER_DRIVER_IN_USE),
11427 "invalid delete driver response");
11429 /* should only delete files not in use by other driver */
11430 torture_assert(tctx,
11431 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
11432 d1->info8.driver_name,
11433 d1->info8.architecture,
11434 DPD_DELETE_UNUSED_FILES,
11435 d1->info8.version,
11436 WERR_OK),
11437 "failed to delete driver (unused files)");
11439 /* check non-overlapping were deleted */
11440 d1->info8.driver_path = NULL;
11441 d1->info8.help_file = NULL;
11442 torture_assert(tctx,
11443 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
11444 "printer driver file check failed");
11445 /* d2 files should be uneffected */
11446 torture_assert(tctx,
11447 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
11448 "printer driver file check failed");
11450 torture_assert(tctx,
11451 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
11452 d2->info8.driver_name,
11453 d2->info8.architecture,
11454 DPD_DELETE_ALL_FILES,
11455 d2->info8.version,
11456 WERR_OK),
11457 "failed to delete driver");
11459 torture_assert(tctx,
11460 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
11461 "printer driver file check failed");
11463 talloc_free(d1);
11464 talloc_free(d2);
11465 return true;
11468 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
11470 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
11472 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
11473 "driver", &ndr_table_spoolss);
11474 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
11475 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
11477 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
11478 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
11480 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
11482 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
11484 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
11486 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
11488 torture_rpc_tcase_add_test(tcase,
11489 "test_driver_copy_from_directory_64",
11490 test_driver_copy_from_directory_64);
11492 torture_rpc_tcase_add_test(tcase,
11493 "test_driver_copy_from_directory_32",
11494 test_driver_copy_from_directory_32);
11496 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
11498 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
11500 return suite;