ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / rpc / spoolss.c
blobd2b7a244c113bf708804cb177269044e286044b8
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/cmdline.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;
1406 FALL_THROUGH;
1407 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1408 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1409 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1410 if (info_ctr.level > 0) {
1411 /* is invalid for all levels other then 0 */
1412 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1413 "unexpected error code returned");
1414 continue;
1415 } else {
1416 torture_assert_werr_ok(tctx, r.out.result,
1417 "failed to call SetPrinter with non 0 command");
1418 continue;
1420 break;
1422 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1423 /* FIXME: gd needs further investigation */
1424 default:
1425 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1426 "unexpected error code returned");
1427 continue;
1430 switch (info_ctr.level) {
1431 case 1:
1432 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL,
1433 "unexpected error code returned");
1434 break;
1435 case 2:
1436 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1437 "unexpected error code returned");
1438 break;
1439 case 3:
1440 case 4:
1441 case 5:
1442 case 7:
1443 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
1444 "unexpected error code returned");
1445 break;
1446 case 9:
1447 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1448 "unexpected error code returned");
1449 break;
1450 default:
1451 torture_assert_werr_ok(tctx, r.out.result,
1452 "failed to call SetPrinter");
1453 break;
1457 if (r.in.command < 5) {
1458 r.in.command++;
1459 goto again;
1462 return true;
1465 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1467 if ((r->level == 2) && (r->info.info2)) {
1468 r->info.info2->secdesc_ptr = 0;
1469 r->info.info2->devmode_ptr = 0;
1473 static bool test_PrinterInfo(struct torture_context *tctx,
1474 struct dcerpc_binding_handle *b,
1475 struct policy_handle *handle)
1477 NTSTATUS status;
1478 struct spoolss_SetPrinter s;
1479 struct spoolss_GetPrinter q;
1480 struct spoolss_GetPrinter q0;
1481 struct spoolss_SetPrinterInfoCtr info_ctr;
1482 union spoolss_PrinterInfo info;
1483 struct spoolss_DevmodeContainer devmode_ctr;
1484 struct sec_desc_buf secdesc_ctr;
1485 uint32_t needed = 0;
1486 DATA_BLOB blob = data_blob_null;
1487 bool ret = true;
1488 int i;
1490 uint32_t status_list[] = {
1491 /* these do not stick
1492 PRINTER_STATUS_PAUSED,
1493 PRINTER_STATUS_ERROR,
1494 PRINTER_STATUS_PENDING_DELETION, */
1495 PRINTER_STATUS_PAPER_JAM,
1496 PRINTER_STATUS_PAPER_OUT,
1497 PRINTER_STATUS_MANUAL_FEED,
1498 PRINTER_STATUS_PAPER_PROBLEM,
1499 PRINTER_STATUS_OFFLINE,
1500 PRINTER_STATUS_IO_ACTIVE,
1501 PRINTER_STATUS_BUSY,
1502 PRINTER_STATUS_PRINTING,
1503 PRINTER_STATUS_OUTPUT_BIN_FULL,
1504 PRINTER_STATUS_NOT_AVAILABLE,
1505 PRINTER_STATUS_WAITING,
1506 PRINTER_STATUS_PROCESSING,
1507 PRINTER_STATUS_INITIALIZING,
1508 PRINTER_STATUS_WARMING_UP,
1509 PRINTER_STATUS_TONER_LOW,
1510 PRINTER_STATUS_NO_TONER,
1511 PRINTER_STATUS_PAGE_PUNT,
1512 PRINTER_STATUS_USER_INTERVENTION,
1513 PRINTER_STATUS_OUT_OF_MEMORY,
1514 PRINTER_STATUS_DOOR_OPEN,
1515 PRINTER_STATUS_SERVER_UNKNOWN,
1516 PRINTER_STATUS_POWER_SAVE,
1517 /* these do not stick
1518 0x02000000,
1519 0x04000000,
1520 0x08000000,
1521 0x10000000,
1522 0x20000000,
1523 0x40000000,
1524 0x80000000 */
1526 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1527 uint32_t attribute_list[] = {
1528 PRINTER_ATTRIBUTE_QUEUED,
1529 /* fails with WERR_INVALID_DATATYPE:
1530 PRINTER_ATTRIBUTE_DIRECT, */
1531 /* does not stick
1532 PRINTER_ATTRIBUTE_DEFAULT, */
1533 PRINTER_ATTRIBUTE_SHARED,
1534 /* does not stick
1535 PRINTER_ATTRIBUTE_NETWORK, */
1536 PRINTER_ATTRIBUTE_HIDDEN,
1537 PRINTER_ATTRIBUTE_LOCAL,
1538 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1539 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1540 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1541 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1542 /* does not stick
1543 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1544 /* fails with WERR_INVALID_DATATYPE:
1545 PRINTER_ATTRIBUTE_RAW_ONLY, */
1546 /* these do not stick
1547 PRINTER_ATTRIBUTE_PUBLISHED,
1548 PRINTER_ATTRIBUTE_FAX,
1549 PRINTER_ATTRIBUTE_TS,
1550 0x00010000,
1551 0x00020000,
1552 0x00040000,
1553 0x00080000,
1554 0x00100000,
1555 0x00200000,
1556 0x00400000,
1557 0x00800000,
1558 0x01000000,
1559 0x02000000,
1560 0x04000000,
1561 0x08000000,
1562 0x10000000,
1563 0x20000000,
1564 0x40000000,
1565 0x80000000 */
1568 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1571 ZERO_STRUCT(devmode_ctr);
1572 ZERO_STRUCT(secdesc_ctr);
1574 s.in.handle = handle;
1575 s.in.command = 0;
1576 s.in.info_ctr = &info_ctr;
1577 s.in.devmode_ctr = &devmode_ctr;
1578 s.in.secdesc_ctr = &secdesc_ctr;
1580 q.in.handle = handle;
1581 q.out.info = &info;
1582 q0 = q;
1584 #define TESTGETCALL(call, r, needed, blob) \
1585 r.in.buffer = NULL; \
1586 r.in.offered = 0;\
1587 r.out.needed = &needed; \
1588 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1589 if (!NT_STATUS_IS_OK(status)) { \
1590 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1591 r.in.level, nt_errstr(status), __location__); \
1592 ret = false; \
1593 break; \
1595 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1596 blob = data_blob_talloc_zero(tctx, needed); \
1597 r.in.buffer = &blob; \
1598 r.in.offered = needed; \
1600 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1601 if (!NT_STATUS_IS_OK(status)) { \
1602 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1603 r.in.level, nt_errstr(status), __location__); \
1604 ret = false; \
1605 break; \
1607 if (!W_ERROR_IS_OK(r.out.result)) { \
1608 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1609 r.in.level, win_errstr(r.out.result), __location__); \
1610 ret = false; \
1611 break; \
1615 #define TESTSETCALL_EXP(call, r, err) \
1616 clear_info2(&info_ctr);\
1617 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1618 if (!NT_STATUS_IS_OK(status)) { \
1619 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1620 r.in.info_ctr->level, nt_errstr(status), __location__); \
1621 ret = false; \
1622 break; \
1624 if (!W_ERROR_IS_OK(err)) { \
1625 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1626 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1627 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1628 ret = false; \
1630 break; \
1632 if (!W_ERROR_IS_OK(r.out.result)) { \
1633 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1634 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1635 ret = false; \
1636 break; \
1639 #define TESTSETCALL(call, r) \
1640 TESTSETCALL_EXP(call, r, WERR_OK)
1642 #define STRING_EQUAL(s1, s2, field) \
1643 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1644 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1645 #field, s2, __location__); \
1646 ret = false; \
1647 break; \
1650 #define MEM_EQUAL(s1, s2, length, field) \
1651 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1652 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1653 #field, (const char *)s2, __location__); \
1654 ret = false; \
1655 break; \
1658 #define INT_EQUAL(i1, i2, field) \
1659 if (i1 != i2) { \
1660 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1661 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1662 ret = false; \
1663 break; \
1666 #define SD_EQUAL(sd1, sd2, field) \
1667 if (!security_descriptor_equal(sd1, sd2)) { \
1668 torture_comment(tctx, "Failed to set %s (%s)\n", \
1669 #field, __location__); \
1670 ret = false; \
1671 break; \
1674 #define TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, lvl1, field1, lvl2, field2, value, err) do { \
1675 void *p; \
1676 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1677 q.in.level = lvl1; \
1678 TESTGETCALL(GetPrinter, q, needed, blob) \
1679 info_ctr.level = lvl1; \
1680 p = (void *)&q.out.info->info ## lvl1; \
1681 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1682 info_ctr.info.info ## lvl1->field1 = value;\
1683 TESTSETCALL_EXP(SetPrinter, s, err) \
1684 info_ctr.info.info ## lvl1->field1 = ""; \
1685 TESTGETCALL(GetPrinter, q, needed, blob) \
1686 info_ctr.info.info ## lvl1->field1 = value; \
1687 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1688 q.in.level = lvl2; \
1689 TESTGETCALL(GetPrinter, q, needed, blob) \
1690 p = (void *)&q.out.info->info ## lvl2; \
1691 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1692 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1693 } while (0)
1695 #define TEST_PRINTERINFO_STRING(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
1696 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, lvl1, field1, lvl2, field2, value, WERR_OK); \
1697 } while (0);
1699 #define TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, exp_value) do { \
1700 void *p; \
1701 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1702 q.in.level = lvl1; \
1703 TESTGETCALL(GetPrinter, q, needed, blob) \
1704 info_ctr.level = lvl1; \
1705 p = (void *)&q.out.info->info ## lvl1; \
1706 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1707 info_ctr.info.info ## lvl1->field1 = value; \
1708 TESTSETCALL(SetPrinter, s) \
1709 info_ctr.info.info ## lvl1->field1 = 0; \
1710 TESTGETCALL(GetPrinter, q, needed, blob) \
1711 p = (void *)&q.out.info->info ## lvl1; \
1712 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1713 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1714 q.in.level = lvl2; \
1715 TESTGETCALL(GetPrinter, q, needed, blob) \
1716 p = (void *)&q.out.info->info ## lvl2; \
1717 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1718 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1719 } while (0)
1721 #define TEST_PRINTERINFO_INT(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
1722 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value); \
1723 } while (0)
1725 q0.in.level = 0;
1726 do { TESTGETCALL(GetPrinter, q0, needed, blob) } while (0);
1728 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, comment, 1, comment, "xx2-1 comment");
1729 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, comment, 2, comment, "xx2-2 comment");
1731 /* level 0 printername does not stick */
1732 /* TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername, 0, printername, "xx2-0 printer"); */
1733 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername, 1, name, "xx2-1 printer");
1734 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername, 2, printername, "xx2-2 printer");
1735 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername, 4, printername, "xx2-4 printer");
1736 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername, 5, printername, "xx2-5 printer");
1737 /* TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername, 0, printername, "xx4-0 printer"); */
1738 TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername, 1, name, "xx4-1 printer");
1739 TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername, 2, printername, "xx4-2 printer");
1740 TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername, 4, printername, "xx4-4 printer");
1741 TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername, 5, printername, "xx4-5 printer");
1742 /* TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername, 0, printername, "xx5-0 printer"); */
1743 TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername, 1, name, "xx5-1 printer");
1744 TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername, 2, printername, "xx5-2 printer");
1745 TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername, 4, printername, "xx5-4 printer");
1746 TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername, 5, printername, "xx5-5 printer");
1748 /* servername can be set but does not stick
1749 TEST_PRINTERINFO_STRING(q, 2, servername, 0, servername, "xx2-0 servername");
1750 TEST_PRINTERINFO_STRING(q, 2, servername, 2, servername, "xx2-2 servername");
1751 TEST_PRINTERINFO_STRING(q, 2, servername, 4, servername, "xx2-4 servername");
1754 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1755 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1756 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1757 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1758 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1760 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, sharename, 2, sharename, "xx2-2 sharename");
1761 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1762 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1763 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, location, 2, location, "xx2-2 location");
1764 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1765 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1766 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1767 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1768 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, datatype, 2, datatype, "xx2-2 datatype");
1769 TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, parameters, 2, parameters, "xx2-2 parameters");
1771 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1772 /* TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 1, flags,
1773 attribute_list[i],
1774 (attribute_list[i] | default_attribute)
1775 ); */
1776 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 2, attributes,
1777 attribute_list[i],
1778 (attribute_list[i] | default_attribute)
1780 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 4, attributes,
1781 attribute_list[i],
1782 (attribute_list[i] | default_attribute)
1784 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 5, attributes,
1785 attribute_list[i],
1786 (attribute_list[i] | default_attribute)
1788 /* TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 1, flags,
1789 attribute_list[i],
1790 (attribute_list[i] | default_attribute)
1791 ); */
1792 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 2, attributes,
1793 attribute_list[i],
1794 (attribute_list[i] | default_attribute)
1796 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 4, attributes,
1797 attribute_list[i],
1798 (attribute_list[i] | default_attribute)
1800 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 5, attributes,
1801 attribute_list[i],
1802 (attribute_list[i] | default_attribute)
1804 /* TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 1, flags,
1805 attribute_list[i],
1806 (attribute_list[i] | default_attribute)
1807 ); */
1808 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 2, attributes,
1809 attribute_list[i],
1810 (attribute_list[i] | default_attribute)
1812 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 4, attributes,
1813 attribute_list[i],
1814 (attribute_list[i] | default_attribute)
1816 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 5, attributes,
1817 attribute_list[i],
1818 (attribute_list[i] | default_attribute)
1822 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1823 /* level 2 sets do not stick
1824 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status, 0, status, status_list[i]);
1825 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status, 2, status, status_list[i]);
1826 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status, 6, status, status_list[i]); */
1827 TEST_PRINTERINFO_INT(q, s, needed, blob, 6, status, 0, status, status_list[i]);
1828 TEST_PRINTERINFO_INT(q, s, needed, blob, 6, status, 2, status, status_list[i]);
1829 TEST_PRINTERINFO_INT(q, s, needed, blob, 6, status, 6, status, status_list[i]);
1832 /* priorities need to be between 0 and 99
1833 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1834 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority, 2, priority, 0);
1835 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority, 2, priority, 1);
1836 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority, 2, priority, 99);
1837 /* TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority, 2, priority, 100); */
1838 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 0);
1839 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 1);
1840 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 99);
1841 /* TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 100); */
1843 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, starttime, 2, starttime, __LINE__);
1844 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, untiltime, 2, untiltime, __LINE__);
1846 /* does not stick
1847 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, cjobs, 2, cjobs, __LINE__);
1848 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, averageppm, 2, averageppm, __LINE__); */
1850 /* does not stick
1851 TEST_PRINTERINFO_INT(q, s, needed, blob, 5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1852 TEST_PRINTERINFO_INT(q, s, needed, blob, 5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1854 /* FIXME: gd also test devmode and secdesc behavior */
1857 /* verify composition of level 1 description field */
1858 const char *description;
1859 const char *tmp;
1861 q0.in.level = 1;
1862 do { TESTGETCALL(GetPrinter, q0, needed, blob) } while (0);
1864 description = talloc_strdup(tctx, q0.out.info->info1.description);
1866 q0.in.level = 2;
1867 do { TESTGETCALL(GetPrinter, q0, needed, blob) } while (0);
1869 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1870 q0.out.info->info2.printername,
1871 q0.out.info->info2.drivername,
1872 q0.out.info->info2.location);
1874 do { STRING_EQUAL(description, tmp, "description")} while (0);
1877 return ret;
1880 static bool test_security_descriptor_equal(struct torture_context *tctx,
1881 const struct security_descriptor *sd1,
1882 const struct security_descriptor *sd2)
1884 if (sd1 == sd2) {
1885 return true;
1888 if (!sd1 || !sd2) {
1889 torture_comment(tctx, "%s\n", __location__);
1890 return false;
1893 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1894 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1896 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1897 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1899 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1900 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1901 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1902 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1903 return false;
1905 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1906 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1907 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1908 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1909 return false;
1912 return true;
1915 static bool test_sd_set_level(struct torture_context *tctx,
1916 struct dcerpc_binding_handle *b,
1917 struct policy_handle *handle,
1918 uint32_t level,
1919 struct security_descriptor *sd)
1921 struct spoolss_SetPrinterInfoCtr info_ctr;
1922 struct spoolss_DevmodeContainer devmode_ctr;
1923 struct sec_desc_buf secdesc_ctr;
1924 union spoolss_SetPrinterInfo sinfo;
1925 union spoolss_PrinterInfo info;
1926 struct spoolss_SetPrinterInfo3 info3;
1928 ZERO_STRUCT(devmode_ctr);
1929 ZERO_STRUCT(secdesc_ctr);
1931 switch (level) {
1932 case 2: {
1933 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1934 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1936 info_ctr.level = 2;
1937 info_ctr.info = sinfo;
1939 break;
1941 case 3: {
1943 info3.sec_desc_ptr = 0;
1945 info_ctr.level = 3;
1946 info_ctr.info.info3 = &info3;
1948 break;
1950 default:
1951 return false;
1954 secdesc_ctr.sd = sd;
1956 torture_assert(tctx,
1957 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1959 return true;
1962 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1963 struct dcerpc_binding_handle *b,
1964 struct policy_handle *handle)
1966 union spoolss_PrinterInfo info;
1967 struct security_descriptor *sd1, *sd2;
1968 int i;
1970 /* just compare level 2 and level 3 */
1972 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1974 sd1 = info.info2.secdesc;
1976 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1978 sd2 = info.info3.secdesc;
1980 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1981 "SD level 2 != SD level 3");
1984 /* query level 2, set level 2, query level 2 */
1986 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1988 sd1 = info.info2.secdesc;
1990 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1992 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1994 sd2 = info.info2.secdesc;
1995 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1996 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1997 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
2000 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
2001 "SD level 2 != SD level 2 after SD has been set via level 2");
2004 /* query level 2, set level 3, query level 2 */
2006 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2008 sd1 = info.info2.secdesc;
2010 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
2012 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2014 sd2 = info.info2.secdesc;
2016 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
2017 "SD level 2 != SD level 2 after SD has been set via level 3");
2019 /* set modified sd level 3, query level 2 */
2021 for (i=0; i < 93; i++) {
2022 struct security_ace a = {};
2023 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
2024 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
2025 a.flags = 0;
2026 a.size = 0; /* autogenerated */
2027 a.access_mask = 0;
2028 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
2029 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
2032 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
2034 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2035 sd2 = info.info2.secdesc;
2037 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
2038 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
2039 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
2042 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
2043 "modified SD level 2 != SD level 2 after SD has been set via level 3");
2046 return true;
2050 * wrapper call that saves original sd, runs tests, and restores sd
2053 static bool test_PrinterInfo_SD(struct torture_context *tctx,
2054 struct dcerpc_binding_handle *b,
2055 struct policy_handle *handle)
2057 union spoolss_PrinterInfo info;
2058 struct security_descriptor *sd;
2059 bool ret = true;
2061 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2063 /* save original sd */
2065 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2066 "failed to get initial security descriptor");
2068 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2070 /* run tests */
2072 ret = test_PrinterInfo_SDs(tctx, b, handle);
2074 /* restore original sd */
2076 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2077 "failed to restore initial security descriptor");
2079 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2080 ret ? "succeeded" : "failed");
2083 return ret;
2086 static bool test_devmode_set_level(struct torture_context *tctx,
2087 struct dcerpc_binding_handle *b,
2088 struct policy_handle *handle,
2089 uint32_t level,
2090 struct spoolss_DeviceMode *devmode)
2092 struct spoolss_SetPrinterInfo8 info8;
2093 struct spoolss_SetPrinterInfoCtr info_ctr;
2094 struct spoolss_DevmodeContainer devmode_ctr;
2095 struct sec_desc_buf secdesc_ctr;
2096 union spoolss_SetPrinterInfo sinfo;
2098 ZERO_STRUCT(devmode_ctr);
2099 ZERO_STRUCT(secdesc_ctr);
2101 switch (level) {
2102 case 2: {
2103 union spoolss_PrinterInfo info;
2104 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2105 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2107 info_ctr.level = 2;
2108 info_ctr.info = sinfo;
2110 break;
2112 case 8: {
2113 info8.devmode_ptr = 0;
2115 info_ctr.level = 8;
2116 info_ctr.info.info8 = &info8;
2118 break;
2120 default:
2121 return false;
2124 devmode_ctr.devmode = devmode;
2126 torture_assert(tctx,
2127 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2129 return true;
2133 static bool test_devicemode_equal(struct torture_context *tctx,
2134 const struct spoolss_DeviceMode *d1,
2135 const struct spoolss_DeviceMode *d2)
2137 if (d1 == d2) {
2138 return true;
2141 if (!d1 || !d2) {
2142 torture_comment(tctx, "%s\n", __location__);
2143 return false;
2145 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2146 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2147 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2148 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2149 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2150 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2151 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2152 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2153 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2154 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2155 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2156 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2157 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2158 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2159 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2160 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2161 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2162 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2163 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2164 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2165 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2166 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2167 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2168 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2169 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2170 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2171 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2172 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2173 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2174 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2175 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2176 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2177 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2178 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2179 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2181 return true;
2184 static bool test_devicemode_full(struct torture_context *tctx,
2185 struct dcerpc_binding_handle *b,
2186 struct policy_handle *handle)
2188 struct spoolss_SetPrinter s;
2189 struct spoolss_GetPrinter q;
2190 struct spoolss_SetPrinterInfoCtr info_ctr;
2191 struct spoolss_SetPrinterInfo8 info8;
2192 union spoolss_PrinterInfo info;
2193 struct spoolss_DevmodeContainer devmode_ctr;
2194 struct sec_desc_buf secdesc_ctr;
2195 uint32_t needed = 0;
2196 DATA_BLOB blob = data_blob_null;
2197 bool ret = true;
2198 NTSTATUS status;
2200 #define TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2201 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2202 q.in.level = lvl1; \
2203 TESTGETCALL(GetPrinter, q, needed, blob) \
2204 info_ctr.level = lvl1; \
2205 if (lvl1 == 2) {\
2206 void *p = (void *)&q.out.info->info ## lvl1; \
2207 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
2208 } else if (lvl1 == 8) {\
2209 info_ctr.info.info ## lvl1 = &info8; \
2211 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2212 devmode_ctr.devmode->field1 = value; \
2213 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2214 if (W_ERROR_IS_OK(expected_result)) { \
2215 TESTGETCALL(GetPrinter, q, needed, blob) \
2216 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2217 q.in.level = lvl2; \
2218 TESTGETCALL(GetPrinter, q, needed, blob) \
2219 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2221 } while (0)
2223 #define TEST_DEVMODE_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, expected_result) do { \
2224 TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value, expected_result); \
2225 } while (0)
2227 #define TEST_DEVMODE_INT(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
2228 TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2229 } while (0)
2231 ZERO_STRUCT(devmode_ctr);
2232 ZERO_STRUCT(secdesc_ctr);
2233 ZERO_STRUCT(info8);
2235 s.in.handle = handle;
2236 s.in.command = 0;
2237 s.in.info_ctr = &info_ctr;
2238 s.in.devmode_ctr = &devmode_ctr;
2239 s.in.secdesc_ctr = &secdesc_ctr;
2241 q.in.handle = handle;
2242 q.out.info = &info;
2244 #if 0
2245 const char *devicename;/* [charset(UTF16)] */
2246 enum spoolss_DeviceModeSpecVersion specversion;
2247 uint16_t driverversion;
2248 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2249 uint32_t fields;
2250 #endif
2251 TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size, 8, size, __LINE__, WERR_INVALID_PARAMETER);
2252 TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size, 8, size, 0, WERR_INVALID_PARAMETER);
2253 TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size, 8, size, 0xffff, WERR_INVALID_PARAMETER);
2254 TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
2255 TEST_DEVMODE_INT(q, s, needed, blob, 8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2257 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2258 torture_assert(tctx,
2259 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2260 "failed to set devmode");
2262 TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
2263 TEST_DEVMODE_INT(q, s, needed, blob, 8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2265 TEST_DEVMODE_INT(q, s, needed, blob, 8, orientation, 8, orientation, __LINE__);
2266 TEST_DEVMODE_INT(q, s, needed, blob, 8, papersize, 8, papersize, __LINE__);
2267 TEST_DEVMODE_INT(q, s, needed, blob, 8, paperlength, 8, paperlength, __LINE__);
2268 TEST_DEVMODE_INT(q, s, needed, blob, 8, paperwidth, 8, paperwidth, __LINE__);
2269 TEST_DEVMODE_INT(q, s, needed, blob, 8, scale, 8, scale, __LINE__);
2270 TEST_DEVMODE_INT(q, s, needed, blob, 8, copies, 8, copies, __LINE__);
2271 TEST_DEVMODE_INT(q, s, needed, blob, 8, defaultsource, 8, defaultsource, __LINE__);
2272 TEST_DEVMODE_INT(q, s, needed, blob, 8, printquality, 8, printquality, __LINE__);
2273 TEST_DEVMODE_INT(q, s, needed, blob, 8, color, 8, color, __LINE__);
2274 TEST_DEVMODE_INT(q, s, needed, blob, 8, duplex, 8, duplex, __LINE__);
2275 TEST_DEVMODE_INT(q, s, needed, blob, 8, yresolution, 8, yresolution, __LINE__);
2276 TEST_DEVMODE_INT(q, s, needed, blob, 8, ttoption, 8, ttoption, __LINE__);
2277 TEST_DEVMODE_INT(q, s, needed, blob, 8, collate, 8, collate, __LINE__);
2278 #if 0
2279 const char *formname;/* [charset(UTF16)] */
2280 #endif
2281 TEST_DEVMODE_INT(q, s, needed, blob, 8, logpixels, 8, logpixels, __LINE__);
2282 TEST_DEVMODE_INT(q, s, needed, blob, 8, bitsperpel, 8, bitsperpel, __LINE__);
2283 TEST_DEVMODE_INT(q, s, needed, blob, 8, pelswidth, 8, pelswidth, __LINE__);
2284 TEST_DEVMODE_INT(q, s, needed, blob, 8, pelsheight, 8, pelsheight, __LINE__);
2285 TEST_DEVMODE_INT(q, s, needed, blob, 8, displayflags, 8, displayflags, __LINE__);
2286 TEST_DEVMODE_INT(q, s, needed, blob, 8, displayfrequency, 8, displayfrequency, __LINE__);
2287 TEST_DEVMODE_INT(q, s, needed, blob, 8, icmmethod, 8, icmmethod, __LINE__);
2288 TEST_DEVMODE_INT(q, s, needed, blob, 8, icmintent, 8, icmintent, __LINE__);
2289 TEST_DEVMODE_INT(q, s, needed, blob, 8, mediatype, 8, mediatype, __LINE__);
2290 TEST_DEVMODE_INT(q, s, needed, blob, 8, dithertype, 8, dithertype, __LINE__);
2291 TEST_DEVMODE_INT(q, s, needed, blob, 8, reserved1, 8, reserved1, __LINE__);
2292 TEST_DEVMODE_INT(q, s, needed, blob, 8, reserved2, 8, reserved2, __LINE__);
2293 TEST_DEVMODE_INT(q, s, needed, blob, 8, panningwidth, 8, panningwidth, __LINE__);
2294 TEST_DEVMODE_INT(q, s, needed, blob, 8, panningheight, 8, panningheight, __LINE__);
2296 return ret;
2299 static bool call_OpenPrinterEx(struct torture_context *tctx,
2300 struct dcerpc_pipe *p,
2301 const char *name,
2302 struct spoolss_DeviceMode *devmode,
2303 struct policy_handle *handle);
2305 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2306 struct dcerpc_pipe *p,
2307 struct policy_handle *handle,
2308 const char *name)
2310 union spoolss_PrinterInfo info;
2311 struct spoolss_DeviceMode *devmode;
2312 struct spoolss_DeviceMode *devmode2;
2313 struct policy_handle handle_devmode;
2314 struct dcerpc_binding_handle *b = p->binding_handle;
2316 /* simply compare level8 and level2 devmode */
2318 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2320 devmode = info.info8.devmode;
2322 if (devmode && devmode->size == 0) {
2323 torture_fail(tctx,
2324 "devmode of zero size!");
2327 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2329 devmode2 = info.info2.devmode;
2331 if (devmode2 && devmode2->size == 0) {
2332 torture_fail(tctx,
2333 "devmode of zero size!");
2336 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2337 "DM level 8 != DM level 2");
2340 /* set devicemode level 8 and see if it persists */
2342 devmode->copies = 93;
2343 devmode->formname = talloc_strdup(tctx, "Legal");
2345 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2347 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2349 devmode2 = info.info8.devmode;
2351 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2352 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2354 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2356 devmode2 = info.info2.devmode;
2358 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2359 "modified DM level 8 != DM level 2");
2362 /* set devicemode level 2 and see if it persists */
2364 devmode->copies = 39;
2365 devmode->formname = talloc_strdup(tctx, "Executive");
2367 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2369 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2371 devmode2 = info.info8.devmode;
2373 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2374 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2376 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2378 devmode2 = info.info2.devmode;
2380 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2381 "modified DM level 8 != DM level 2");
2384 /* check every single bit in public part of devicemode */
2386 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2387 "failed to set every single devicemode component");
2390 /* change formname upon open and see if it persists in getprinter calls */
2392 devmode->formname = talloc_strdup(tctx, "A4");
2393 devmode->copies = 42;
2395 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2396 "failed to open printer handle");
2398 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2400 devmode2 = info.info8.devmode;
2402 if (strequal(devmode->devicename, devmode2->devicename)) {
2403 torture_warning(tctx, "devicenames are the same\n");
2404 } else {
2405 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2406 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2409 if (strequal(devmode->formname, devmode2->formname)) {
2410 torture_warning(tctx, "formname are the same\n");
2411 } else {
2412 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2413 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2416 if (devmode->copies == devmode2->copies) {
2417 torture_warning(tctx, "copies are the same\n");
2418 } else {
2419 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2420 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2423 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2425 devmode2 = info.info2.devmode;
2427 if (strequal(devmode->devicename, devmode2->devicename)) {
2428 torture_warning(tctx, "devicenames are the same\n");
2429 } else {
2430 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2431 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2434 if (strequal(devmode->formname, devmode2->formname)) {
2435 torture_warning(tctx, "formname is the same\n");
2436 } else {
2437 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2438 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2441 if (devmode->copies == devmode2->copies) {
2442 torture_warning(tctx, "copies are the same\n");
2443 } else {
2444 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2445 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2448 test_ClosePrinter(tctx, b, &handle_devmode);
2450 return true;
2454 * wrapper call that saves original devmode, runs tests, and restores devmode
2457 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2458 struct dcerpc_pipe *p,
2459 struct policy_handle *handle,
2460 const char *name,
2461 struct spoolss_DeviceMode *addprinter_devmode)
2463 union spoolss_PrinterInfo info;
2464 struct spoolss_DeviceMode *devmode;
2465 bool ret = true;
2466 struct dcerpc_binding_handle *b = p->binding_handle;
2468 torture_comment(tctx, "Testing Printer Devicemodes\n");
2470 /* save original devmode */
2472 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2473 "failed to get initial global devicemode");
2475 devmode = info.info8.devmode;
2477 if (devmode && devmode->size == 0) {
2478 torture_fail(tctx,
2479 "devmode of zero size!");
2482 if (addprinter_devmode) {
2483 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2484 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2488 /* run tests */
2490 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2492 /* restore original devmode */
2494 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2495 "failed to restore initial global device mode");
2497 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2498 ret ? "succeeded" : "failed");
2501 return ret;
2504 bool test_ClosePrinter(struct torture_context *tctx,
2505 struct dcerpc_binding_handle *b,
2506 struct policy_handle *handle)
2508 NTSTATUS status;
2509 struct spoolss_ClosePrinter r;
2511 r.in.handle = handle;
2512 r.out.handle = handle;
2514 torture_comment(tctx, "Testing ClosePrinter\n");
2516 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2517 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2518 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2520 return true;
2523 static bool test_GetForm_args(struct torture_context *tctx,
2524 struct dcerpc_binding_handle *b,
2525 struct policy_handle *handle,
2526 const char *form_name,
2527 uint32_t level,
2528 union spoolss_FormInfo *info_p)
2530 NTSTATUS status;
2531 struct spoolss_GetForm r;
2532 uint32_t needed;
2534 r.in.handle = handle;
2535 r.in.form_name = form_name;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2541 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2543 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2544 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2546 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2547 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2548 r.in.buffer = &blob;
2549 r.in.offered = needed;
2550 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2551 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2553 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2555 torture_assert(tctx, r.out.info, "No form info returned");
2558 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2560 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2562 if (info_p) {
2563 *info_p = *r.out.info;
2566 return true;
2569 static bool test_GetForm(struct torture_context *tctx,
2570 struct dcerpc_binding_handle *b,
2571 struct policy_handle *handle,
2572 const char *form_name,
2573 uint32_t level)
2575 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2578 static bool test_EnumForms(struct torture_context *tctx,
2579 struct dcerpc_binding_handle *b,
2580 struct policy_handle *handle,
2581 bool print_server,
2582 uint32_t level,
2583 uint32_t *count_p,
2584 union spoolss_FormInfo **info_p)
2586 struct spoolss_EnumForms r;
2587 uint32_t needed;
2588 uint32_t count;
2589 union spoolss_FormInfo *info;
2591 r.in.handle = handle;
2592 r.in.level = level;
2593 r.in.buffer = NULL;
2594 r.in.offered = 0;
2595 r.out.needed = &needed;
2596 r.out.count = &count;
2597 r.out.info = &info;
2599 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2601 torture_assert_ntstatus_ok(tctx,
2602 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2603 "EnumForms failed");
2605 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL))) {
2606 torture_skip(tctx, "EnumForms level 2 not supported");
2609 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_INVALID_HANDLE)) {
2610 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2613 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2614 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2615 r.in.buffer = &blob;
2616 r.in.offered = needed;
2618 torture_assert_ntstatus_ok(tctx,
2619 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2620 "EnumForms failed");
2622 torture_assert(tctx, info, "No forms returned");
2625 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2627 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2629 if (info_p) {
2630 *info_p = info;
2632 if (count_p) {
2633 *count_p = count;
2636 return true;
2639 static bool test_EnumForms_all(struct torture_context *tctx,
2640 struct dcerpc_binding_handle *b,
2641 struct policy_handle *handle,
2642 bool print_server)
2644 uint32_t levels[] = { 1, 2 };
2645 int i, j;
2647 for (i=0; i<ARRAY_SIZE(levels); i++) {
2649 uint32_t count = 0;
2650 union spoolss_FormInfo *info = NULL;
2652 torture_assert(tctx,
2653 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2654 "failed to enum forms");
2656 for (j = 0; j < count; j++) {
2657 if (!print_server) {
2658 torture_assert(tctx,
2659 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2660 "failed to get form");
2665 return true;
2668 static bool test_EnumForms_find_one(struct torture_context *tctx,
2669 struct dcerpc_binding_handle *b,
2670 struct policy_handle *handle,
2671 bool print_server,
2672 const char *form_name)
2674 union spoolss_FormInfo *info = NULL;
2675 uint32_t count = 0;
2676 bool found = false;
2677 int i;
2679 torture_assert(tctx,
2680 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2681 "failed to enumerate forms");
2683 for (i=0; i<count; i++) {
2684 if (strequal(form_name, info[i].info1.form_name)) {
2685 found = true;
2686 break;
2690 return found;
2693 static bool test_DeleteForm(struct torture_context *tctx,
2694 struct dcerpc_binding_handle *b,
2695 struct policy_handle *handle,
2696 const char *form_name,
2697 WERROR expected_result)
2699 struct spoolss_DeleteForm r;
2701 r.in.handle = handle;
2702 r.in.form_name = form_name;
2704 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2706 torture_assert_ntstatus_ok(tctx,
2707 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2708 "DeleteForm failed");
2709 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2710 "DeleteForm gave unexpected result");
2711 if (W_ERROR_IS_OK(r.out.result)) {
2712 torture_assert_ntstatus_ok(tctx,
2713 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2714 "2nd DeleteForm failed");
2715 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2716 "2nd DeleteForm failed");
2719 return true;
2722 static bool test_AddForm(struct torture_context *tctx,
2723 struct dcerpc_binding_handle *b,
2724 struct policy_handle *handle,
2725 uint32_t level,
2726 union spoolss_AddFormInfo *info,
2727 WERROR expected_result)
2729 struct spoolss_AddForm r;
2730 struct spoolss_AddFormInfoCtr info_ctr;
2732 info_ctr.level = level;
2733 info_ctr.info = *info;
2735 if (level != 1) {
2736 torture_skip(tctx, "only level 1 supported");
2739 r.in.handle = handle;
2740 r.in.info_ctr = &info_ctr;
2742 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2743 r.in.info_ctr->info.info1->form_name, level,
2744 r.in.info_ctr->info.info1->flags);
2746 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2747 "AddForm failed");
2748 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2749 "AddForm gave unexpected result");
2751 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2752 "2nd AddForm failed");
2753 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAMETER)) {
2754 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
2755 "2nd AddForm gave unexpected result");
2756 } else {
2757 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2758 "2nd AddForm gave unexpected result");
2761 return true;
2764 static bool test_SetForm(struct torture_context *tctx,
2765 struct dcerpc_binding_handle *b,
2766 struct policy_handle *handle,
2767 const char *form_name,
2768 uint32_t level,
2769 union spoolss_AddFormInfo *info)
2771 struct spoolss_SetForm r;
2772 struct spoolss_AddFormInfoCtr info_ctr;
2774 info_ctr.level = level;
2775 info_ctr.info = *info;
2777 r.in.handle = handle;
2778 r.in.form_name = form_name;
2779 r.in.info_ctr = &info_ctr;
2781 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2782 form_name, level);
2784 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2785 "SetForm failed");
2787 torture_assert_werr_ok(tctx, r.out.result,
2788 "SetForm failed");
2790 return true;
2793 static bool test_GetForm_winreg(struct torture_context *tctx,
2794 struct dcerpc_binding_handle *b,
2795 struct policy_handle *handle,
2796 const char *key_name,
2797 const char *form_name,
2798 enum winreg_Type *w_type,
2799 uint32_t *w_size,
2800 uint32_t *w_length,
2801 uint8_t **w_data);
2803 static bool test_Forms_args(struct torture_context *tctx,
2804 struct dcerpc_binding_handle *b,
2805 struct policy_handle *handle,
2806 bool print_server,
2807 const char *printer_name,
2808 struct dcerpc_binding_handle *winreg_handle,
2809 struct policy_handle *hive_handle,
2810 const char *form_name,
2811 struct spoolss_AddFormInfo1 *info1,
2812 WERROR expected_add_result,
2813 WERROR expected_delete_result)
2815 union spoolss_FormInfo info;
2816 union spoolss_AddFormInfo add_info;
2818 enum winreg_Type w_type;
2819 uint32_t w_size;
2820 uint32_t w_length;
2821 uint8_t *w_data;
2823 add_info.info1 = info1;
2825 torture_assert(tctx,
2826 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2827 "failed to add form");
2829 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2831 struct spoolss_FormInfo1 i1;
2833 torture_assert(tctx,
2834 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2835 "failed to get form via winreg");
2837 i1.size.width = IVAL(w_data, 0);
2838 i1.size.height = IVAL(w_data, 4);
2839 i1.area.left = IVAL(w_data, 8);
2840 i1.area.top = IVAL(w_data, 12);
2841 i1.area.right = IVAL(w_data, 16);
2842 i1.area.bottom = IVAL(w_data, 20);
2843 /* skip index here */
2844 i1.flags = IVAL(w_data, 28);
2846 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2847 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2848 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2849 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2850 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2851 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2852 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2853 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2854 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2855 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2858 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2859 torture_assert(tctx,
2860 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2861 "failed to get added form");
2863 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2864 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2865 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2866 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2867 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2868 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2869 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2871 if (winreg_handle && hive_handle) {
2873 struct spoolss_FormInfo1 i1;
2875 i1.size.width = IVAL(w_data, 0);
2876 i1.size.height = IVAL(w_data, 4);
2877 i1.area.left = IVAL(w_data, 8);
2878 i1.area.top = IVAL(w_data, 12);
2879 i1.area.right = IVAL(w_data, 16);
2880 i1.area.bottom = IVAL(w_data, 20);
2881 /* skip index here */
2882 i1.flags = IVAL(w_data, 28);
2884 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2885 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2886 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2887 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2888 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2889 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2890 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2893 add_info.info1->size.width = 1234;
2895 torture_assert(tctx,
2896 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2897 "failed to set form");
2898 torture_assert(tctx,
2899 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2900 "failed to get set form");
2902 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2905 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAMETER)) {
2906 torture_assert(tctx,
2907 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2908 "Newly added form not found in enum call");
2911 torture_assert(tctx,
2912 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2913 "failed to delete form");
2915 return true;
2918 static bool test_Forms(struct torture_context *tctx,
2919 struct dcerpc_binding_handle *b,
2920 struct policy_handle *handle,
2921 bool print_server,
2922 const char *printer_name,
2923 struct dcerpc_binding_handle *winreg_handle,
2924 struct policy_handle *hive_handle)
2926 const struct spoolss_FormSize size = {
2927 .width = 50,
2928 .height = 25
2930 const struct spoolss_FormArea area = {
2931 .left = 5,
2932 .top = 10,
2933 .right = 45,
2934 .bottom = 15
2936 int i;
2938 struct {
2939 struct spoolss_AddFormInfo1 info1;
2940 WERROR expected_add_result;
2941 WERROR expected_delete_result;
2942 } forms[] = {
2944 .info1 = {
2945 .flags = SPOOLSS_FORM_USER,
2946 .form_name = "testform_user",
2947 .size = size,
2948 .area = area,
2950 .expected_add_result = WERR_OK,
2951 .expected_delete_result = WERR_OK
2954 weird, we can add a builtin form but we can never remove it
2955 again - gd
2958 .info1 = {
2959 .flags = SPOOLSS_FORM_BUILTIN,
2960 .form_name = "testform_builtin",
2961 .size = size,
2962 .area = area,
2964 .expected_add_result = WERR_OK,
2965 .expected_delete_result = WERR_INVALID_PARAMETER,
2969 .info1 = {
2970 .flags = SPOOLSS_FORM_PRINTER,
2971 .form_name = "testform_printer",
2972 .size = size,
2973 .area = area,
2975 .expected_add_result = WERR_OK,
2976 .expected_delete_result = WERR_OK
2979 .info1 = {
2980 .flags = SPOOLSS_FORM_USER,
2981 .form_name = "Letter",
2982 .size = size,
2983 .area = area,
2985 .expected_add_result = WERR_FILE_EXISTS,
2986 .expected_delete_result = WERR_INVALID_PARAMETER
2989 .info1 = {
2990 .flags = SPOOLSS_FORM_BUILTIN,
2991 .form_name = "Letter",
2992 .size = size,
2993 .area = area,
2995 .expected_add_result = WERR_FILE_EXISTS,
2996 .expected_delete_result = WERR_INVALID_PARAMETER
2999 .info1 = {
3000 .flags = SPOOLSS_FORM_PRINTER,
3001 .form_name = "Letter",
3002 .size = size,
3003 .area = area,
3005 .expected_add_result = WERR_FILE_EXISTS,
3006 .expected_delete_result = WERR_INVALID_PARAMETER
3009 .info1 = {
3010 .flags = 12345,
3011 .form_name = "invalid_flags",
3012 .size = size,
3013 .area = area,
3015 .expected_add_result = WERR_INVALID_PARAMETER,
3016 .expected_delete_result = WERR_INVALID_FORM_NAME
3021 for (i=0; i < ARRAY_SIZE(forms); i++) {
3022 torture_assert(tctx,
3023 test_Forms_args(tctx, b, handle, print_server, printer_name,
3024 winreg_handle, hive_handle,
3025 forms[i].info1.form_name,
3026 &forms[i].info1,
3027 forms[i].expected_add_result,
3028 forms[i].expected_delete_result),
3029 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
3032 return true;
3035 static bool test_EnumPorts_old(struct torture_context *tctx,
3036 void *private_data)
3038 struct test_spoolss_context *ctx =
3039 talloc_get_type_abort(private_data, struct test_spoolss_context);
3041 NTSTATUS status;
3042 struct spoolss_EnumPorts r;
3043 uint32_t needed;
3044 uint32_t count;
3045 union spoolss_PortInfo *info;
3046 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3047 struct dcerpc_binding_handle *b = p->binding_handle;
3049 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
3050 dcerpc_server_name(p));
3051 r.in.level = 2;
3052 r.in.buffer = NULL;
3053 r.in.offered = 0;
3054 r.out.needed = &needed;
3055 r.out.count = &count;
3056 r.out.info = &info;
3058 torture_comment(tctx, "Testing EnumPorts\n");
3060 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3062 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3064 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3065 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3066 r.in.buffer = &blob;
3067 r.in.offered = needed;
3069 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3070 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3071 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3073 torture_assert(tctx, info, "No ports returned");
3076 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3078 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3080 return true;
3083 static bool test_AddPort(struct torture_context *tctx,
3084 void *private_data)
3086 struct test_spoolss_context *ctx =
3087 talloc_get_type_abort(private_data, struct test_spoolss_context);
3089 NTSTATUS status;
3090 struct spoolss_AddPort r;
3091 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3092 struct dcerpc_binding_handle *b = p->binding_handle;
3094 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3095 dcerpc_server_name(p));
3096 r.in.unknown = 0;
3097 r.in.monitor_name = "foo";
3099 torture_comment(tctx, "Testing AddPort\n");
3101 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3103 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3105 /* win2k3 returns WERR_NOT_SUPPORTED */
3107 #if 0
3109 if (!W_ERROR_IS_OK(r.out.result)) {
3110 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3111 return false;
3114 #endif
3116 return true;
3119 static bool test_GetJob_args(struct torture_context *tctx,
3120 struct dcerpc_binding_handle *b,
3121 struct policy_handle *handle,
3122 uint32_t job_id,
3123 uint32_t level,
3124 union spoolss_JobInfo *info_p)
3126 NTSTATUS status;
3127 struct spoolss_GetJob r;
3128 union spoolss_JobInfo info;
3129 uint32_t needed;
3131 r.in.handle = handle;
3132 r.in.job_id = job_id;
3133 r.in.level = level;
3134 r.in.buffer = NULL;
3135 r.in.offered = 0;
3136 r.out.needed = &needed;
3137 r.out.info = &info;
3139 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3141 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3142 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3143 if (level == 0) {
3144 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "Unexpected return code");
3147 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3148 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3149 r.in.buffer = &blob;
3150 r.in.offered = needed;
3152 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3153 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3156 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3157 torture_assert(tctx, r.out.info, "No job info returned");
3159 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3161 if (info_p) {
3162 *info_p = *r.out.info;
3165 return true;
3168 #if 0
3169 static bool test_GetJob(struct torture_context *tctx,
3170 struct dcerpc_binding_handle *b,
3171 struct policy_handle *handle,
3172 uint32_t job_id)
3174 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3175 uint32_t i;
3177 for (i=0; i < ARRAY_SIZE(levels); i++) {
3178 torture_assert(tctx,
3179 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3180 "GetJob failed");
3183 return true;
3185 #endif
3187 static bool test_SetJob(struct torture_context *tctx,
3188 struct dcerpc_binding_handle *b,
3189 struct policy_handle *handle,
3190 uint32_t job_id,
3191 struct spoolss_JobInfoContainer *ctr,
3192 enum spoolss_JobControl command)
3194 NTSTATUS status;
3195 struct spoolss_SetJob r;
3197 r.in.handle = handle;
3198 r.in.job_id = job_id;
3199 r.in.ctr = ctr;
3200 r.in.command = command;
3202 switch (command) {
3203 case SPOOLSS_JOB_CONTROL_PAUSE:
3204 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3205 break;
3206 case SPOOLSS_JOB_CONTROL_RESUME:
3207 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3208 break;
3209 case SPOOLSS_JOB_CONTROL_CANCEL:
3210 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3211 break;
3212 case SPOOLSS_JOB_CONTROL_RESTART:
3213 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3214 break;
3215 case SPOOLSS_JOB_CONTROL_DELETE:
3216 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3217 break;
3218 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3219 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3220 break;
3221 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3222 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3223 break;
3224 case SPOOLSS_JOB_CONTROL_RETAIN:
3225 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3226 break;
3227 case SPOOLSS_JOB_CONTROL_RELEASE:
3228 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3229 break;
3230 default:
3231 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3232 break;
3235 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3236 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3237 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3239 return true;
3242 static bool test_AddJob(struct torture_context *tctx,
3243 struct dcerpc_binding_handle *b,
3244 struct policy_handle *handle)
3246 NTSTATUS status;
3247 struct spoolss_AddJob r;
3248 uint32_t needed;
3250 r.in.level = 0;
3251 r.in.handle = handle;
3252 r.in.offered = 0;
3253 r.out.needed = &needed;
3254 r.in.buffer = r.out.buffer = NULL;
3256 torture_comment(tctx, "Testing AddJob\n");
3258 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3259 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3260 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "AddJob failed");
3262 r.in.level = 1;
3264 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3265 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3266 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER, "AddJob failed");
3268 return true;
3272 static bool test_EnumJobs_args(struct torture_context *tctx,
3273 struct dcerpc_binding_handle *b,
3274 struct policy_handle *handle,
3275 uint32_t level,
3276 WERROR werr_expected,
3277 uint32_t *count_p,
3278 union spoolss_JobInfo **info_p)
3280 NTSTATUS status;
3281 struct spoolss_EnumJobs r;
3282 uint32_t needed;
3283 uint32_t count;
3284 union spoolss_JobInfo *info;
3286 r.in.handle = handle;
3287 r.in.firstjob = 0;
3288 r.in.numjobs = 0xffffffff;
3289 r.in.level = level;
3290 r.in.buffer = NULL;
3291 r.in.offered = 0;
3292 r.out.needed = &needed;
3293 r.out.count = &count;
3294 r.out.info = &info;
3296 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3298 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3300 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3302 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3303 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3304 r.in.buffer = &blob;
3305 r.in.offered = needed;
3307 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3309 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3310 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3311 "EnumJobs failed");
3312 torture_assert(tctx, info, "No jobs returned");
3314 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3316 } else {
3317 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3318 "EnumJobs failed");
3321 if (count_p) {
3322 *count_p = count;
3324 if (info_p) {
3325 *info_p = info;
3328 return true;
3331 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3332 struct dcerpc_binding_handle *b,
3333 struct policy_handle *handle,
3334 uint32_t job_id)
3336 struct spoolss_EnumJobNamedProperties r;
3337 uint32_t pcProperties = 0;
3338 struct spoolss_PrintNamedProperty *ppProperties = NULL;
3340 r.in.hPrinter = handle;
3341 r.in.JobId = job_id;
3342 r.out.pcProperties = &pcProperties;
3343 r.out.ppProperties = &ppProperties;
3345 torture_comment(tctx, "Testing EnumJobNamedProperties(%d)\n", job_id);
3347 torture_assert_ntstatus_ok(tctx,
3348 dcerpc_spoolss_EnumJobNamedProperties_r(b, tctx, &r),
3349 "spoolss_EnumJobNamedProperties failed");
3350 torture_assert_werr_ok(tctx, r.out.result,
3351 "spoolss_EnumJobNamedProperties failed");
3353 return true;
3356 static bool test_JobPropertySet(struct torture_context *tctx,
3357 struct dcerpc_binding_handle *b,
3358 struct policy_handle *handle,
3359 uint32_t job_id,
3360 struct spoolss_PrintNamedProperty *property)
3362 struct spoolss_SetJobNamedProperty r;
3364 r.in.hPrinter = handle;
3365 r.in.JobId = job_id;
3366 r.in.pProperty = property;
3368 torture_comment(tctx, "Testing SetJobNamedProperty(%d) %s - %d\n",
3369 job_id, property->propertyName,
3370 property->propertyValue.ePropertyType);
3372 torture_assert_ntstatus_ok(tctx,
3373 dcerpc_spoolss_SetJobNamedProperty_r(b, tctx, &r),
3374 "spoolss_SetJobNamedProperty failed");
3375 torture_assert_werr_ok(tctx, r.out.result,
3376 "spoolss_SetJobNamedProperty failed");
3378 return true;
3381 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3382 struct dcerpc_binding_handle *b,
3383 struct policy_handle *handle,
3384 uint32_t job_id,
3385 const char *property_name,
3386 struct spoolss_PrintPropertyValue *value)
3388 struct spoolss_GetJobNamedPropertyValue r;
3390 r.in.hPrinter = handle;
3391 r.in.JobId = job_id;
3392 r.in.pszName = property_name;
3393 r.out.pValue = value;
3395 torture_comment(tctx, "Testing GetJobNamedPropertyValue(%d) %s\n",
3396 job_id, property_name);
3398 torture_assert_ntstatus_ok(tctx,
3399 dcerpc_spoolss_GetJobNamedPropertyValue_r(b, tctx, &r),
3400 "spoolss_GetJobNamedPropertyValue failed");
3401 torture_assert_werr_ok(tctx, r.out.result,
3402 "spoolss_GetJobNamedPropertyValue failed");
3404 return true;
3407 static bool test_JobPropertyDelete(struct torture_context *tctx,
3408 struct dcerpc_binding_handle *b,
3409 struct policy_handle *handle,
3410 uint32_t job_id,
3411 const char *property_name)
3413 struct spoolss_DeleteJobNamedProperty r;
3415 r.in.hPrinter = handle;
3416 r.in.JobId = job_id;
3417 r.in.pszName = property_name;
3419 torture_comment(tctx, "Testing DeleteJobNamedProperty(%d) %s\n",
3420 job_id, property_name);
3422 torture_assert_ntstatus_ok(tctx,
3423 dcerpc_spoolss_DeleteJobNamedProperty_r(b, tctx, &r),
3424 "spoolss_DeleteJobNamedProperty failed");
3425 torture_assert_werr_ok(tctx, r.out.result,
3426 "spoolss_DeleteJobNamedProperty failed");
3428 return true;
3431 static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
3432 struct dcerpc_binding_handle *b,
3433 struct policy_handle *handle,
3434 const char *document_name,
3435 const char *datatype,
3436 uint32_t *job_id)
3438 NTSTATUS status;
3439 struct spoolss_StartDocPrinter s;
3440 struct spoolss_DocumentInfoCtr info_ctr;
3441 struct spoolss_DocumentInfo1 info1;
3442 struct spoolss_StartPagePrinter sp;
3443 struct spoolss_WritePrinter w;
3444 struct spoolss_EndPagePrinter ep;
3445 struct spoolss_EndDocPrinter e;
3446 int i;
3447 uint32_t num_written;
3449 torture_comment(tctx, "Testing StartDocPrinter\n");
3451 s.in.handle = handle;
3452 s.in.info_ctr = &info_ctr;
3453 s.out.job_id = job_id;
3455 info1.document_name = document_name;
3456 info1.output_file = NULL;
3457 info1.datatype = datatype;
3459 info_ctr.level = 1;
3460 info_ctr.info.info1 = &info1;
3462 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3463 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3464 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3466 for (i=1; i < 4; i++) {
3467 union spoolss_JobInfo ginfo;
3468 bool ok;
3470 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3472 sp.in.handle = handle;
3474 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3475 torture_assert_ntstatus_ok(tctx, status,
3476 "dcerpc_spoolss_StartPagePrinter failed");
3477 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3479 ok = test_GetJob_args(tctx, b, handle, *job_id, 1, &ginfo);
3480 if (!ok) {
3481 torture_comment(tctx, "test_GetJob failed for JobId[%d]\n", *job_id);
3484 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3486 w.in.handle = handle;
3487 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3488 w.out.num_written = &num_written;
3490 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3491 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3492 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3494 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3496 ep.in.handle = handle;
3498 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3499 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3500 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3503 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3505 e.in.handle = handle;
3507 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3508 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3509 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3511 return true;
3514 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3515 struct dcerpc_binding_handle *b,
3516 struct policy_handle *handle,
3517 const char *document_name,
3518 uint32_t *job_id)
3520 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
3522 return true;
3525 static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
3526 struct dcerpc_binding_handle *b,
3527 struct policy_handle *handle,
3528 const char *document_name,
3529 uint32_t *job_id)
3531 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
3533 return true;
3537 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3538 struct dcerpc_binding_handle *b,
3539 struct policy_handle *handle,
3540 uint32_t num_jobs,
3541 uint32_t *job_ids)
3543 uint32_t count;
3544 union spoolss_JobInfo *info = NULL;
3545 int i;
3547 torture_assert(tctx,
3548 test_AddJob(tctx, b, handle),
3549 "AddJob failed");
3551 torture_assert(tctx,
3552 test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
3553 "EnumJobs level 1 failed");
3555 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3557 for (i=0; i < num_jobs; i++) {
3558 union spoolss_JobInfo ginfo;
3559 const char *document_name;
3560 const char *new_document_name = "any_other_docname";
3561 struct spoolss_JobInfoContainer ctr;
3562 struct spoolss_SetJobInfo1 info1;
3564 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3566 torture_assert(tctx,
3567 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3568 "failed to call test_GetJob");
3570 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3572 document_name = ginfo.info1.document_name;
3574 info1.job_id = ginfo.info1.job_id;
3575 info1.printer_name = ginfo.info1.printer_name;
3576 info1.server_name = ginfo.info1.server_name;
3577 info1.user_name = ginfo.info1.user_name;
3578 info1.document_name = new_document_name;
3579 info1.data_type = ginfo.info1.data_type;
3580 info1.text_status = ginfo.info1.text_status;
3581 info1.status = ginfo.info1.status;
3582 info1.priority = ginfo.info1.priority;
3583 info1.position = ginfo.info1.position;
3584 info1.total_pages = ginfo.info1.total_pages;
3585 info1.pages_printed = ginfo.info1.pages_printed;
3586 info1.submitted = ginfo.info1.submitted;
3588 ctr.level = 1;
3589 ctr.info.info1 = &info1;
3591 torture_assert(tctx,
3592 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3593 "failed to call test_SetJob level 1");
3595 torture_assert(tctx,
3596 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3597 "failed to call test_GetJob");
3599 if (strequal(ginfo.info1.document_name, document_name)) {
3600 torture_warning(tctx,
3601 "document_name did *NOT* change from '%s' to '%s'\n",
3602 document_name, new_document_name);
3606 for (i=0; i < num_jobs; i++) {
3607 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3608 torture_warning(tctx, "failed to pause printjob\n");
3610 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3611 torture_warning(tctx, "failed to resume printjob\n");
3615 return true;
3618 static bool test_DoPrintTest(struct torture_context *tctx,
3619 struct dcerpc_binding_handle *b,
3620 struct policy_handle *handle)
3622 bool ret = true;
3623 uint32_t num_jobs = 8;
3624 uint32_t *job_ids;
3625 int i;
3627 torture_comment(tctx, "Testing real print operations\n");
3629 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3631 for (i=0; i < num_jobs; i++) {
3632 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3635 for (i=0; i < num_jobs; i++) {
3636 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3639 for (i=0; i < num_jobs; i++) {
3640 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
3643 for (i=0; i < num_jobs; i++) {
3644 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3647 if (ret == true) {
3648 torture_comment(tctx, "real print operations test succeeded\n\n");
3651 return ret;
3654 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3655 struct dcerpc_binding_handle *b,
3656 struct policy_handle *handle)
3658 bool ret = true;
3659 uint32_t num_jobs = 8;
3660 uint32_t *job_ids;
3661 int i;
3662 torture_comment(tctx, "Testing real print operations (extended)\n");
3664 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3666 for (i=0; i < num_jobs; i++) {
3667 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3670 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3672 for (i=0; i < num_jobs; i++) {
3673 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3676 if (ret == true) {
3677 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3680 return ret;
3683 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3684 struct spoolss_PrintPropertyValue *got,
3685 struct spoolss_PrintNamedProperty *exp)
3687 torture_assert_int_equal(tctx,
3688 got->ePropertyType,
3689 exp->propertyValue.ePropertyType,
3690 "ePropertyType");
3692 switch (exp->propertyValue.ePropertyType) {
3693 case kRpcPropertyTypeString:
3694 torture_assert_str_equal(tctx,
3695 got->value.propertyString,
3696 exp->propertyValue.value.propertyString,
3697 "propertyString");
3698 break;
3699 case kRpcPropertyTypeInt32:
3700 torture_assert_int_equal(tctx,
3701 got->value.propertyInt32,
3702 exp->propertyValue.value.propertyInt32,
3703 "propertyInt32");
3704 break;
3705 case kRpcPropertyTypeInt64:
3706 torture_assert_u64_equal(tctx,
3707 got->value.propertyInt64,
3708 exp->propertyValue.value.propertyInt64,
3709 "propertyInt64");
3710 break;
3711 case kRpcPropertyTypeByte:
3712 torture_assert_int_equal(tctx,
3713 got->value.propertyByte,
3714 exp->propertyValue.value.propertyByte,
3715 "propertyByte");
3716 break;
3717 case kRpcPropertyTypeBuffer:
3718 torture_assert_int_equal(tctx,
3719 got->value.propertyBlob.cbBuf,
3720 exp->propertyValue.value.propertyBlob.cbBuf,
3721 "propertyBlob.cbBuf");
3722 torture_assert_mem_equal(tctx,
3723 got->value.propertyBlob.pBuf,
3724 exp->propertyValue.value.propertyBlob.pBuf,
3725 exp->propertyValue.value.propertyBlob.cbBuf,
3726 "propertyBlob.pBuf");
3728 break;
3732 return true;
3735 static bool test_JobPrintProperties(struct torture_context *tctx,
3736 struct dcerpc_binding_handle *b,
3737 struct policy_handle *handle,
3738 uint32_t job_id)
3740 struct spoolss_PrintNamedProperty in;
3741 struct spoolss_PrintPropertyValue out;
3742 int i;
3743 DATA_BLOB blob = data_blob_string_const("blob");
3744 struct {
3745 const char *property_name;
3746 enum spoolss_EPrintPropertyType type;
3747 union spoolss_PrintPropertyValueUnion value;
3748 WERROR expected_result;
3749 } tests[] = {
3751 .property_name = "torture_property_string",
3752 .type = kRpcPropertyTypeString,
3753 .value.propertyString = "torture_property_value_string",
3755 .property_name = "torture_property_int32",
3756 .type = kRpcPropertyTypeInt32,
3757 .value.propertyInt32 = 42,
3759 .property_name = "torture_property_int64",
3760 .type = kRpcPropertyTypeInt64,
3761 .value.propertyInt64 = 0xaffe,
3763 .property_name = "torture_property_byte",
3764 .type = kRpcPropertyTypeByte,
3765 .value.propertyByte = 0xab,
3767 .property_name = "torture_property_buffer",
3768 .type = kRpcPropertyTypeBuffer,
3769 .value.propertyBlob.cbBuf = blob.length,
3770 .value.propertyBlob.pBuf = blob.data,
3774 torture_assert(tctx,
3775 test_JobPropertiesEnum(tctx, b, handle, job_id),
3776 "failed to enum properties");
3778 for (i=0; i <ARRAY_SIZE(tests); i++) {
3780 in.propertyName = tests[i].property_name;
3781 in.propertyValue.ePropertyType = tests[i].type;
3782 in.propertyValue.value = tests[i].value;
3784 torture_assert(tctx,
3785 test_JobPropertySet(tctx, b, handle, job_id, &in),
3786 "failed to set property");
3788 torture_assert(tctx,
3789 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3790 "failed to get property");
3792 torture_assert(tctx,
3793 test_JobPrintProperties_equal(tctx, &out, &in),
3794 "property unequal");
3796 torture_assert(tctx,
3797 test_JobPropertiesEnum(tctx, b, handle, job_id),
3798 "failed to enum properties");
3800 torture_assert(tctx,
3801 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3802 "failed to delete job property");
3805 torture_assert(tctx,
3806 test_JobPropertiesEnum(tctx, b, handle, job_id),
3807 "failed to enum properties");
3809 return true;
3812 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3813 struct dcerpc_binding_handle *b,
3814 struct policy_handle *handle)
3816 uint32_t num_jobs = 8;
3817 uint32_t *job_ids;
3818 int i;
3819 torture_comment(tctx, "Testing real print operations (properties)\n");
3821 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3823 for (i=0; i < num_jobs; i++) {
3824 torture_assert(tctx,
3825 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3826 "failed to create print job");
3829 for (i=0; i < num_jobs; i++) {
3830 torture_assert(tctx,
3831 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3832 "failed to test job properties");
3836 for (i=0; i < num_jobs; i++) {
3837 torture_assert(tctx,
3838 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3839 "failed to delete printjob");
3842 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3844 return true;
3847 static bool test_PausePrinter(struct torture_context *tctx,
3848 struct dcerpc_binding_handle *b,
3849 struct policy_handle *handle)
3851 NTSTATUS status;
3852 struct spoolss_SetPrinter r;
3853 struct spoolss_SetPrinterInfoCtr info_ctr;
3854 struct spoolss_DevmodeContainer devmode_ctr;
3855 struct sec_desc_buf secdesc_ctr;
3857 info_ctr.level = 0;
3858 info_ctr.info.info0 = NULL;
3860 ZERO_STRUCT(devmode_ctr);
3861 ZERO_STRUCT(secdesc_ctr);
3863 r.in.handle = handle;
3864 r.in.info_ctr = &info_ctr;
3865 r.in.devmode_ctr = &devmode_ctr;
3866 r.in.secdesc_ctr = &secdesc_ctr;
3867 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3869 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3871 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3873 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3875 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3877 return true;
3880 static bool test_ResumePrinter(struct torture_context *tctx,
3881 struct dcerpc_binding_handle *b,
3882 struct policy_handle *handle)
3884 NTSTATUS status;
3885 struct spoolss_SetPrinter r;
3886 struct spoolss_SetPrinterInfoCtr info_ctr;
3887 struct spoolss_DevmodeContainer devmode_ctr;
3888 struct sec_desc_buf secdesc_ctr;
3890 info_ctr.level = 0;
3891 info_ctr.info.info0 = NULL;
3893 ZERO_STRUCT(devmode_ctr);
3894 ZERO_STRUCT(secdesc_ctr);
3896 r.in.handle = handle;
3897 r.in.info_ctr = &info_ctr;
3898 r.in.devmode_ctr = &devmode_ctr;
3899 r.in.secdesc_ctr = &secdesc_ctr;
3900 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3902 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3904 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3906 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3908 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3910 return true;
3913 static bool test_printer_purge(struct torture_context *tctx,
3914 struct dcerpc_binding_handle *b,
3915 struct policy_handle *handle)
3917 NTSTATUS status;
3918 struct spoolss_SetPrinter r;
3919 struct spoolss_SetPrinterInfoCtr info_ctr;
3920 struct spoolss_DevmodeContainer devmode_ctr;
3921 struct sec_desc_buf secdesc_ctr;
3923 info_ctr.level = 0;
3924 info_ctr.info.info0 = NULL;
3926 ZERO_STRUCT(devmode_ctr);
3927 ZERO_STRUCT(secdesc_ctr);
3929 r.in.handle = handle;
3930 r.in.info_ctr = &info_ctr;
3931 r.in.devmode_ctr = &devmode_ctr;
3932 r.in.secdesc_ctr = &secdesc_ctr;
3933 r.in.command = SPOOLSS_PRINTER_CONTROL_PURGE;
3935 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3937 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3938 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3939 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3941 return true;
3944 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3945 struct dcerpc_binding_handle *b,
3946 struct policy_handle *handle,
3947 const char *value_name,
3948 enum winreg_Type *expected_type,
3949 enum winreg_Type *type_p,
3950 uint8_t **data_p,
3951 uint32_t *needed_p)
3953 NTSTATUS status;
3954 struct spoolss_GetPrinterData r;
3955 uint32_t needed;
3956 enum winreg_Type type;
3957 union spoolss_PrinterData data;
3959 r.in.handle = handle;
3960 r.in.value_name = value_name;
3961 r.in.offered = 0;
3962 r.out.needed = &needed;
3963 r.out.type = &type;
3964 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3966 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3968 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3969 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3971 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3972 if (expected_type) {
3973 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3975 r.in.offered = needed;
3976 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3977 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3978 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3981 torture_assert_werr_ok(tctx, r.out.result,
3982 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3984 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3986 if (type_p) {
3987 *type_p = type;
3990 if (data_p) {
3991 *data_p = r.out.data;
3994 if (needed_p) {
3995 *needed_p = needed;
3998 return true;
4001 static bool test_GetPrinterData(struct torture_context *tctx,
4002 struct dcerpc_binding_handle *b,
4003 struct policy_handle *handle,
4004 const char *value_name,
4005 enum winreg_Type *type_p,
4006 uint8_t **data_p,
4007 uint32_t *needed_p)
4009 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
4010 NULL, type_p, data_p, needed_p);
4013 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
4014 struct dcerpc_pipe *p,
4015 struct policy_handle *handle,
4016 const char *key_name,
4017 const char *value_name,
4018 enum winreg_Type *expected_type,
4019 enum winreg_Type *type_p,
4020 uint8_t **data_p,
4021 uint32_t *needed_p)
4023 NTSTATUS status;
4024 struct spoolss_GetPrinterDataEx r;
4025 enum winreg_Type type;
4026 uint32_t needed;
4027 union spoolss_PrinterData data;
4028 struct dcerpc_binding_handle *b = p->binding_handle;
4030 r.in.handle = handle;
4031 r.in.key_name = key_name;
4032 r.in.value_name = value_name;
4033 r.in.offered = 0;
4034 r.out.type = &type;
4035 r.out.needed = &needed;
4036 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4038 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
4039 r.in.key_name, r.in.value_name);
4041 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4042 if (!NT_STATUS_IS_OK(status)) {
4043 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
4044 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
4046 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4049 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4050 if (expected_type) {
4051 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
4053 r.in.offered = needed;
4054 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4055 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4056 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4059 torture_assert_werr_ok(tctx, r.out.result,
4060 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
4062 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
4064 if (type_p) {
4065 *type_p = type;
4068 if (data_p) {
4069 *data_p = r.out.data;
4072 if (needed_p) {
4073 *needed_p = needed;
4076 return true;
4079 static bool test_GetPrinterDataEx(struct torture_context *tctx,
4080 struct dcerpc_pipe *p,
4081 struct policy_handle *handle,
4082 const char *key_name,
4083 const char *value_name,
4084 enum winreg_Type *type_p,
4085 uint8_t **data_p,
4086 uint32_t *needed_p)
4088 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
4089 NULL, type_p, data_p, needed_p);
4092 static bool test_get_environment(struct torture_context *tctx,
4093 struct dcerpc_binding_handle *b,
4094 struct policy_handle *handle,
4095 const char **architecture)
4097 DATA_BLOB blob;
4098 enum winreg_Type type;
4099 uint8_t *data;
4100 uint32_t needed;
4102 torture_assert(tctx,
4103 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
4104 "failed to get Architecture");
4106 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
4108 blob = data_blob_const(data, needed);
4109 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
4111 return true;
4114 static bool test_GetPrinterData_list(struct torture_context *tctx,
4115 void *private_data)
4117 struct test_spoolss_context *ctx =
4118 talloc_get_type_abort(private_data, struct test_spoolss_context);
4119 struct dcerpc_pipe *p = ctx->spoolss_pipe;
4120 struct dcerpc_binding_handle *b = p->binding_handle;
4121 const char *list[] = {
4122 "W3SvcInstalled",
4123 "BeepEnabled",
4124 "EventLog",
4125 /* "NetPopup", not on w2k8 */
4126 /* "NetPopupToComputer", not on w2k8 */
4127 "MajorVersion",
4128 "MinorVersion",
4129 "DefaultSpoolDirectory",
4130 "Architecture",
4131 "DsPresent",
4132 "OSVersion",
4133 /* "OSVersionEx", not on s3 */
4134 "DNSMachineName"
4136 int i;
4138 for (i=0; i < ARRAY_SIZE(list); i++) {
4139 enum winreg_Type type = REG_NONE;
4140 enum winreg_Type type_ex1 = REG_NONE;
4141 enum winreg_Type type_ex2 = REG_NONE;
4142 uint8_t *data;
4143 uint8_t *data_ex1 = NULL;
4144 uint8_t *data_ex2 = NULL;
4145 uint32_t needed;
4146 uint32_t needed_ex1 = 0;
4147 uint32_t needed_ex2 = 0;
4149 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4150 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4151 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex1, &data_ex1, &needed_ex1),
4152 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4153 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "", list[i], &type_ex2, &data_ex2, &needed_ex2),
4154 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4155 torture_assert_int_equal(tctx, type, type_ex1, "type mismatch");
4156 torture_assert_int_equal(tctx, type, type_ex2, "type mismatch");
4157 torture_assert_int_equal(tctx, needed, needed_ex1, "needed mismatch");
4158 torture_assert_int_equal(tctx, needed, needed_ex2, "needed mismatch");
4159 torture_assert_mem_equal(tctx, data, data_ex1, needed, "data mismatch");
4160 torture_assert_mem_equal(tctx, data, data_ex2, needed, "data mismatch");
4163 return true;
4166 static bool test_EnumPrinterData(struct torture_context *tctx,
4167 struct dcerpc_pipe *p,
4168 struct policy_handle *handle,
4169 uint32_t enum_index,
4170 uint32_t value_offered,
4171 uint32_t data_offered,
4172 enum winreg_Type *type_p,
4173 uint32_t *value_needed_p,
4174 uint32_t *data_needed_p,
4175 const char **value_name_p,
4176 uint8_t **data_p,
4177 WERROR *result_p)
4179 struct spoolss_EnumPrinterData r;
4180 uint32_t data_needed;
4181 uint32_t value_needed;
4182 enum winreg_Type type;
4183 struct dcerpc_binding_handle *b = p->binding_handle;
4185 r.in.handle = handle;
4186 r.in.enum_index = enum_index;
4187 r.in.value_offered = value_offered;
4188 r.in.data_offered = data_offered;
4189 r.out.data_needed = &data_needed;
4190 r.out.value_needed = &value_needed;
4191 r.out.type = &type;
4192 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4193 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4195 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4197 torture_assert_ntstatus_ok(tctx,
4198 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4199 "EnumPrinterData failed");
4201 if (type_p) {
4202 *type_p = type;
4204 if (value_needed_p) {
4205 *value_needed_p = value_needed;
4207 if (data_needed_p) {
4208 *data_needed_p = data_needed;
4210 if (value_name_p) {
4211 *value_name_p = r.out.value_name;
4213 if (data_p) {
4214 *data_p = r.out.data;
4216 if (result_p) {
4217 *result_p = r.out.result;
4220 return true;
4224 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4225 struct dcerpc_pipe *p,
4226 struct policy_handle *handle)
4228 uint32_t enum_index = 0;
4229 enum winreg_Type type;
4230 uint32_t value_needed;
4231 uint32_t data_needed;
4232 uint8_t *data;
4233 const char *value_name;
4234 WERROR result;
4236 torture_comment(tctx, "Testing EnumPrinterData\n");
4238 do {
4239 torture_assert(tctx,
4240 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4241 &type, &value_needed, &data_needed,
4242 &value_name, &data, &result),
4243 "EnumPrinterData failed");
4245 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4246 break;
4249 torture_assert(tctx,
4250 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4251 &type, &value_needed, &data_needed,
4252 &value_name, &data, &result),
4253 "EnumPrinterData failed");
4255 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4256 break;
4259 enum_index++;
4261 } while (W_ERROR_IS_OK(result));
4263 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4265 return true;
4268 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4269 struct dcerpc_binding_handle *b,
4270 struct policy_handle *handle,
4271 const char *key_name,
4272 uint32_t *count_p,
4273 struct spoolss_PrinterEnumValues **info_p)
4275 struct spoolss_EnumPrinterDataEx r;
4276 struct spoolss_PrinterEnumValues *info;
4277 uint32_t needed;
4278 uint32_t count;
4280 r.in.handle = handle;
4281 r.in.key_name = key_name;
4282 r.in.offered = 0;
4283 r.out.needed = &needed;
4284 r.out.count = &count;
4285 r.out.info = &info;
4287 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4289 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4290 "EnumPrinterDataEx failed");
4291 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4292 r.in.offered = needed;
4293 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4294 "EnumPrinterDataEx failed");
4297 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4299 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4301 if (count_p) {
4302 *count_p = count;
4304 if (info_p) {
4305 *info_p = info;
4308 return true;
4311 static bool test_SetPrinterData(struct torture_context *tctx,
4312 struct dcerpc_binding_handle *b,
4313 struct policy_handle *handle,
4314 const char *value_name,
4315 enum winreg_Type type,
4316 uint8_t *data,
4317 uint32_t offered);
4318 static bool test_DeletePrinterData(struct torture_context *tctx,
4319 struct dcerpc_binding_handle *b,
4320 struct policy_handle *handle,
4321 const char *value_name);
4323 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4324 struct dcerpc_pipe *p,
4325 struct policy_handle *handle)
4327 uint32_t count;
4328 struct spoolss_PrinterEnumValues *info;
4329 int i;
4330 uint32_t value_needed, data_needed;
4331 uint32_t value_offered, data_offered;
4332 WERROR result;
4333 struct dcerpc_binding_handle *b = p->binding_handle;
4335 enum winreg_Type type;
4336 DATA_BLOB blob;
4338 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4340 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4341 type = REG_SZ;
4343 torture_assert(tctx,
4344 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4345 "SetPrinterData failed");
4347 blob = data_blob_string_const("torture_data2");
4349 torture_assert(tctx,
4350 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4351 "SetPrinterData failed");
4353 blob = data_blob_talloc(tctx, NULL, 4);
4354 SIVAL(blob.data, 0, 0x11223344);
4356 torture_assert(tctx,
4357 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4358 "SetPrinterData failed");
4360 torture_assert(tctx,
4361 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4362 "failed to call EnumPrinterDataEx");
4364 /* get the max sizes for value and data */
4366 torture_assert(tctx,
4367 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4368 NULL, &value_needed, &data_needed,
4369 NULL, NULL, &result),
4370 "EnumPrinterData failed");
4371 torture_assert_werr_ok(tctx, result, "unexpected result");
4373 /* check if the reply from the EnumPrinterData really matches max values */
4375 for (i=0; i < count; i++) {
4376 if (info[i].value_name_len > value_needed) {
4377 torture_fail(tctx,
4378 talloc_asprintf(tctx,
4379 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4380 info[i].value_name_len, value_needed));
4382 if (info[i].data_length > data_needed) {
4383 torture_fail(tctx,
4384 talloc_asprintf(tctx,
4385 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4386 info[i].data_length, data_needed));
4390 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4391 * sort or not sort the replies by value name, we should be able to do
4392 * the following entry comparison */
4394 data_offered = data_needed;
4395 value_offered = value_needed;
4397 for (i=0; i < count; i++) {
4399 const char *value_name;
4400 uint8_t *data;
4402 torture_assert(tctx,
4403 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4404 &type, &value_needed, &data_needed,
4405 &value_name, &data, &result),
4406 "EnumPrinterData failed");
4408 if (i -1 == count) {
4409 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4410 "unexpected result");
4411 break;
4412 } else {
4413 torture_assert_werr_ok(tctx, result, "unexpected result");
4416 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4417 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4418 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4419 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4420 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4423 torture_assert(tctx,
4424 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4425 "DeletePrinterData failed");
4426 torture_assert(tctx,
4427 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4428 "DeletePrinterData failed");
4429 torture_assert(tctx,
4430 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4431 "DeletePrinterData failed");
4433 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4435 return true;
4438 static bool test_DeletePrinterData(struct torture_context *tctx,
4439 struct dcerpc_binding_handle *b,
4440 struct policy_handle *handle,
4441 const char *value_name)
4443 NTSTATUS status;
4444 struct spoolss_DeletePrinterData r;
4446 r.in.handle = handle;
4447 r.in.value_name = value_name;
4449 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4450 r.in.value_name);
4452 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4454 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4455 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4457 return true;
4460 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4461 struct dcerpc_binding_handle *b,
4462 struct policy_handle *handle,
4463 const char *key_name,
4464 const char *value_name)
4466 struct spoolss_DeletePrinterDataEx r;
4468 r.in.handle = handle;
4469 r.in.key_name = key_name;
4470 r.in.value_name = value_name;
4472 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4473 r.in.key_name, r.in.value_name);
4475 torture_assert_ntstatus_ok(tctx,
4476 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4477 "DeletePrinterDataEx failed");
4478 torture_assert_werr_ok(tctx, r.out.result,
4479 "DeletePrinterDataEx failed");
4481 return true;
4484 static bool test_DeletePrinterKey(struct torture_context *tctx,
4485 struct dcerpc_binding_handle *b,
4486 struct policy_handle *handle,
4487 const char *key_name)
4489 struct spoolss_DeletePrinterKey r;
4491 r.in.handle = handle;
4492 r.in.key_name = key_name;
4494 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4496 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4497 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4498 return true;
4501 torture_assert_ntstatus_ok(tctx,
4502 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4503 "DeletePrinterKey failed");
4504 torture_assert_werr_ok(tctx, r.out.result,
4505 "DeletePrinterKey failed");
4507 return true;
4510 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4511 struct dcerpc_binding_handle *b,
4512 struct policy_handle *handle)
4514 struct winreg_OpenHKLM r;
4516 r.in.system_name = NULL;
4517 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4518 r.out.handle = handle;
4520 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4522 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4523 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4525 return true;
4528 static void init_winreg_String(struct winreg_String *name, const char *s)
4530 name->name = s;
4531 if (s) {
4532 name->name_len = 2 * (strlen_m(s) + 1);
4533 name->name_size = name->name_len;
4534 } else {
4535 name->name_len = 0;
4536 name->name_size = 0;
4540 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4541 struct dcerpc_binding_handle *b,
4542 struct policy_handle *hive_handle,
4543 const char *keyname,
4544 uint32_t options,
4545 struct policy_handle *key_handle)
4547 struct winreg_OpenKey r;
4549 r.in.parent_handle = hive_handle;
4550 init_winreg_String(&r.in.keyname, keyname);
4551 r.in.options = options;
4552 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4553 r.out.handle = key_handle;
4555 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4557 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4558 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4560 return true;
4563 static bool test_winreg_OpenKey(struct torture_context *tctx,
4564 struct dcerpc_binding_handle *b,
4565 struct policy_handle *hive_handle,
4566 const char *keyname,
4567 struct policy_handle *key_handle)
4569 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4570 REG_OPTION_NON_VOLATILE, key_handle);
4573 static bool test_winreg_CloseKey(struct torture_context *tctx,
4574 struct dcerpc_binding_handle *b,
4575 struct policy_handle *handle)
4577 struct winreg_CloseKey r;
4579 r.in.handle = handle;
4580 r.out.handle = handle;
4582 torture_comment(tctx, "Testing winreg_CloseKey\n");
4584 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4585 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4587 return true;
4590 bool test_winreg_QueryValue(struct torture_context *tctx,
4591 struct dcerpc_binding_handle *b,
4592 struct policy_handle *handle,
4593 const char *value_name,
4594 enum winreg_Type *type_p,
4595 uint32_t *data_size_p,
4596 uint32_t *data_length_p,
4597 uint8_t **data_p)
4599 struct winreg_QueryValue r;
4600 enum winreg_Type type = REG_NONE;
4601 uint32_t data_size = 0;
4602 uint32_t data_length = 0;
4603 struct winreg_String valuename;
4604 uint8_t *data = NULL;
4606 init_winreg_String(&valuename, value_name);
4608 data = talloc_zero_array(tctx, uint8_t, 0);
4610 r.in.handle = handle;
4611 r.in.value_name = &valuename;
4612 r.in.type = &type;
4613 r.in.data_size = &data_size;
4614 r.in.data_length = &data_length;
4615 r.in.data = data;
4616 r.out.type = &type;
4617 r.out.data = data;
4618 r.out.data_size = &data_size;
4619 r.out.data_length = &data_length;
4621 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4623 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4624 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4625 *r.in.data_size = *r.out.data_size;
4626 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4627 r.in.data = data;
4628 r.out.data = data;
4629 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4631 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4633 if (type_p) {
4634 *type_p = *r.out.type;
4636 if (data_size_p) {
4637 *data_size_p = *r.out.data_size;
4639 if (data_length_p) {
4640 *data_length_p = *r.out.data_length;
4642 if (data_p) {
4643 *data_p = r.out.data;
4646 return true;
4649 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4650 struct dcerpc_binding_handle *b,
4651 struct policy_handle *handle,
4652 const char *printer_name,
4653 const char *key_name,
4654 const char *value_name,
4655 enum winreg_Type *w_type,
4656 uint32_t *w_size,
4657 uint32_t *w_length,
4658 uint8_t **w_data)
4660 const char *printer_key;
4661 struct policy_handle key_handle;
4663 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4664 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4666 torture_assert(tctx,
4667 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4669 torture_assert(tctx,
4670 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4672 torture_assert(tctx,
4673 test_winreg_CloseKey(tctx, b, &key_handle), "");
4675 return true;
4678 static bool test_GetForm_winreg(struct torture_context *tctx,
4679 struct dcerpc_binding_handle *b,
4680 struct policy_handle *handle,
4681 const char *key_name,
4682 const char *form_name,
4683 enum winreg_Type *w_type,
4684 uint32_t *w_size,
4685 uint32_t *w_length,
4686 uint8_t **w_data)
4688 struct policy_handle key_handle;
4690 torture_assert(tctx,
4691 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4693 torture_assert(tctx,
4694 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4696 torture_assert(tctx,
4697 test_winreg_CloseKey(tctx, b, &key_handle), "");
4699 return true;
4702 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4703 struct dcerpc_binding_handle *b,
4704 struct policy_handle *handle,
4705 const char *symlink_keyname,
4706 const char *symlink_destination)
4708 /* check if the first key is a symlink to the second key */
4710 enum winreg_Type w_type;
4711 uint32_t w_size;
4712 uint32_t w_length;
4713 uint8_t *w_data;
4714 struct policy_handle key_handle;
4715 DATA_BLOB blob;
4716 const char *str;
4718 if (torture_setting_bool(tctx, "samba3", false)) {
4719 torture_skip(tctx, "skip winreg symlink test against samba");
4722 torture_assert(tctx,
4723 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4724 "failed to open key link");
4726 torture_assert(tctx,
4727 test_winreg_QueryValue(tctx, b, &key_handle,
4728 "SymbolicLinkValue",
4729 &w_type, &w_size, &w_length, &w_data),
4730 "failed to query for 'SymbolicLinkValue' attribute");
4732 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4734 blob = data_blob(w_data, w_size);
4735 str = reg_val_data_string(tctx, REG_SZ, blob);
4737 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4739 torture_assert(tctx,
4740 test_winreg_CloseKey(tctx, b, &key_handle),
4741 "failed to close key link");
4743 return true;
4746 static const char *strip_unc(const char *unc)
4748 char *name;
4750 if (!unc) {
4751 return NULL;
4754 if (unc[0] == '\\' && unc[1] == '\\') {
4755 unc +=2;
4758 name = strchr(unc, '\\');
4759 if (name) {
4760 return name+1;
4763 return unc;
4766 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4767 struct dcerpc_binding_handle *b,
4768 struct policy_handle *handle,
4769 const char *printer_name,
4770 struct dcerpc_binding_handle *winreg_handle,
4771 struct policy_handle *hive_handle)
4773 union spoolss_PrinterInfo info;
4774 const char *keys[] = {
4775 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4776 TOP_LEVEL_PRINT_PRINTERS_KEY
4778 int i;
4779 const char *printername, *sharename;
4781 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4783 torture_assert(tctx,
4784 test_GetPrinter_level(tctx, b, handle, 2, &info),
4785 "failed to get printer info level 2");
4787 printername = strip_unc(info.info2.printername);
4788 sharename = strip_unc(info.info2.sharename);
4790 #define test_sz(wname, iname) \
4791 do {\
4792 DATA_BLOB blob;\
4793 const char *str;\
4794 enum winreg_Type w_type;\
4795 uint32_t w_size;\
4796 uint32_t w_length;\
4797 uint8_t *w_data;\
4798 torture_assert(tctx,\
4799 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4800 &w_type, &w_size, &w_length, &w_data),\
4801 "failed to query winreg");\
4802 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4803 blob = data_blob(w_data, w_size);\
4804 str = reg_val_data_string(tctx, REG_SZ, blob);\
4805 if (w_size == 2 && iname == NULL) {\
4806 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4807 } else {\
4808 torture_assert_str_equal(tctx, str, iname,\
4809 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4811 } while(0);
4813 #define test_dword(wname, iname) \
4814 do {\
4815 uint32_t value;\
4816 enum winreg_Type w_type;\
4817 uint32_t w_size;\
4818 uint32_t w_length;\
4819 uint8_t *w_data;\
4820 torture_assert(tctx,\
4821 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4822 &w_type, &w_size, &w_length, &w_data),\
4823 "failed to query winreg");\
4824 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4825 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4826 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4827 value = IVAL(w_data, 0);\
4828 torture_assert_int_equal(tctx, value, iname,\
4829 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4830 } while(0);
4832 #define test_binary(wname, iname) \
4833 do {\
4834 enum winreg_Type w_type;\
4835 uint32_t w_size;\
4836 uint32_t w_length;\
4837 uint8_t *w_data;\
4838 torture_assert(tctx,\
4839 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4840 &w_type, &w_size, &w_length, &w_data),\
4841 "failed to query winreg");\
4842 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4843 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4844 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4845 "binary unequal");\
4846 } while(0);
4849 #define test_dm(wname, iname) \
4850 do {\
4851 DATA_BLOB blob;\
4852 struct spoolss_DeviceMode dm;\
4853 enum ndr_err_code ndr_err;\
4854 enum winreg_Type w_type;\
4855 uint32_t w_size;\
4856 uint32_t w_length;\
4857 uint8_t *w_data;\
4858 torture_assert(tctx,\
4859 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4860 &w_type, &w_size, &w_length, &w_data),\
4861 "failed to query winreg");\
4862 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4863 blob = data_blob(w_data, w_size);\
4864 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4865 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4866 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4867 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4868 "dm unequal");\
4869 } while(0);
4871 #define test_sd(wname, iname) \
4872 do {\
4873 DATA_BLOB blob;\
4874 struct security_descriptor sd;\
4875 enum ndr_err_code ndr_err;\
4876 enum winreg_Type w_type;\
4877 uint32_t w_size;\
4878 uint32_t w_length;\
4879 uint8_t *w_data;\
4880 torture_assert(tctx,\
4881 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4882 &w_type, &w_size, &w_length, &w_data),\
4883 "failed to query winreg");\
4884 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4885 blob = data_blob(w_data, w_size);\
4886 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4887 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4888 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4889 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4890 "sd unequal");\
4891 } while(0);
4893 #define test_multi_sz(wname, iname) \
4894 do {\
4895 DATA_BLOB blob;\
4896 const char **array;\
4897 enum winreg_Type w_type;\
4898 uint32_t w_size;\
4899 uint32_t w_length;\
4900 uint8_t *w_data;\
4901 int i;\
4902 torture_assert(tctx,\
4903 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4904 &w_type, &w_size, &w_length, &w_data),\
4905 "failed to query winreg");\
4906 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4907 blob = data_blob(w_data, w_size);\
4908 torture_assert(tctx, \
4909 pull_reg_multi_sz(tctx, &blob, &array),\
4910 "failed to pull multi sz");\
4911 for (i=0; array[i] != NULL; i++) {\
4912 torture_assert_str_equal(tctx, array[i], iname[i],\
4913 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4915 } while(0);
4917 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4918 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4919 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4921 torture_warning(tctx, "failed to check for winreg symlink");
4924 for (i=0; i < ARRAY_SIZE(keys); i++) {
4926 const char *printer_key;
4927 struct policy_handle key_handle;
4929 printer_key = talloc_asprintf(tctx, "%s\\%s",
4930 keys[i], printer_name);
4932 torture_assert(tctx,
4933 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4935 test_sz("Name", printername);
4936 test_sz("Share Name", sharename);
4937 test_sz("Port", info.info2.portname);
4938 test_sz("Printer Driver", info.info2.drivername);
4939 test_sz("Description", info.info2.comment);
4940 test_sz("Location", info.info2.location);
4941 test_sz("Separator File", info.info2.sepfile);
4942 test_sz("Print Processor", info.info2.printprocessor);
4943 test_sz("Datatype", info.info2.datatype);
4944 test_sz("Parameters", info.info2.parameters);
4945 /* winreg: 0, spoolss not */
4946 /* test_dword("Attributes", info.info2.attributes); */
4947 test_dword("Priority", info.info2.priority);
4948 test_dword("Default Priority", info.info2.defaultpriority);
4949 /* winreg: 60, spoolss: 0 */
4950 /* test_dword("StartTime", info.info2.starttime); */
4951 /* test_dword("UntilTime", info.info2.untiltime); */
4952 /* winreg != spoolss */
4953 /* test_dword("Status", info.info2.status); */
4954 test_dm("Default DevMode", info.info2.devmode);
4955 test_sd("Security", info.info2.secdesc);
4957 torture_assert(tctx,
4958 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4961 #undef test_dm
4963 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4965 return true;
4968 static bool test_GetPrintserverInfo_winreg(struct torture_context *tctx,
4969 struct dcerpc_binding_handle *b,
4970 struct policy_handle *handle,
4971 struct dcerpc_binding_handle *winreg_handle,
4972 struct policy_handle *hive_handle)
4974 union spoolss_PrinterInfo info;
4975 struct policy_handle key_handle;
4977 torture_comment(tctx,
4978 "Testing Printserver Info and winreg consistency\n");
4980 torture_assert(tctx,
4981 test_GetPrinter_level(tctx, b, handle, 3, &info),
4982 "failed to get printer info level 2");
4984 torture_assert(tctx,
4985 test_winreg_OpenKey(tctx, winreg_handle, hive_handle,
4986 TOP_LEVEL_CONTROL_KEY, &key_handle), "");
4988 test_sd("ServerSecurityDescriptor", info.info3.secdesc);
4990 torture_assert(tctx,
4991 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4993 #undef test_sd
4995 torture_comment(tctx,
4996 "Printserver Info and winreg consistency test succeeded\n\n");
4998 return true;
5002 static bool test_PrintProcessors(struct torture_context *tctx,
5003 struct dcerpc_binding_handle *b,
5004 const char *environment,
5005 struct dcerpc_binding_handle *winreg_handle,
5006 struct policy_handle *hive_handle)
5008 union spoolss_PrintProcessorInfo *info;
5009 uint32_t count;
5010 int i;
5012 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
5014 torture_assert(tctx,
5015 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
5016 "failed to enum print processors level 1");
5018 for (i=0; i < count; i++) {
5020 const char *processor_key;
5021 struct policy_handle key_handle;
5023 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
5024 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5025 environment,
5026 info[i].info1.print_processor_name);
5028 torture_assert(tctx,
5029 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
5031 /* nothing to check in there so far */
5033 torture_assert(tctx,
5034 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5037 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
5039 return true;
5042 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5043 struct dcerpc_binding_handle *b,
5044 struct policy_handle *handle,
5045 const char *driver_name,
5046 const char *architecture,
5047 uint32_t level,
5048 uint32_t client_major_version,
5049 uint32_t client_minor_version,
5050 union spoolss_DriverInfo *info_p,
5051 WERROR *result);
5053 static const char *strip_path(const char *path)
5055 char *p;
5057 if (path == NULL) {
5058 return NULL;
5061 p = strrchr(path, '\\');
5062 if (p) {
5063 return p+1;
5066 return path;
5069 static const char **strip_paths(const char **path_array)
5071 int i;
5073 if (path_array == NULL) {
5074 return NULL;
5077 for (i=0; path_array[i] != NULL; i++) {
5078 path_array[i] = strip_path(path_array[i]);
5081 return path_array;
5084 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
5086 time_t t;
5087 struct tm *tm;
5089 if (nt == 0) {
5090 return talloc_strdup(mem_ctx, "01/01/1601");
5093 t = nt_time_to_unix(nt);
5094 tm = localtime(&t);
5096 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
5097 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
5100 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
5102 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
5103 (unsigned)((v >> 48) & 0xFFFF),
5104 (unsigned)((v >> 32) & 0xFFFF),
5105 (unsigned)((v >> 16) & 0xFFFF),
5106 (unsigned)(v & 0xFFFF));
5109 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
5110 struct dcerpc_binding_handle *b,
5111 struct policy_handle *handle,
5112 const char *printer_name,
5113 const char *driver_name,
5114 const char *environment,
5115 enum spoolss_DriverOSVersion version,
5116 struct dcerpc_binding_handle *winreg_handle,
5117 struct policy_handle *hive_handle,
5118 const char *server_name_slash)
5120 WERROR result = WERR_OK;
5121 union spoolss_DriverInfo info;
5122 const char *driver_key;
5123 struct policy_handle key_handle;
5125 const char *driver_path;
5126 const char *data_file;
5127 const char *config_file;
5128 const char *help_file;
5129 const char **dependent_files;
5131 const char *driver_date;
5132 const char *inbox_driver_date;
5134 const char *driver_version;
5135 const char *inbox_driver_version;
5137 ZERO_STRUCT(key_handle);
5139 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
5141 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
5142 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5143 environment,
5144 version,
5145 driver_name);
5147 torture_assert(tctx,
5148 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
5149 "failed to open driver key");
5151 if (torture_setting_bool(tctx, "samba3", false) ||
5152 torture_setting_bool(tctx, "w2k3", false)) {
5153 goto try_level6;
5156 if (handle) {
5157 torture_assert(tctx,
5158 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
5159 "failed to get driver info level 8");
5160 } else {
5161 torture_assert(tctx,
5162 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
5163 "failed to get driver info level 8");
5166 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
5167 goto try_level6;
5170 driver_path = strip_path(info.info8.driver_path);
5171 data_file = strip_path(info.info8.data_file);
5172 config_file = strip_path(info.info8.config_file);
5173 help_file = strip_path(info.info8.help_file);
5174 dependent_files = strip_paths(info.info8.dependent_files);
5176 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5177 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5179 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5180 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5182 test_sz("Configuration File", config_file);
5183 test_sz("Data File", data_file);
5184 test_sz("Datatype", info.info8.default_datatype);
5185 test_sz("Driver", driver_path);
5186 test_sz("DriverDate", driver_date);
5187 test_sz("DriverVersion", driver_version);
5188 test_sz("HardwareID", info.info8.hardware_id);
5189 test_sz("Help File", help_file);
5190 test_sz("InfPath", info.info8.inf_path);
5191 test_sz("Manufacturer", info.info8.manufacturer_name);
5192 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5193 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5194 test_sz("Monitor", info.info8.monitor_name);
5195 test_sz("OEM URL", info.info8.manufacturer_url);
5196 test_sz("Print Processor", info.info8.print_processor);
5197 test_sz("Provider", info.info8.provider);
5198 test_sz("VendorSetup", info.info8.vendor_setup);
5199 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5200 test_multi_sz("Dependent Files", dependent_files);
5201 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5202 test_multi_sz("Previous Names", info.info8.previous_names);
5203 /* test_dword("Attributes", ?); */
5204 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5205 test_dword("Version", info.info8.version);
5206 /* test_dword("TempDir", ?); */
5208 try_level6:
5210 if (handle) {
5211 torture_assert(tctx,
5212 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5213 "failed to get driver info level 6");
5214 } else {
5215 torture_assert(tctx,
5216 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5217 "failed to get driver info level 6");
5220 driver_path = strip_path(info.info6.driver_path);
5221 data_file = strip_path(info.info6.data_file);
5222 config_file = strip_path(info.info6.config_file);
5223 help_file = strip_path(info.info6.help_file);
5224 dependent_files = strip_paths(info.info6.dependent_files);
5226 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5228 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5230 test_sz("Configuration File", config_file);
5231 test_sz("Data File", data_file);
5232 test_sz("Datatype", info.info6.default_datatype);
5233 test_sz("Driver", driver_path);
5234 if (torture_setting_bool(tctx, "w2k3", false)) {
5235 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5236 push_nttime(blob.data, 0, info.info6.driver_date);
5237 test_binary("DriverDate", blob);
5238 SBVAL(blob.data, 0, info.info6.driver_version);
5239 test_binary("DriverVersion", blob);
5240 } else {
5241 test_sz("DriverDate", driver_date);
5242 test_sz("DriverVersion", driver_version);
5244 test_sz("HardwareID", info.info6.hardware_id);
5245 test_sz("Help File", help_file);
5246 test_sz("Manufacturer", info.info6.manufacturer_name);
5247 test_sz("Monitor", info.info6.monitor_name);
5248 test_sz("OEM URL", info.info6.manufacturer_url);
5249 test_sz("Provider", info.info6.provider);
5250 test_multi_sz("Dependent Files", dependent_files);
5251 test_multi_sz("Previous Names", info.info6.previous_names);
5252 /* test_dword("Attributes", ?); */
5253 test_dword("Version", info.info6.version);
5254 /* test_dword("TempDir", ?); */
5256 if (handle) {
5257 torture_assert(tctx,
5258 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5259 "failed to get driver info level 3");
5260 } else {
5261 torture_assert(tctx,
5262 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5263 "failed to get driver info level 3");
5266 driver_path = strip_path(info.info3.driver_path);
5267 data_file = strip_path(info.info3.data_file);
5268 config_file = strip_path(info.info3.config_file);
5269 help_file = strip_path(info.info3.help_file);
5270 dependent_files = strip_paths(info.info3.dependent_files);
5272 test_sz("Configuration File", config_file);
5273 test_sz("Data File", data_file);
5274 test_sz("Datatype", info.info3.default_datatype);
5275 test_sz("Driver", driver_path);
5276 test_sz("Help File", help_file);
5277 test_sz("Monitor", info.info3.monitor_name);
5278 test_multi_sz("Dependent Files", dependent_files);
5279 /* test_dword("Attributes", ?); */
5280 test_dword("Version", info.info3.version);
5281 /* test_dword("TempDir", ?); */
5284 torture_assert(tctx,
5285 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5287 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5289 return true;
5292 #undef test_sz
5293 #undef test_dword
5295 static bool test_SetPrinterData(struct torture_context *tctx,
5296 struct dcerpc_binding_handle *b,
5297 struct policy_handle *handle,
5298 const char *value_name,
5299 enum winreg_Type type,
5300 uint8_t *data,
5301 uint32_t offered)
5303 struct spoolss_SetPrinterData r;
5305 r.in.handle = handle;
5306 r.in.value_name = value_name;
5307 r.in.type = type;
5308 r.in.data = data;
5309 r.in.offered = offered;
5311 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5312 r.in.value_name);
5314 torture_assert_ntstatus_ok(tctx,
5315 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5316 "SetPrinterData failed");
5317 torture_assert_werr_ok(tctx, r.out.result,
5318 "SetPrinterData failed");
5320 return true;
5323 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5324 struct dcerpc_binding_handle *b,
5325 struct policy_handle *handle,
5326 const char *printer_name,
5327 struct dcerpc_binding_handle *winreg_handle,
5328 struct policy_handle *hive_handle)
5330 const char *values[] = {
5331 "spootyfoot",
5332 "spooty\\foot",
5333 #if 0
5334 /* FIXME: not working with s3 atm. */
5335 "spooty,foot",
5336 "spooty,fo,ot",
5337 #endif
5338 "spooty foot",
5339 #if 0
5340 /* FIXME: not working with s3 atm. */
5341 "spooty\\fo,ot",
5342 "spooty,fo\\ot"
5343 #endif
5345 int i;
5347 for (i=0; i < ARRAY_SIZE(values); i++) {
5349 enum winreg_Type type, expected_type = REG_SZ;
5350 DATA_BLOB blob;
5351 uint8_t *data;
5352 uint32_t needed;
5354 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5355 type = REG_SZ;
5357 torture_assert(tctx,
5358 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5359 "SetPrinterData failed");
5361 torture_assert(tctx,
5362 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5363 "GetPrinterData failed");
5365 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5366 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5367 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5369 if (winreg_handle && hive_handle) {
5371 enum winreg_Type w_type;
5372 uint32_t w_size;
5373 uint32_t w_length;
5374 uint8_t *w_data;
5376 torture_assert(tctx,
5377 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5378 printer_name, "PrinterDriverData", values[i],
5379 &w_type, &w_size, &w_length, &w_data), "");
5381 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5382 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5383 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5384 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5387 torture_assert(tctx,
5388 test_DeletePrinterData(tctx, b, handle, values[i]),
5389 "DeletePrinterData failed");
5392 return true;
5396 static bool test_EnumPrinterKey(struct torture_context *tctx,
5397 struct dcerpc_binding_handle *b,
5398 struct policy_handle *handle,
5399 const char *key_name,
5400 const char ***array);
5402 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5403 struct dcerpc_binding_handle *b,
5404 struct policy_handle *handle,
5405 const char *key_name,
5406 const char *value_name,
5407 enum winreg_Type type,
5408 uint8_t *data,
5409 uint32_t offered)
5411 NTSTATUS status;
5412 struct spoolss_SetPrinterDataEx r;
5414 r.in.handle = handle;
5415 r.in.key_name = key_name;
5416 r.in.value_name = value_name;
5417 r.in.type = type;
5418 r.in.data = data;
5419 r.in.offered = offered;
5421 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5422 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5424 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5426 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5427 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5429 return true;
5432 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5433 struct dcerpc_pipe *p,
5434 struct policy_handle *handle)
5436 struct dcerpc_binding_handle *b = p->binding_handle;
5437 const char *value_name = "dog";
5438 const char *keys[] = {
5439 "torturedataex",
5440 "torture data ex",
5441 "torturedataex_with_subkey\\subkey",
5442 "torturedataex_with_subkey\\subkey:0",
5443 "torturedataex_with_subkey\\subkey:1",
5444 "torturedataex_with_subkey\\subkey\\subsubkey",
5445 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5446 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5447 "torture,data",
5448 "torture,data,ex",
5449 "torture,data\\ex",
5450 "torture\\data,ex",
5451 "torture/data",
5452 "torture/data ex",
5453 "torture/data ex/sub",
5454 "torture//data",
5455 "torture//data ex",
5456 "torture//data ex/sub",
5457 "torture//data ex//sub",
5459 int i;
5461 for (i=0; i < ARRAY_SIZE(keys); i++) {
5463 char *c;
5464 const char *key;
5465 enum winreg_Type type;
5466 DATA_BLOB blob_in, blob_out;
5467 const char **subkeys;
5468 uint32_t ecount;
5469 struct spoolss_PrinterEnumValues *einfo;
5470 uint32_t needed;
5472 blob_in = data_blob_talloc(tctx, NULL, 42);
5474 generate_random_buffer(blob_in.data, blob_in.length);
5476 torture_assert(tctx,
5477 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5478 "failed to call SetPrinterDataEx");
5480 torture_assert(tctx,
5481 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5482 "failed to call GetPrinterDataEx");
5484 blob_out.length = needed;
5485 torture_assert(tctx,
5486 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5487 "failed to call EnumPrinterDataEx");
5489 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5490 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5491 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5493 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5494 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5495 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5496 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5497 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5498 if (einfo[0].data_length > 0) {
5499 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5502 key = talloc_strdup(tctx, keys[i]);
5504 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5505 return false;
5508 c = strchr(key, '\\');
5509 if (c) {
5510 int k;
5512 /* we have subkeys */
5514 *c = 0;
5516 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5517 return false;
5520 for (k=0; subkeys && subkeys[k]; k++) {
5522 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5524 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5525 return false;
5529 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5530 return false;
5533 } else {
5534 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5535 return false;
5540 return true;
5543 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5544 struct dcerpc_pipe *p,
5545 struct policy_handle *handle)
5547 struct dcerpc_binding_handle *b = p->binding_handle;
5548 const char *key = "torturedataex";
5549 const char *values[] = {
5550 "torture_value",
5551 "torture value",
5552 "torture,value",
5553 "torture/value",
5554 "torture\\value",
5555 "torture\\\\value"
5557 int i;
5559 for (i=0; i < ARRAY_SIZE(values); i++) {
5561 enum winreg_Type type = REG_NONE;
5562 DATA_BLOB blob_in = data_blob_null;
5563 DATA_BLOB blob_out = data_blob_null;
5564 uint32_t ecount;
5565 struct spoolss_PrinterEnumValues *einfo;
5566 uint32_t needed = 0;
5568 if (torture_setting_bool(tctx, "samba3", false)) {
5569 char *q;
5570 q = strrchr(values[i], ',');
5571 if (q) {
5572 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5573 values[i]);
5574 continue;
5578 blob_in = data_blob_talloc(tctx, NULL, 42);
5580 generate_random_buffer(blob_in.data, blob_in.length);
5582 torture_assert(tctx,
5583 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5584 "failed to call SetPrinterDataEx");
5586 torture_assert(tctx,
5587 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5588 "failed to call GetPrinterDataEx");
5590 blob_out.length = needed;
5591 torture_assert(tctx,
5592 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5593 "failed to call EnumPrinterDataEx");
5595 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5596 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5597 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5599 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5600 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5601 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5602 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5603 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5604 if (einfo[0].data_length > 0) {
5605 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5608 torture_assert(tctx,
5609 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5610 "failed to call DeletePrinterDataEx");
5613 return true;
5617 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5618 struct dcerpc_pipe *p,
5619 struct policy_handle *handle,
5620 const char *printername,
5621 struct dcerpc_binding_handle *winreg_handle,
5622 struct policy_handle *hive_handle)
5624 struct dcerpc_binding_handle *b = p->binding_handle;
5625 const char *value_name = "dog";
5626 const char *key_name = "torturedataex";
5627 enum winreg_Type types[] = {
5628 REG_SZ,
5629 REG_MULTI_SZ,
5630 REG_DWORD,
5631 REG_BINARY
5633 const char *str = "abcdefghi";
5634 size_t t, s;
5636 for (t=0; t < ARRAY_SIZE(types); t++) {
5637 for (s=0; s < strlen(str); s++) {
5639 enum winreg_Type type;
5640 const char *string = talloc_strndup(tctx, str, s);
5641 const char *array[2];
5642 DATA_BLOB blob = data_blob_string_const(string);
5643 DATA_BLOB data;
5644 uint8_t *data_out;
5645 uint32_t needed, offered = 0;
5646 uint32_t ecount;
5647 struct spoolss_PrinterEnumValues *einfo;
5649 array[0] = talloc_strdup(tctx, string);
5650 array[1] = NULL;
5652 if (types[t] == REG_DWORD) {
5653 s = 0xffff;
5656 switch (types[t]) {
5657 case REG_BINARY:
5658 data = blob;
5659 offered = blob.length;
5660 break;
5661 case REG_DWORD:
5662 data = data_blob_talloc(tctx, NULL, 4);
5663 SIVAL(data.data, 0, 0x12345678);
5664 offered = 4;
5665 break;
5666 case REG_SZ:
5667 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5668 type = REG_SZ;
5669 offered = data.length;
5670 /*strlen_m_term(data.string)*2;*/
5671 break;
5672 case REG_MULTI_SZ:
5673 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5674 type = REG_MULTI_SZ;
5675 offered = data.length;
5676 break;
5677 default:
5678 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5681 torture_assert(tctx,
5682 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5683 "failed to call SetPrinterDataEx");
5685 torture_assert(tctx,
5686 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5687 "failed to call GetPrinterDataEx");
5689 torture_assert(tctx,
5690 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5691 "failed to call EnumPrinterDataEx");
5693 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5694 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5695 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5697 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5698 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5699 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5700 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5701 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5702 if (einfo[0].data_length > 0) {
5703 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5706 if (winreg_handle && hive_handle) {
5707 enum winreg_Type w_type;
5708 uint32_t w_size;
5709 uint32_t w_length;
5710 uint8_t *w_data;
5712 torture_assert(tctx,
5713 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5714 printername, key_name, value_name,
5715 &w_type, &w_size, &w_length, &w_data), "");
5717 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5718 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5719 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5720 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5723 torture_assert(tctx,
5724 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5725 "failed to call DeletePrinterDataEx");
5729 return true;
5732 static bool test_PrinterData_winreg(struct torture_context *tctx,
5733 struct dcerpc_pipe *p,
5734 struct policy_handle *handle,
5735 const char *printer_name)
5737 struct dcerpc_binding_handle *b = p->binding_handle;
5738 struct dcerpc_pipe *p2;
5739 bool ret = true;
5740 struct policy_handle hive_handle;
5741 struct dcerpc_binding_handle *b2;
5743 torture_assert_ntstatus_ok(tctx,
5744 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5745 "could not open winreg pipe");
5746 b2 = p2->binding_handle;
5748 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5750 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5751 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5753 test_winreg_CloseKey(tctx, b2, &hive_handle);
5755 talloc_free(p2);
5757 return ret;
5760 static bool test_Forms_winreg(struct torture_context *tctx,
5761 struct dcerpc_binding_handle *b,
5762 struct policy_handle *handle,
5763 bool print_server,
5764 const char *printer_name)
5766 struct dcerpc_pipe *p2;
5767 bool ret = true;
5768 struct policy_handle hive_handle;
5769 struct dcerpc_binding_handle *b2;
5771 torture_assert_ntstatus_ok(tctx,
5772 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5773 "could not open winreg pipe");
5774 b2 = p2->binding_handle;
5776 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5778 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5780 test_winreg_CloseKey(tctx, b2, &hive_handle);
5782 talloc_free(p2);
5784 return ret;
5787 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5788 struct dcerpc_pipe *p,
5789 struct policy_handle *handle,
5790 const char *printer_name)
5792 struct dcerpc_binding_handle *b = p->binding_handle;
5793 struct dcerpc_pipe *p2;
5794 bool ret = true;
5795 struct policy_handle hive_handle;
5796 struct dcerpc_binding_handle *b2;
5798 torture_assert_ntstatus_ok(tctx,
5799 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5800 "could not open winreg pipe");
5801 b2 = p2->binding_handle;
5803 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5805 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5807 test_winreg_CloseKey(tctx, b2, &hive_handle);
5809 talloc_free(p2);
5811 return ret;
5814 static bool test_PrintserverInfo_winreg(struct torture_context *tctx,
5815 struct dcerpc_pipe *p,
5816 struct policy_handle *handle)
5818 struct dcerpc_binding_handle *b = p->binding_handle;
5819 struct dcerpc_pipe *p2;
5820 bool ret = true;
5821 struct policy_handle hive_handle;
5822 struct dcerpc_binding_handle *b2;
5824 torture_assert_ntstatus_ok(tctx,
5825 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5826 "could not open winreg pipe");
5827 b2 = p2->binding_handle;
5829 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5831 ret = test_GetPrintserverInfo_winreg(tctx, b, handle, b2, &hive_handle);
5833 test_winreg_CloseKey(tctx, b2, &hive_handle);
5835 talloc_free(p2);
5837 return ret;
5841 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5842 struct dcerpc_pipe *p,
5843 struct policy_handle *handle,
5844 const char *printer_name,
5845 const char *driver_name,
5846 const char *environment,
5847 enum spoolss_DriverOSVersion version)
5849 struct dcerpc_binding_handle *b = p->binding_handle;
5850 struct dcerpc_pipe *p2;
5851 bool ret = true;
5852 struct policy_handle hive_handle;
5853 struct dcerpc_binding_handle *b2;
5855 torture_assert_ntstatus_ok(tctx,
5856 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5857 "could not open winreg pipe");
5858 b2 = p2->binding_handle;
5860 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5862 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5864 test_winreg_CloseKey(tctx, b2, &hive_handle);
5866 talloc_free(p2);
5868 return ret;
5871 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5872 struct dcerpc_binding_handle *b,
5873 const char *environment)
5875 struct dcerpc_pipe *p2;
5876 bool ret = true;
5877 struct policy_handle hive_handle;
5878 struct dcerpc_binding_handle *b2;
5880 torture_assert_ntstatus_ok(tctx,
5881 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5882 "could not open winreg pipe");
5883 b2 = p2->binding_handle;
5885 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5887 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5889 test_winreg_CloseKey(tctx, b2, &hive_handle);
5891 talloc_free(p2);
5893 return ret;
5896 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5897 struct dcerpc_pipe *p,
5898 struct policy_handle *handle,
5899 const char *printer_name)
5901 struct spoolss_SetPrinterInfoCtr info_ctr;
5902 struct spoolss_DevmodeContainer devmode_ctr;
5903 struct sec_desc_buf secdesc_ctr;
5904 union spoolss_SetPrinterInfo sinfo;
5905 union spoolss_PrinterInfo info;
5906 struct dcerpc_binding_handle *b = p->binding_handle;
5907 const char *pname;
5909 ZERO_STRUCT(info_ctr);
5910 ZERO_STRUCT(devmode_ctr);
5911 ZERO_STRUCT(secdesc_ctr);
5913 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5915 torture_assert(tctx,
5916 test_GetPrinter_level(tctx, b, handle, 2, &info),
5917 "failed to query Printer level 2");
5919 torture_assert(tctx,
5920 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5921 "failed to convert");
5923 info_ctr.level = 2;
5924 info_ctr.info = sinfo;
5926 #define TEST_SZ(wname, iname) \
5927 do {\
5928 enum winreg_Type type;\
5929 uint8_t *data;\
5930 uint32_t needed;\
5931 DATA_BLOB blob;\
5932 const char *str;\
5933 torture_assert(tctx,\
5934 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5935 "failed to query");\
5936 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5937 blob = data_blob_const(data, needed);\
5938 torture_assert(tctx,\
5939 pull_reg_sz(tctx, &blob, &str),\
5940 "failed to pull REG_SZ");\
5941 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5942 } while(0);
5945 #define TEST_SET_SZ(wname, iname, val) \
5946 do {\
5947 enum winreg_Type type;\
5948 uint8_t *data;\
5949 uint32_t needed;\
5950 DATA_BLOB blob;\
5951 const char *str;\
5952 sinfo.info2->iname = val;\
5953 torture_assert(tctx,\
5954 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5955 "failed to call SetPrinter");\
5956 torture_assert(tctx,\
5957 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5958 "failed to query");\
5959 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5960 blob = data_blob_const(data, needed);\
5961 torture_assert(tctx,\
5962 pull_reg_sz(tctx, &blob, &str),\
5963 "failed to pull REG_SZ");\
5964 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5965 } while(0);
5967 #define TEST_SET_DWORD(wname, iname, val) \
5968 do {\
5969 enum winreg_Type type;\
5970 uint8_t *data;\
5971 uint32_t needed;\
5972 uint32_t value;\
5973 sinfo.info2->iname = val;\
5974 torture_assert(tctx,\
5975 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5976 "failed to call SetPrinter");\
5977 torture_assert(tctx,\
5978 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5979 "failed to query");\
5980 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5981 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5982 value = IVAL(data, 0); \
5983 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5984 } while(0);
5986 TEST_SET_SZ("description", comment, "newval");
5987 TEST_SET_SZ("location", location, "newval");
5988 TEST_SET_SZ("driverName", drivername, "newval");
5989 /* TEST_SET_DWORD("priority", priority, 25); */
5991 torture_assert(tctx,
5992 test_GetPrinter_level(tctx, b, handle, 2, &info),
5993 "failed to query Printer level 2");
5995 TEST_SZ("description", info.info2.comment);
5996 TEST_SZ("driverName", info.info2.drivername);
5997 TEST_SZ("location", info.info2.location);
5999 pname = strrchr(info.info2.printername, '\\');
6000 if (pname == NULL) {
6001 pname = info.info2.printername;
6002 } else {
6003 pname++;
6005 TEST_SZ("printerName", pname);
6006 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
6007 /* TEST_SZ("printShareName", info.info2.sharename); */
6009 /* FIXME gd: complete the list */
6011 #undef TEST_SZ
6012 #undef TEST_SET_SZ
6013 #undef TEST_DWORD
6015 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
6017 return true;
6020 static bool test_print_processors_winreg(struct torture_context *tctx,
6021 void *private_data)
6023 struct test_spoolss_context *ctx =
6024 talloc_get_type_abort(private_data, struct test_spoolss_context);
6025 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6026 struct dcerpc_binding_handle *b = p->binding_handle;
6028 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
6031 static bool test_AddPrintProcessor(struct torture_context *tctx,
6032 struct dcerpc_binding_handle *b,
6033 const char *environment,
6034 const char *path_name,
6035 const char *print_processor_name,
6036 WERROR expected_error)
6038 struct spoolss_AddPrintProcessor r;
6040 r.in.server = NULL;
6041 r.in.architecture = environment;
6042 r.in.path_name = path_name;
6043 r.in.print_processor_name = print_processor_name;
6045 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
6046 print_processor_name);
6048 torture_assert_ntstatus_ok(tctx,
6049 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
6050 "spoolss_AddPrintProcessor failed");
6051 torture_assert_werr_equal(tctx, r.out.result, expected_error,
6052 "spoolss_AddPrintProcessor failed");
6054 return true;
6057 static bool test_DeletePrintProcessor(struct torture_context *tctx,
6058 struct dcerpc_binding_handle *b,
6059 const char *environment,
6060 const char *print_processor_name,
6061 WERROR expected_error)
6063 struct spoolss_DeletePrintProcessor r;
6065 r.in.server = NULL;
6066 r.in.architecture = environment;
6067 r.in.print_processor_name = print_processor_name;
6069 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
6070 print_processor_name);
6072 torture_assert_ntstatus_ok(tctx,
6073 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
6074 "spoolss_DeletePrintProcessor failed");
6075 torture_assert_werr_equal(tctx, r.out.result, expected_error,
6076 "spoolss_DeletePrintProcessor failed");
6078 return true;
6081 static bool test_add_print_processor(struct torture_context *tctx,
6082 void *private_data)
6084 struct test_spoolss_context *ctx =
6085 talloc_get_type_abort(private_data, struct test_spoolss_context);
6086 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6087 struct dcerpc_binding_handle *b = p->binding_handle;
6088 int i;
6090 struct {
6091 const char *environment;
6092 const char *path_name;
6093 const char *print_processor_name;
6094 WERROR expected_add_result;
6095 WERROR expected_del_result;
6096 } tests[] = {
6098 .environment = ctx->environment,
6099 .path_name = "",
6100 .print_processor_name = "winprint",
6101 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
6102 .expected_del_result = WERR_CAN_NOT_COMPLETE
6104 .environment = ctx->environment,
6105 .path_name = "",
6106 .print_processor_name = "unknown",
6107 .expected_add_result = WERR_MOD_NOT_FOUND,
6108 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
6112 for (i=0; i < ARRAY_SIZE(tests); i++) {
6113 torture_assert(tctx,
6114 test_AddPrintProcessor(tctx, b,
6115 tests[i].environment,
6116 tests[i].path_name,
6117 tests[i].print_processor_name,
6118 tests[i].expected_add_result),
6119 "add print processor failed");
6120 torture_assert(tctx,
6121 test_DeletePrintProcessor(tctx, b,
6122 tests[i].environment,
6123 tests[i].print_processor_name,
6124 tests[i].expected_del_result),
6125 "delete print processor failed");
6128 return true;
6131 static bool test_AddPerMachineConnection(struct torture_context *tctx,
6132 struct dcerpc_binding_handle *b,
6133 const char *servername,
6134 const char *printername,
6135 const char *printserver,
6136 const char *provider,
6137 WERROR expected_error)
6139 struct spoolss_AddPerMachineConnection r;
6140 const char *composed_printername = printername;
6142 if (servername != NULL) {
6143 composed_printername = talloc_asprintf(tctx, "%s\\%s",
6144 servername,
6145 printername);
6147 r.in.server = servername;
6148 r.in.printername = composed_printername;
6149 r.in.printserver = printserver;
6150 r.in.provider = provider;
6152 torture_comment(tctx, "Testing AddPerMachineConnection(%s|%s|%s)\n",
6153 printername, printserver, provider);
6155 torture_assert_ntstatus_ok(tctx,
6156 dcerpc_spoolss_AddPerMachineConnection_r(b, tctx, &r),
6157 "spoolss_AddPerMachineConnection failed");
6158 torture_assert_werr_equal(tctx, r.out.result, expected_error,
6159 "spoolss_AddPerMachineConnection failed");
6161 return true;
6164 static bool test_DeletePerMachineConnection(struct torture_context *tctx,
6165 struct dcerpc_binding_handle *b,
6166 const char *servername,
6167 const char *printername,
6168 WERROR expected_error)
6170 struct spoolss_DeletePerMachineConnection r;
6171 const char *composed_printername = printername;
6173 if (servername != NULL) {
6174 composed_printername = talloc_asprintf(tctx, "%s\\%s",
6175 servername,
6176 printername);
6179 r.in.server = servername;
6180 r.in.printername = composed_printername;
6182 torture_comment(tctx, "Testing DeletePerMachineConnection(%s)\n",
6183 printername);
6185 torture_assert_ntstatus_ok(tctx,
6186 dcerpc_spoolss_DeletePerMachineConnection_r(b, tctx, &r),
6187 "spoolss_DeletePerMachineConnection failed");
6188 torture_assert_werr_equal(tctx, r.out.result, expected_error,
6189 "spoolss_DeletePerMachineConnection failed");
6191 return true;
6194 static bool test_EnumPerMachineConnections(struct torture_context *tctx,
6195 struct dcerpc_binding_handle *b,
6196 const char *servername)
6198 struct spoolss_EnumPerMachineConnections r;
6199 DATA_BLOB blob = data_blob_null;
6200 struct spoolss_PrinterInfo4 *info;
6201 uint32_t needed;
6202 uint32_t count;
6204 r.in.server = servername;
6205 r.in.buffer = &blob;
6206 r.in.offered = 0;
6208 r.out.info = &info;
6209 r.out.needed = &needed;
6210 r.out.count = &count;
6212 torture_comment(tctx, "Testing EnumPerMachineConnections(%s)\n",
6213 servername);
6215 torture_assert_ntstatus_ok(tctx,
6216 dcerpc_spoolss_EnumPerMachineConnections_r(b, tctx, &r),
6217 "spoolss_EnumPerMachineConnections failed");
6218 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6219 blob = data_blob_talloc_zero(tctx, needed);
6220 r.in.buffer = &blob;
6221 r.in.offered = needed;
6223 torture_assert_ntstatus_ok(tctx,
6224 dcerpc_spoolss_EnumPerMachineConnections_r(b, tctx, &r),
6225 "spoolss_EnumPerMachineConnections failed");
6227 torture_assert_werr_ok(tctx, r.out.result,
6228 "spoolss_EnumPerMachineConnections failed");
6230 return true;
6233 static bool test_addpermachineconnection(struct torture_context *tctx,
6234 void *private_data)
6236 struct test_spoolss_context *ctx =
6237 talloc_get_type_abort(private_data, struct test_spoolss_context);
6238 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6239 struct dcerpc_binding_handle *b = p->binding_handle;
6240 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6241 int i;
6243 struct {
6244 const char *servername;
6245 const char *printername;
6246 const char *printserver;
6247 const char *provider;
6248 WERROR expected_add_result;
6249 WERROR expected_del_result;
6250 } tests[] = {
6252 .servername = NULL,
6253 .printername = "foo",
6254 .printserver = "",
6255 .provider = "unknown",
6256 .expected_add_result = WERR_INVALID_PRINTER_NAME,
6257 .expected_del_result = WERR_INVALID_PRINTER_NAME
6259 .servername = NULL,
6260 .printername = "Microsoft Print to PDF",
6261 .printserver = "samba.org",
6262 .provider = "unknown",
6263 .expected_add_result = WERR_INVALID_PRINTER_NAME,
6264 .expected_del_result = WERR_INVALID_PRINTER_NAME
6266 .servername = NULL,
6267 .printername = "Microsoft Print to PDF",
6268 .printserver = "samba.org",
6269 .provider = "",
6270 .expected_add_result = WERR_INVALID_PRINTER_NAME,
6271 .expected_del_result = WERR_INVALID_PRINTER_NAME
6273 .servername = server_name_slash,
6274 .printername = "foo",
6275 .printserver = "",
6276 .provider = "unknown",
6277 .expected_add_result = WERR_FILE_NOT_FOUND,
6278 .expected_del_result = WERR_INVALID_PRINTER_NAME
6280 .servername = server_name_slash,
6281 .printername = "foo",
6282 .printserver = "",
6283 .provider = "",
6284 .expected_add_result = WERR_OK,
6285 .expected_del_result = WERR_OK
6287 .servername = server_name_slash,
6288 .printername = "Microsoft Print to PDF",
6289 .printserver = "samba.org",
6290 .provider = "unknown",
6291 .expected_add_result = WERR_FILE_NOT_FOUND,
6292 .expected_del_result = WERR_INVALID_PRINTER_NAME
6294 .servername = server_name_slash,
6295 .printername = "Microsoft Print to PDF",
6296 .printserver = "samba.org",
6297 .provider = "",
6298 .expected_add_result = WERR_OK,
6299 .expected_del_result = WERR_OK
6303 for (i=0; i < ARRAY_SIZE(tests); i++) {
6304 torture_assert(tctx,
6305 test_AddPerMachineConnection(tctx, b,
6306 tests[i].servername,
6307 tests[i].printername,
6308 tests[i].printserver,
6309 tests[i].provider,
6310 tests[i].expected_add_result),
6311 "add per machine connection failed");
6312 torture_assert(tctx,
6313 test_EnumPerMachineConnections(tctx, b,
6314 tests[i].servername),
6315 "enum per machine connections failed");
6316 torture_assert(tctx,
6317 test_DeletePerMachineConnection(tctx, b,
6318 tests[i].servername,
6319 tests[i].printername,
6320 tests[i].expected_del_result),
6321 "delete per machine connection failed");
6322 torture_assert(tctx,
6323 test_EnumPerMachineConnections(tctx, b,
6324 tests[i].servername),
6325 "enum per machine connections failed");
6328 return true;
6331 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
6332 struct dcerpc_binding_handle *b,
6333 struct policy_handle *handle,
6334 uint32_t *change_id)
6336 enum winreg_Type type;
6337 uint8_t *data;
6338 uint32_t needed;
6340 torture_assert(tctx,
6341 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
6342 "failed to call GetPrinterData");
6344 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6345 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6347 *change_id = IVAL(data, 0);
6349 return true;
6352 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
6353 struct dcerpc_pipe *p,
6354 struct policy_handle *handle,
6355 uint32_t *change_id)
6357 enum winreg_Type type = REG_NONE;
6358 uint8_t *data = NULL;
6359 uint32_t needed = 0;
6361 torture_assert(tctx,
6362 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
6363 "failed to call GetPrinterData");
6365 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6366 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6368 *change_id = IVAL(data, 0);
6370 return true;
6373 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
6374 struct dcerpc_binding_handle *b,
6375 struct policy_handle *handle,
6376 uint32_t *change_id)
6378 union spoolss_PrinterInfo info;
6380 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
6381 "failed to query Printer level 0");
6383 *change_id = info.info0.change_id;
6385 return true;
6388 static bool test_ChangeID(struct torture_context *tctx,
6389 struct dcerpc_pipe *p,
6390 struct policy_handle *handle)
6392 uint32_t change_id, change_id_ex, change_id_info;
6393 uint32_t change_id2, change_id_ex2, change_id_info2;
6394 union spoolss_PrinterInfo info;
6395 const char *comment;
6396 struct dcerpc_binding_handle *b = p->binding_handle;
6398 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
6400 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6401 "failed to query for ChangeID");
6402 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6403 "failed to query for ChangeID");
6404 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6405 "failed to query for ChangeID");
6407 torture_assert_int_equal(tctx, change_id, change_id_ex,
6408 "change_ids should all be equal");
6409 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6410 "change_ids should all be equal");
6413 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6415 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6416 "failed to query for ChangeID");
6417 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6418 "failed to query Printer level 2");
6419 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6420 "failed to query for ChangeID");
6421 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6422 "failed to query for ChangeID");
6423 torture_assert_int_equal(tctx, change_id, change_id_ex,
6424 "change_id should not have changed");
6425 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6426 "change_id should not have changed");
6429 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6431 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6432 "failed to query for ChangeID");
6433 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6434 "failed to query for ChangeID");
6435 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6436 "failed to query for ChangeID");
6437 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6438 "failed to query Printer level 2");
6439 comment = talloc_strdup(tctx, info.info2.comment);
6442 struct spoolss_SetPrinterInfoCtr info_ctr;
6443 struct spoolss_DevmodeContainer devmode_ctr;
6444 struct sec_desc_buf secdesc_ctr;
6445 union spoolss_SetPrinterInfo sinfo;
6447 ZERO_STRUCT(info_ctr);
6448 ZERO_STRUCT(devmode_ctr);
6449 ZERO_STRUCT(secdesc_ctr);
6452 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6453 sinfo.info2->comment = "torture_comment";
6455 info_ctr.level = 2;
6456 info_ctr.info = sinfo;
6458 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6459 "failed to call SetPrinter");
6461 sinfo.info2->comment = comment;
6463 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6464 "failed to call SetPrinter");
6468 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6469 "failed to query for ChangeID");
6470 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6471 "failed to query for ChangeID");
6472 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6473 "failed to query for ChangeID");
6475 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6476 "change_ids should all be equal");
6477 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6478 "change_ids should all be equal");
6480 torture_assert(tctx, (change_id < change_id2),
6481 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6482 change_id2, change_id));
6483 torture_assert(tctx, (change_id_ex < change_id_ex2),
6484 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6485 change_id_ex2, change_id_ex));
6486 torture_assert(tctx, (change_id_info < change_id_info2),
6487 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6488 change_id_info2, change_id_info));
6490 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6492 return true;
6495 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6496 struct dcerpc_pipe *p,
6497 struct policy_handle *handle)
6499 NTSTATUS status;
6500 struct cli_credentials *anon_creds;
6501 const struct dcerpc_binding *binding2;
6502 struct dcerpc_pipe *p2;
6503 struct spoolss_ClosePrinter cp;
6505 /* only makes sense on SMB */
6506 if (dcerpc_binding_handle_get_transport(p->binding_handle) != NCACN_NP) {
6507 return true;
6510 torture_comment(tctx, "Testing close on secondary pipe\n");
6512 anon_creds = cli_credentials_init_anon(tctx);
6513 torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
6515 binding2 = dcerpc_binding_handle_get_binding(p->binding_handle);
6516 status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_spoolss,
6517 anon_creds, tctx->lp_ctx,
6518 tctx, &p2);
6519 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6521 cp.in.handle = handle;
6522 cp.out.handle = handle;
6524 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6525 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6526 "ERROR: Allowed close on secondary connection");
6528 talloc_free(p2);
6530 return true;
6533 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6534 struct dcerpc_binding_handle *b, const char *name)
6536 NTSTATUS status;
6537 struct spoolss_OpenPrinter op;
6538 struct spoolss_OpenPrinterEx opEx;
6539 struct policy_handle handle;
6540 bool ret = true;
6542 op.in.printername = name;
6543 op.in.datatype = NULL;
6544 op.in.devmode_ctr.devmode= NULL;
6545 op.in.access_mask = 0;
6546 op.out.handle = &handle;
6548 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6550 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6551 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6552 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6553 "unexpected result");
6555 if (W_ERROR_IS_OK(op.out.result)) {
6556 ret &=test_ClosePrinter(tctx, b, &handle);
6559 opEx.in.printername = name;
6560 opEx.in.datatype = NULL;
6561 opEx.in.devmode_ctr.devmode = NULL;
6562 opEx.in.access_mask = 0;
6563 opEx.in.userlevel_ctr.level = 1;
6564 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6565 opEx.out.handle = &handle;
6567 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6569 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6570 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6571 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAMETER,
6572 "unexpected result");
6574 if (W_ERROR_IS_OK(opEx.out.result)) {
6575 ret &=test_ClosePrinter(tctx, b, &handle);
6578 return ret;
6581 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6582 void *private_data)
6584 struct test_spoolss_context *ctx =
6585 talloc_get_type_abort(private_data, struct test_spoolss_context);
6587 const char *badnames[] = {
6588 "__INVALID_PRINTER__",
6589 "\\\\__INVALID_HOST__",
6591 "\\\\\\",
6592 "\\\\\\__INVALID_PRINTER__"
6594 const char *badname;
6595 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6596 const char *server_name = dcerpc_server_name(p);
6597 struct dcerpc_binding_handle *b = p->binding_handle;
6598 int i;
6600 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6601 torture_assert(tctx,
6602 test_OpenPrinter_badname(tctx, b, badnames[i]),
6603 "");
6606 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6607 torture_assert(tctx,
6608 test_OpenPrinter_badname(tctx, b, badname),
6609 "");
6611 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6612 torture_assert(tctx,
6613 test_OpenPrinter_badname(tctx, b, badname),
6614 "");
6616 return true;
6619 static bool test_OpenPrinter(struct torture_context *tctx,
6620 struct dcerpc_pipe *p,
6621 const char *name,
6622 const char *environment,
6623 bool open_only)
6625 NTSTATUS status;
6626 struct spoolss_OpenPrinter r;
6627 struct policy_handle handle;
6628 bool ret = true;
6629 struct dcerpc_binding_handle *b = p->binding_handle;
6631 r.in.printername = name;
6632 r.in.datatype = NULL;
6633 r.in.devmode_ctr.devmode= NULL;
6634 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6635 r.out.handle = &handle;
6637 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6639 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6641 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6643 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6645 if (open_only) {
6646 goto close_printer;
6649 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6650 ret = false;
6653 if (!torture_setting_bool(tctx, "samba3", false)) {
6654 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6655 ret = false;
6659 close_printer:
6660 if (!test_ClosePrinter(tctx, b, &handle)) {
6661 ret = false;
6664 return ret;
6667 static bool test_OpenPrinterEx(struct torture_context *tctx,
6668 struct dcerpc_binding_handle *b,
6669 const char *printername,
6670 const char *datatype,
6671 struct spoolss_DeviceMode *devmode,
6672 uint32_t access_mask,
6673 struct spoolss_UserLevelCtr *userlevel_ctr,
6674 struct policy_handle *handle,
6675 WERROR expected_result)
6677 struct spoolss_OpenPrinterEx r;
6679 r.in.printername = printername;
6680 r.in.datatype = datatype;
6681 r.in.devmode_ctr.devmode= devmode;
6682 r.in.access_mask = access_mask;
6683 r.in.userlevel_ctr = *userlevel_ctr;
6684 r.out.handle = handle;
6686 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6688 torture_assert_ntstatus_ok(tctx,
6689 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6690 "OpenPrinterEx failed");
6692 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6693 "OpenPrinterEx failed");
6695 return true;
6698 static bool call_OpenPrinterEx(struct torture_context *tctx,
6699 struct dcerpc_pipe *p,
6700 const char *name,
6701 struct spoolss_DeviceMode *devmode,
6702 struct policy_handle *handle)
6704 struct spoolss_UserLevelCtr userlevel_ctr;
6705 struct spoolss_UserLevel1 userlevel1;
6706 struct dcerpc_binding_handle *b = p->binding_handle;
6708 userlevel1.size = 1234;
6709 userlevel1.client = "hello";
6710 userlevel1.user = "spottyfoot!";
6711 userlevel1.build = 1;
6712 userlevel1.major = 2;
6713 userlevel1.minor = 3;
6714 userlevel1.processor = 4;
6716 userlevel_ctr.level = 1;
6717 userlevel_ctr.user_info.level1 = &userlevel1;
6719 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6720 SEC_FLAG_MAXIMUM_ALLOWED,
6721 &userlevel_ctr,
6722 handle,
6723 WERR_OK);
6726 static bool test_printer_rename(struct torture_context *tctx,
6727 void *private_data)
6729 struct torture_printer_context *t =
6730 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6731 struct dcerpc_pipe *p = t->spoolss_pipe;
6733 bool ret = true;
6734 union spoolss_PrinterInfo info;
6735 union spoolss_SetPrinterInfo sinfo;
6736 struct spoolss_SetPrinterInfoCtr info_ctr;
6737 struct spoolss_DevmodeContainer devmode_ctr;
6738 struct sec_desc_buf secdesc_ctr;
6739 const char *printer_name;
6740 const char *printer_name_orig;
6741 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6742 struct policy_handle new_handle;
6743 const char *q;
6744 struct dcerpc_binding_handle *b = p->binding_handle;
6746 ZERO_STRUCT(devmode_ctr);
6747 ZERO_STRUCT(secdesc_ctr);
6749 torture_comment(tctx, "Testing Printer rename operations\n");
6751 torture_assert(tctx,
6752 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6753 "failed to call GetPrinter level 2");
6755 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6757 q = strrchr(info.info2.printername, '\\');
6758 if (q) {
6759 torture_warning(tctx,
6760 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6763 torture_assert(tctx,
6764 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6766 sinfo.info2->printername = printer_name_new;
6768 info_ctr.level = 2;
6769 info_ctr.info = sinfo;
6771 torture_assert(tctx,
6772 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6773 "failed to call SetPrinter level 2");
6775 torture_assert(tctx,
6776 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6777 "failed to call GetPrinter level 2");
6779 printer_name = talloc_strdup(tctx, info.info2.printername);
6781 q = strrchr(info.info2.printername, '\\');
6782 if (q) {
6783 torture_warning(tctx,
6784 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6785 q++;
6786 printer_name = q;
6789 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6790 "new printer name was not set");
6792 /* samba currently cannot fully rename printers */
6793 if (!torture_setting_bool(tctx, "samba3", false)) {
6794 torture_assert(tctx,
6795 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6796 "still can open printer with oldname after rename");
6797 } else {
6798 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6801 torture_assert(tctx,
6802 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6803 "failed to open printer with new name");
6805 torture_assert(tctx,
6806 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6807 "failed to call GetPrinter level 2");
6809 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6810 "new printer name was not set");
6812 torture_assert(tctx,
6813 test_ClosePrinter(tctx, b, &new_handle),
6814 "failed to close printer");
6816 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6818 return ret;
6821 static bool test_openprinter(struct torture_context *tctx,
6822 struct dcerpc_binding_handle *b,
6823 const char *real_printername)
6825 struct spoolss_UserLevelCtr userlevel_ctr;
6826 struct policy_handle handle;
6827 struct spoolss_UserLevel1 userlevel1;
6828 const char *printername = NULL;
6829 int i;
6831 struct {
6832 const char *suffix;
6833 WERROR expected_result;
6834 } tests[] = {
6836 .suffix = "rubbish",
6837 .expected_result = WERR_INVALID_PRINTER_NAME
6839 .suffix = ", LocalOnl",
6840 .expected_result = WERR_INVALID_PRINTER_NAME
6842 .suffix = ", localOnly",
6843 .expected_result = WERR_INVALID_PRINTER_NAME
6845 .suffix = ", localonl",
6846 .expected_result = WERR_INVALID_PRINTER_NAME
6848 .suffix = ",LocalOnl",
6849 .expected_result = WERR_INVALID_PRINTER_NAME
6851 .suffix = ",localOnl2",
6852 .expected_result = WERR_INVALID_PRINTER_NAME
6854 .suffix = ", DrvConver2t",
6855 .expected_result = WERR_INVALID_PRINTER_NAME
6857 .suffix = ", drvconvert",
6858 .expected_result = WERR_INVALID_PRINTER_NAME
6860 .suffix = ",drvconvert",
6861 .expected_result = WERR_INVALID_PRINTER_NAME
6863 .suffix = ", DrvConvert",
6864 .expected_result = WERR_OK
6866 .suffix = " , DrvConvert",
6867 .expected_result = WERR_INVALID_PRINTER_NAME
6869 .suffix = ",DrvConvert",
6870 .expected_result = WERR_OK
6872 .suffix = ", DrvConvertsadfasdf",
6873 .expected_result = WERR_OK
6875 .suffix = ",DrvConvertasdfasd",
6876 .expected_result = WERR_OK
6878 .suffix = ", LocalOnly",
6879 .expected_result = WERR_OK
6881 .suffix = " , LocalOnly",
6882 .expected_result = WERR_INVALID_PRINTER_NAME
6884 .suffix = ",LocalOnly",
6885 .expected_result = WERR_OK
6887 .suffix = ", LocalOnlysagi4gjfkd",
6888 .expected_result = WERR_OK
6890 .suffix = ",LocalOnlysagi4gjfkd",
6891 .expected_result = WERR_OK
6895 userlevel1.size = 1234;
6896 userlevel1.client = "hello";
6897 userlevel1.user = "spottyfoot!";
6898 userlevel1.build = 1;
6899 userlevel1.major = 2;
6900 userlevel1.minor = 3;
6901 userlevel1.processor = 4;
6903 userlevel_ctr.level = 1;
6904 userlevel_ctr.user_info.level1 = &userlevel1;
6906 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6908 torture_assert(tctx,
6909 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6910 &userlevel_ctr, &handle,
6911 WERR_OK),
6912 "OpenPrinterEx failed");
6913 test_ClosePrinter(tctx, b, &handle);
6915 for (i=0; i < ARRAY_SIZE(tests); i++) {
6917 printername = talloc_asprintf(tctx, "%s%s",
6918 real_printername,
6919 tests[i].suffix);
6921 torture_assert(tctx,
6922 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6923 &userlevel_ctr, &handle,
6924 tests[i].expected_result),
6925 "OpenPrinterEx failed");
6926 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6927 test_ClosePrinter(tctx, b, &handle);
6931 return true;
6935 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6936 struct dcerpc_pipe *p,
6937 const char *name,
6938 const char *environment)
6940 struct policy_handle handle;
6941 bool ret = true;
6942 struct dcerpc_binding_handle *b = p->binding_handle;
6944 if (!test_openprinter(tctx, b, name)) {
6945 return false;
6948 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6949 return false;
6952 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6953 ret = false;
6956 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6957 ret = false;
6960 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6961 ret = false;
6964 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6965 ret = false;
6968 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6969 ret = false;
6972 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6973 ret = false;
6976 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6977 ret = false;
6980 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6981 ret = false;
6984 if (!test_printer_all_keys(tctx, b, &handle)) {
6985 ret = false;
6988 if (!test_PausePrinter(tctx, b, &handle)) {
6989 ret = false;
6992 if (!test_DoPrintTest(tctx, b, &handle)) {
6993 ret = false;
6996 if (!test_ResumePrinter(tctx, b, &handle)) {
6997 ret = false;
7000 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
7001 ret = false;
7004 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
7005 ret = false;
7008 if (!torture_setting_bool(tctx, "samba3", false)) {
7009 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
7010 ret = false;
7014 if (!test_ClosePrinter(tctx, b, &handle)) {
7015 ret = false;
7018 return ret;
7021 static bool test_EnumPrinters_old(struct torture_context *tctx,
7022 void *private_data)
7024 struct test_spoolss_context *ctx =
7025 talloc_get_type_abort(private_data, struct test_spoolss_context);
7026 struct spoolss_EnumPrinters r;
7027 NTSTATUS status;
7028 uint16_t levels[] = {1, 2, 4, 5};
7029 int i;
7030 bool ret = true;
7031 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7032 struct dcerpc_binding_handle *b = p->binding_handle;
7034 for (i=0;i<ARRAY_SIZE(levels);i++) {
7035 union spoolss_PrinterInfo *info;
7036 int j;
7037 uint32_t needed;
7038 uint32_t count;
7040 r.in.flags = PRINTER_ENUM_LOCAL;
7041 r.in.server = "";
7042 r.in.level = levels[i];
7043 r.in.buffer = NULL;
7044 r.in.offered = 0;
7045 r.out.needed = &needed;
7046 r.out.count = &count;
7047 r.out.info = &info;
7049 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
7051 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
7052 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
7054 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7055 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7056 r.in.buffer = &blob;
7057 r.in.offered = needed;
7058 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
7061 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
7063 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
7065 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
7067 if (!info) {
7068 torture_comment(tctx, "No printers returned\n");
7069 return true;
7072 for (j=0;j<count;j++) {
7073 if (r.in.level == 1) {
7074 char *unc = talloc_strdup(tctx, info[j].info1.name);
7075 char *slash, *name, *full_name;
7076 name = unc;
7077 if (unc[0] == '\\' && unc[1] == '\\') {
7078 unc +=2;
7080 slash = strchr(unc, '\\');
7081 if (slash) {
7082 slash++;
7083 name = slash;
7085 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
7086 dcerpc_server_name(p), name);
7087 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
7088 ret = false;
7090 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
7091 ret = false;
7093 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
7094 ret = false;
7096 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
7097 ret = false;
7103 return ret;
7106 static bool test_EnumPrinters_level(struct torture_context *tctx,
7107 struct dcerpc_binding_handle *b,
7108 uint32_t flags,
7109 const char *servername,
7110 uint32_t level,
7111 uint32_t *count_p,
7112 union spoolss_PrinterInfo **info_p)
7114 struct spoolss_EnumPrinters r;
7115 union spoolss_PrinterInfo *info;
7116 uint32_t needed;
7117 uint32_t count;
7119 r.in.flags = flags;
7120 r.in.server = servername;
7121 r.in.level = level;
7122 r.in.buffer = NULL;
7123 r.in.offered = 0;
7124 r.out.needed = &needed;
7125 r.out.count = &count;
7126 r.out.info = &info;
7128 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
7129 r.in.server, r.in.level);
7131 torture_assert_ntstatus_ok(tctx,
7132 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
7133 "EnumPrinters failed");
7134 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7135 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7136 r.in.buffer = &blob;
7137 r.in.offered = needed;
7138 torture_assert_ntstatus_ok(tctx,
7139 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
7140 "EnumPrinters failed");
7143 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
7145 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
7147 if (count_p) {
7148 *count_p = count;
7150 if (info_p) {
7151 *info_p = info;
7154 return true;
7157 static const char *get_short_printername(struct torture_context *tctx,
7158 const char *name)
7160 const char *short_name;
7162 if (name[0] == '\\' && name[1] == '\\') {
7163 name += 2;
7164 short_name = strchr(name, '\\');
7165 if (short_name) {
7166 return talloc_strdup(tctx, short_name+1);
7170 return name;
7173 static const char *get_full_printername(struct torture_context *tctx,
7174 const char *name)
7176 const char *full_name = talloc_strdup(tctx, name);
7177 char *p;
7179 if (name && name[0] == '\\' && name[1] == '\\') {
7180 name += 2;
7181 p = strchr(name, '\\');
7182 if (p) {
7183 return full_name;
7187 return NULL;
7190 static bool test_OnePrinter_servername(struct torture_context *tctx,
7191 struct dcerpc_pipe *p,
7192 struct dcerpc_binding_handle *b,
7193 const char *servername,
7194 const char *printername)
7196 union spoolss_PrinterInfo info;
7197 const char *short_name = get_short_printername(tctx, printername);
7198 const char *full_name = get_full_printername(tctx, printername);
7200 if (short_name) {
7201 struct policy_handle handle;
7202 torture_assert(tctx,
7203 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
7204 "failed to open printer");
7206 torture_assert(tctx,
7207 test_GetPrinter_level(tctx, b, &handle, 2, &info),
7208 "failed to get printer info");
7210 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
7211 "unexpected servername");
7212 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
7213 "unexpected printername");
7215 if (info.info2.devmode) {
7216 const char *expected_devicename;
7217 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
7218 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
7219 "unexpected devicemode devicename");
7222 torture_assert(tctx,
7223 test_ClosePrinter(tctx, b, &handle),
7224 "failed to close printer");
7227 if (full_name) {
7228 struct policy_handle handle;
7230 torture_assert(tctx,
7231 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
7232 "failed to open printer");
7234 torture_assert(tctx,
7235 test_GetPrinter_level(tctx, b, &handle, 2, &info),
7236 "failed to get printer info");
7238 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
7239 "unexpected servername");
7240 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
7241 "unexpected printername");
7243 if (info.info2.devmode) {
7244 const char *expected_devicename;
7245 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
7246 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
7247 "unexpected devicemode devicename");
7250 torture_assert(tctx,
7251 test_ClosePrinter(tctx, b, &handle),
7252 "failed to close printer");
7255 return true;
7258 static bool test_EnumPrinters_servername(struct torture_context *tctx,
7259 void *private_data)
7261 struct test_spoolss_context *ctx =
7262 talloc_get_type_abort(private_data, struct test_spoolss_context);
7263 int i;
7264 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7265 struct dcerpc_binding_handle *b = p->binding_handle;
7266 uint32_t count;
7267 union spoolss_PrinterInfo *info;
7268 const char *servername;
7269 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
7271 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
7273 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7275 torture_assert(tctx,
7276 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
7277 "failed to enumerate printers");
7279 for (i=0; i < count; i++) {
7281 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
7282 "unexpected servername");
7284 torture_assert(tctx,
7285 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7286 "failed to check printer");
7289 servername = "";
7291 torture_assert(tctx,
7292 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
7293 "failed to enumerate printers");
7295 for (i=0; i < count; i++) {
7297 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
7298 "unexpected servername");
7300 torture_assert(tctx,
7301 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7302 "failed to check printer");
7306 return true;
7309 #if 0
7310 static bool test_GetPrinterDriver(struct torture_context *tctx,
7311 struct dcerpc_binding_handle *b,
7312 struct policy_handle *handle,
7313 const char *driver_name)
7315 struct spoolss_GetPrinterDriver r;
7316 uint32_t needed;
7318 r.in.handle = handle;
7319 r.in.architecture = "W32X86";
7320 r.in.level = 1;
7321 r.in.buffer = NULL;
7322 r.in.offered = 0;
7323 r.out.needed = &needed;
7325 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
7327 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7328 "failed to call GetPrinterDriver");
7329 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7330 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7331 r.in.buffer = &blob;
7332 r.in.offered = needed;
7333 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7334 "failed to call GetPrinterDriver");
7337 torture_assert_werr_ok(tctx, r.out.result,
7338 "failed to call GetPrinterDriver");
7340 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7342 return true;
7344 #endif
7346 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
7347 struct dcerpc_binding_handle *b,
7348 struct policy_handle *handle,
7349 const char *driver_name,
7350 const char *architecture,
7351 uint32_t level,
7352 uint32_t client_major_version,
7353 uint32_t client_minor_version,
7354 union spoolss_DriverInfo *info_p,
7355 WERROR *result_p)
7358 struct spoolss_GetPrinterDriver2 r;
7359 uint32_t needed;
7360 uint32_t server_major_version;
7361 uint32_t server_minor_version;
7363 r.in.handle = handle;
7364 r.in.architecture = architecture;
7365 r.in.client_major_version = client_major_version;
7366 r.in.client_minor_version = client_minor_version;
7367 r.in.buffer = NULL;
7368 r.in.offered = 0;
7369 r.in.level = level;
7370 r.out.needed = &needed;
7371 r.out.server_major_version = &server_major_version;
7372 r.out.server_minor_version = &server_minor_version;
7374 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
7375 driver_name, r.in.level);
7377 torture_assert_ntstatus_ok(tctx,
7378 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7379 "failed to call GetPrinterDriver2");
7380 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7381 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7382 r.in.buffer = &blob;
7383 r.in.offered = needed;
7384 torture_assert_ntstatus_ok(tctx,
7385 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7386 "failed to call GetPrinterDriver2");
7389 if (result_p) {
7390 *result_p = r.out.result;
7393 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
7394 switch (r.in.level) {
7395 case 101:
7396 case 8:
7397 torture_comment(tctx,
7398 "level %d not implemented, not considering as an error\n",
7399 r.in.level);
7400 return true;
7401 default:
7402 break;
7406 torture_assert_werr_ok(tctx, r.out.result,
7407 "failed to call GetPrinterDriver2");
7409 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7411 if (info_p) {
7412 *info_p = *r.out.info;
7415 return true;
7418 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7419 struct dcerpc_binding_handle *b,
7420 struct policy_handle *handle,
7421 const char *driver_name,
7422 const char *architecture)
7424 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7425 int i;
7428 for (i=0;i<ARRAY_SIZE(levels);i++) {
7430 torture_assert(tctx,
7431 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7432 "");
7435 return true;
7438 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7439 void *private_data)
7441 struct test_spoolss_context *ctx =
7442 talloc_get_type_abort(private_data, struct test_spoolss_context);
7443 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7444 int i;
7445 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7446 struct dcerpc_binding_handle *b = p->binding_handle;
7447 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7449 for (i=0;i<ARRAY_SIZE(levels);i++) {
7451 uint32_t count;
7452 union spoolss_DriverInfo *info;
7454 torture_assert(tctx,
7455 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7456 "failed to enumerate drivers");
7458 if (!info) {
7459 torture_comment(tctx, "No printer drivers returned\n");
7460 break;
7464 return true;
7467 static bool test_DeletePrinter(struct torture_context *tctx,
7468 struct dcerpc_binding_handle *b,
7469 struct policy_handle *handle)
7471 struct spoolss_DeletePrinter r;
7473 torture_comment(tctx, "Testing DeletePrinter\n");
7475 r.in.handle = handle;
7477 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7478 "failed to delete printer");
7479 torture_assert_werr_ok(tctx, r.out.result,
7480 "failed to delete printer");
7482 return true;
7485 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7486 struct dcerpc_binding_handle *b,
7487 uint32_t flags,
7488 uint32_t level,
7489 const char *name,
7490 bool *found)
7492 struct spoolss_EnumPrinters e;
7493 uint32_t count;
7494 union spoolss_PrinterInfo *info;
7495 uint32_t needed;
7496 int i;
7498 *found = false;
7500 e.in.flags = flags;
7501 e.in.server = NULL;
7502 e.in.level = level;
7503 e.in.buffer = NULL;
7504 e.in.offered = 0;
7505 e.out.count = &count;
7506 e.out.info = &info;
7507 e.out.needed = &needed;
7509 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7510 "failed to enum printers");
7512 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7513 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7514 e.in.buffer = &blob;
7515 e.in.offered = needed;
7517 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7518 "failed to enum printers");
7521 torture_assert_werr_ok(tctx, e.out.result,
7522 "failed to enum printers");
7524 for (i=0; i < count; i++) {
7526 const char *current = NULL;
7527 const char *q;
7529 switch (level) {
7530 case 1:
7531 current = info[i].info1.name;
7532 break;
7535 if (strequal(current, name)) {
7536 *found = true;
7537 break;
7540 q = strrchr(current, '\\');
7541 if (q) {
7542 if (!e.in.server) {
7543 torture_warning(tctx,
7544 "server returns printername %s incl. servername although we did not set servername", current);
7546 q++;
7547 if (strequal(q, name)) {
7548 *found = true;
7549 break;
7554 return true;
7557 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7558 struct dcerpc_pipe *p,
7559 const char *printername,
7560 bool ex)
7562 WERROR result;
7563 struct spoolss_AddPrinter r;
7564 struct spoolss_AddPrinterEx rex;
7565 struct spoolss_SetPrinterInfoCtr info_ctr;
7566 struct spoolss_SetPrinterInfo1 info1;
7567 struct spoolss_DevmodeContainer devmode_ctr;
7568 struct sec_desc_buf secdesc_ctr;
7569 struct spoolss_UserLevelCtr userlevel_ctr;
7570 struct policy_handle handle;
7571 bool found = false;
7572 struct dcerpc_binding_handle *b = p->binding_handle;
7574 ZERO_STRUCT(devmode_ctr);
7575 ZERO_STRUCT(secdesc_ctr);
7576 ZERO_STRUCT(userlevel_ctr);
7577 ZERO_STRUCT(info1);
7579 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7580 ex ? "Ex":"", printername);
7582 /* try to add printer to wellknown printer list (level 1) */
7584 userlevel_ctr.level = 1;
7586 info_ctr.info.info1 = &info1;
7587 info_ctr.level = 1;
7589 rex.in.server = NULL;
7590 rex.in.info_ctr = &info_ctr;
7591 rex.in.devmode_ctr = &devmode_ctr;
7592 rex.in.secdesc_ctr = &secdesc_ctr;
7593 rex.in.userlevel_ctr = &userlevel_ctr;
7594 rex.out.handle = &handle;
7596 r.in.server = NULL;
7597 r.in.info_ctr = &info_ctr;
7598 r.in.devmode_ctr = &devmode_ctr;
7599 r.in.secdesc_ctr = &secdesc_ctr;
7600 r.out.handle = &handle;
7602 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7603 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7604 "failed to add printer");
7605 result = ex ? rex.out.result : r.out.result;
7606 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7607 "unexpected result code");
7609 info1.name = printername;
7610 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7612 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7613 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7614 "failed to add printer");
7615 result = ex ? rex.out.result : r.out.result;
7616 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7617 "unexpected result code");
7619 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7620 better do a real check to see the printer is really there */
7622 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7623 PRINTER_ENUM_NETWORK, 1,
7624 printername,
7625 &found),
7626 "failed to enum printers");
7628 torture_assert(tctx, found, "failed to find newly added printer");
7630 info1.flags = 0;
7632 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7633 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7634 "failed to add printer");
7635 result = ex ? rex.out.result : r.out.result;
7636 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7637 "unexpected result code");
7639 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7640 better do a real check to see the printer has really been removed
7641 from the well known printer list */
7643 found = false;
7645 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7646 PRINTER_ENUM_NETWORK, 1,
7647 printername,
7648 &found),
7649 "failed to enum printers");
7650 #if 0
7651 torture_assert(tctx, !found, "printer still in well known printer list");
7652 #endif
7653 return true;
7656 static bool test_AddPrinter_normal(struct torture_context *tctx,
7657 struct dcerpc_pipe *p,
7658 struct policy_handle *handle_p,
7659 const char *printername,
7660 const char *drivername,
7661 const char *portname,
7662 struct spoolss_DeviceMode *devmode,
7663 bool ex)
7665 WERROR result;
7666 struct spoolss_AddPrinter r;
7667 struct spoolss_AddPrinterEx rex;
7668 struct spoolss_SetPrinterInfoCtr info_ctr;
7669 struct spoolss_SetPrinterInfo2 info2;
7670 struct spoolss_DevmodeContainer devmode_ctr;
7671 struct sec_desc_buf secdesc_ctr;
7672 struct spoolss_UserLevelCtr userlevel_ctr;
7673 struct policy_handle handle;
7674 bool found = false;
7675 bool existing_printer_deleted = false;
7676 struct dcerpc_binding_handle *b = p->binding_handle;
7678 ZERO_STRUCT(devmode_ctr);
7679 ZERO_STRUCT(secdesc_ctr);
7680 ZERO_STRUCT(userlevel_ctr);
7682 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7683 ex ? "Ex":"", printername);
7685 devmode_ctr.devmode = devmode;
7687 userlevel_ctr.level = 1;
7689 rex.in.server = NULL;
7690 rex.in.info_ctr = &info_ctr;
7691 rex.in.devmode_ctr = &devmode_ctr;
7692 rex.in.secdesc_ctr = &secdesc_ctr;
7693 rex.in.userlevel_ctr = &userlevel_ctr;
7694 rex.out.handle = &handle;
7696 r.in.server = NULL;
7697 r.in.info_ctr = &info_ctr;
7698 r.in.devmode_ctr = &devmode_ctr;
7699 r.in.secdesc_ctr = &secdesc_ctr;
7700 r.out.handle = &handle;
7702 again:
7704 /* try to add printer to printer list (level 2) */
7706 ZERO_STRUCT(info2);
7708 info_ctr.info.info2 = &info2;
7709 info_ctr.level = 2;
7711 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7712 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7713 "failed to add printer");
7714 result = ex ? rex.out.result : r.out.result;
7715 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7716 "unexpected result code");
7718 info2.printername = printername;
7720 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7721 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7722 "failed to add printer");
7723 result = ex ? rex.out.result : r.out.result;
7725 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7726 struct policy_handle printer_handle;
7728 if (existing_printer_deleted) {
7729 torture_fail(tctx, "already deleted printer still existing?");
7732 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7733 "failed to open printer handle");
7735 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7736 "failed to delete printer");
7738 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7739 "failed to close server handle");
7741 existing_printer_deleted = true;
7743 goto again;
7746 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7747 "unexpected result code");
7749 info2.portname = portname;
7751 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7752 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7753 "failed to add printer");
7754 result = ex ? rex.out.result : r.out.result;
7755 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7756 "unexpected result code");
7758 info2.drivername = drivername;
7760 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7761 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7762 "failed to add printer");
7763 result = ex ? rex.out.result : r.out.result;
7765 /* w2k8r2 allows one to add printer w/o defining printprocessor */
7767 if (!W_ERROR_IS_OK(result)) {
7768 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7769 "unexpected result code");
7771 info2.printprocessor = "winprint";
7773 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7774 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7775 "failed to add printer");
7776 result = ex ? rex.out.result : r.out.result;
7777 torture_assert_werr_ok(tctx, result,
7778 "failed to add printer");
7781 *handle_p = handle;
7783 /* we are paranoid, really check if the printer is there now */
7785 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7786 PRINTER_ENUM_LOCAL, 1,
7787 printername,
7788 &found),
7789 "failed to enum printers");
7790 torture_assert(tctx, found, "failed to find newly added printer");
7792 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7793 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7794 "failed to add printer");
7795 result = ex ? rex.out.result : r.out.result;
7796 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7797 "unexpected result code");
7799 return true;
7802 static bool test_printer_info(struct torture_context *tctx,
7803 void *private_data)
7805 struct torture_printer_context *t =
7806 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7807 struct dcerpc_pipe *p = t->spoolss_pipe;
7808 struct dcerpc_binding_handle *b = p->binding_handle;
7810 bool ret = true;
7812 if (torture_setting_bool(tctx, "samba3", false)) {
7813 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7816 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7817 ret = false;
7820 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7821 ret = false;
7824 return ret;
7827 static bool test_EnumPrinterKey(struct torture_context *tctx,
7828 struct dcerpc_binding_handle *b,
7829 struct policy_handle *handle,
7830 const char *key_name,
7831 const char ***array)
7833 struct spoolss_EnumPrinterKey r;
7834 uint32_t needed = 0;
7835 union spoolss_KeyNames key_buffer = {};
7836 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7837 uint32_t _ndr_size;
7838 int i;
7840 r.in.handle = handle;
7841 r.in.key_name = key_name;
7842 r.out.key_buffer = &key_buffer;
7843 r.out.needed = &needed;
7844 r.out._ndr_size = &_ndr_size;
7846 for (i=0; i < ARRAY_SIZE(offered); i++) {
7848 if (offered[i] < 0 && needed) {
7849 if (needed <= 4) {
7850 continue;
7852 r.in.offered = needed + offered[i];
7853 } else {
7854 r.in.offered = offered[i];
7857 ZERO_STRUCT(key_buffer);
7859 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7861 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7862 "failed to call EnumPrinterKey");
7863 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7865 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7866 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7867 _ndr_size, r.in.offered/2));
7869 r.in.offered = needed;
7870 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7871 "failed to call EnumPrinterKey");
7874 if (offered[i] > 0) {
7875 torture_assert_werr_ok(tctx, r.out.result,
7876 "failed to call EnumPrinterKey");
7879 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7880 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7881 _ndr_size, r.in.offered/2));
7883 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7884 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7886 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7887 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7889 if (key_buffer.string_array) {
7890 uint32_t calc_needed = 0;
7891 int s;
7892 for (s=0; key_buffer.string_array[s]; s++) {
7893 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7895 if (!key_buffer.string_array[0]) {
7896 calc_needed += 2;
7898 calc_needed += 2;
7900 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7901 "EnumPrinterKey unexpected size");
7905 if (array) {
7906 *array = key_buffer.string_array;
7909 return true;
7912 bool test_printer_all_keys(struct torture_context *tctx,
7913 struct dcerpc_binding_handle *b,
7914 struct policy_handle *handle)
7916 const char **key_array = NULL;
7917 int i;
7919 torture_comment(tctx, "Testing Printer Keys\n");
7921 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7922 "failed to call test_EnumPrinterKey");
7924 for (i=0; key_array && key_array[i]; i++) {
7925 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7926 "failed to call test_EnumPrinterKey");
7928 for (i=0; key_array && key_array[i]; i++) {
7929 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7930 "failed to call test_EnumPrinterDataEx");
7933 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7935 return true;
7938 static bool test_openprinter_wrap(struct torture_context *tctx,
7939 void *private_data)
7941 struct torture_printer_context *t =
7942 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7943 struct dcerpc_pipe *p = t->spoolss_pipe;
7944 struct dcerpc_binding_handle *b = p->binding_handle;
7945 const char *printername = t->info2.printername;
7947 return test_openprinter(tctx, b, printername);
7950 static bool test_csetprinter(struct torture_context *tctx,
7951 void *private_data)
7953 struct torture_printer_context *t =
7954 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7955 struct dcerpc_pipe *p = t->spoolss_pipe;
7957 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7958 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7959 const char *portname = t->info2.portname;
7961 union spoolss_PrinterInfo info;
7962 struct policy_handle new_handle, new_handle2;
7963 struct dcerpc_binding_handle *b = p->binding_handle;
7965 torture_comment(tctx, "Testing c_setprinter\n");
7967 torture_assert(tctx,
7968 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7969 "failed to get level 0 printer info");
7970 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7971 info.info0.c_setprinter);
7973 /* check if c_setprinter on 1st handle increases after a printer has
7974 * been added */
7976 torture_assert(tctx,
7977 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7978 "failed to add new printer");
7979 torture_assert(tctx,
7980 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7981 "failed to get level 0 printer info");
7982 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7983 info.info0.c_setprinter);
7985 /* check if c_setprinter on new handle increases after a printer has
7986 * been added */
7988 torture_assert(tctx,
7989 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7990 "failed to get level 0 printer info");
7991 torture_comment(tctx, "csetprinter on created handle: %d\n",
7992 info.info0.c_setprinter);
7994 /* open the new printer and check if c_setprinter increases */
7996 torture_assert(tctx,
7997 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7998 "failed to open created printer");
7999 torture_assert(tctx,
8000 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
8001 "failed to get level 0 printer info");
8002 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
8003 info.info0.c_setprinter);
8005 /* cleanup */
8007 torture_assert(tctx,
8008 test_ClosePrinter(tctx, b, &new_handle2),
8009 "failed to close printer");
8010 torture_assert(tctx,
8011 test_DeletePrinter(tctx, b, &new_handle),
8012 "failed to delete new printer");
8014 return true;
8017 static bool compose_local_driver_directory(struct torture_context *tctx,
8018 const char *environment,
8019 const char *local_dir,
8020 const char **path)
8022 char *p;
8024 p = strrchr(local_dir, '/');
8025 if (!p) {
8026 return NULL;
8028 p++;
8030 if (strequal(environment, SPOOLSS_ARCHITECTURE_x64)) {
8031 if (!strequal(p, "x64")) {
8032 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
8034 } else if (strequal(environment, SPOOLSS_ARCHITECTURE_NT_X86)) {
8035 if (!strequal(p, "i386")) {
8036 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
8038 } else {
8039 torture_assert(tctx, "unknown environment: '%s'\n", environment);
8042 return true;
8045 #if 0
8046 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
8047 const char *devicename)
8049 struct spoolss_DeviceMode *r;
8051 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
8052 if (r == NULL) {
8053 return NULL;
8056 r->devicename = talloc_strdup(r, devicename);
8057 r->specversion = DMSPEC_NT4_AND_ABOVE;
8058 r->driverversion = 0x0600;
8059 r->size = 0x00dc;
8060 r->__driverextra_length = 0;
8061 r->fields = DEVMODE_FORMNAME |
8062 DEVMODE_TTOPTION |
8063 DEVMODE_PRINTQUALITY |
8064 DEVMODE_DEFAULTSOURCE |
8065 DEVMODE_COPIES |
8066 DEVMODE_SCALE |
8067 DEVMODE_PAPERSIZE |
8068 DEVMODE_ORIENTATION;
8069 r->orientation = DMORIENT_PORTRAIT;
8070 r->papersize = DMPAPER_LETTER;
8071 r->paperlength = 0;
8072 r->paperwidth = 0;
8073 r->scale = 100;
8074 r->copies = 55;
8075 r->defaultsource = DMBIN_FORMSOURCE;
8076 r->printquality = DMRES_HIGH;
8077 r->color = DMRES_MONOCHROME;
8078 r->duplex = DMDUP_SIMPLEX;
8079 r->yresolution = 0;
8080 r->ttoption = DMTT_SUBDEV;
8081 r->collate = DMCOLLATE_FALSE;
8082 r->formname = talloc_strdup(r, "Letter");
8084 return r;
8086 #endif
8088 static bool test_architecture_buffer(struct torture_context *tctx,
8089 void *private_data)
8091 struct test_spoolss_context *ctx =
8092 talloc_get_type_abort(private_data, struct test_spoolss_context);
8094 struct spoolss_OpenPrinterEx r;
8095 struct spoolss_UserLevel1 u1;
8096 struct policy_handle handle;
8097 uint32_t architectures[] = {
8098 PROCESSOR_ARCHITECTURE_INTEL,
8099 PROCESSOR_ARCHITECTURE_IA64,
8100 PROCESSOR_ARCHITECTURE_AMD64
8102 uint32_t needed[3];
8103 int i;
8104 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8105 struct dcerpc_binding_handle *b = p->binding_handle;
8107 for (i=0; i < ARRAY_SIZE(architectures); i++) {
8109 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
8111 u1.size = 0;
8112 u1.client = NULL;
8113 u1.user = NULL;
8114 u1.build = 0;
8115 u1.major = 3;
8116 u1.minor = 0;
8117 u1.processor = architectures[i];
8119 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8120 r.in.datatype = NULL;
8121 r.in.devmode_ctr.devmode= NULL;
8122 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8123 r.in.userlevel_ctr.level = 1;
8124 r.in.userlevel_ctr.user_info.level1 = &u1;
8125 r.out.handle = &handle;
8127 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
8128 torture_assert_werr_ok(tctx, r.out.result, "");
8131 struct spoolss_EnumPrinters e;
8132 uint32_t count;
8133 union spoolss_PrinterInfo *info;
8135 e.in.flags = PRINTER_ENUM_LOCAL;
8136 e.in.server = NULL;
8137 e.in.level = 2;
8138 e.in.buffer = NULL;
8139 e.in.offered = 0;
8140 e.out.count = &count;
8141 e.out.info = &info;
8142 e.out.needed = &needed[i];
8144 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
8145 #if 0
8146 torture_comment(tctx, "needed was %d\n", needed[i]);
8147 #endif
8150 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
8153 for (i=1; i < ARRAY_SIZE(architectures); i++) {
8154 if (needed[i-1] != needed[i]) {
8155 torture_fail(tctx,
8156 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
8157 needed[i-1], architectures[i-1], needed[i], architectures[i]));
8161 return true;
8164 static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
8165 struct dcerpc_pipe *p,
8166 const char *architecture,
8167 const char *guid_str,
8168 const char **package_id)
8170 struct spoolss_GetCorePrinterDrivers r;
8171 struct spoolss_CorePrinterDriver core_printer_drivers;
8172 DATA_BLOB blob = data_blob_talloc_zero(tctx, 2);
8173 const char **s;
8174 struct dcerpc_binding_handle *b = p->binding_handle;
8175 struct GUID guid;
8177 s = talloc_zero_array(tctx, const char *, 2);
8179 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8180 r.in.architecture = "foobar";
8181 r.in.core_driver_size = 0;
8182 r.in.core_driver_dependencies = (uint16_t *)blob.data;
8183 r.in.core_printer_driver_count = 0;
8184 r.out.core_printer_drivers = &core_printer_drivers;
8186 torture_assert_ntstatus_ok(tctx,
8187 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8188 "spoolss_GetCorePrinterDrivers failed");
8189 torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
8190 "spoolss_GetCorePrinterDrivers failed");
8192 guid = GUID_random();
8193 s[0] = GUID_string2(tctx, &guid);
8195 torture_assert(tctx,
8196 push_reg_multi_sz(tctx, &blob, s),
8197 "push_reg_multi_sz failed");
8199 r.in.core_driver_size = blob.length/2;
8200 r.in.core_driver_dependencies = (uint16_t *)blob.data;
8201 r.in.core_printer_driver_count = 1;
8202 r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
8204 torture_assert_ntstatus_ok(tctx,
8205 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8206 "spoolss_GetCorePrinterDrivers failed");
8207 torture_assert_werr_equal(tctx,
8208 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
8209 "spoolss_GetCorePrinterDrivers failed");
8211 r.in.architecture = architecture;
8213 torture_assert_ntstatus_ok(tctx,
8214 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8215 "spoolss_GetCorePrinterDrivers failed");
8216 torture_assert_werr_equal(tctx,
8217 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
8218 "spoolss_GetCorePrinterDrivers failed");
8220 s[0] = talloc_strdup(s, guid_str);
8222 torture_assert(tctx,
8223 push_reg_multi_sz(tctx, &blob, s),
8224 "push_reg_multi_sz failed");
8226 r.in.core_driver_size = blob.length/2;
8227 r.in.core_driver_dependencies = (uint16_t *)blob.data;
8228 r.in.core_printer_driver_count = 1;
8229 r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
8231 torture_assert_ntstatus_ok(tctx,
8232 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
8233 "spoolss_GetCorePrinterDrivers failed");
8234 torture_assert_hresult_ok(tctx, r.out.result,
8235 "spoolss_GetCorePrinterDrivers failed");
8237 if (package_id) {
8238 *package_id = r.out.core_printer_drivers[0].szPackageID;
8241 return true;
8244 static bool test_get_core_printer_drivers(struct torture_context *tctx,
8245 void *private_data)
8247 struct test_spoolss_context *ctx =
8248 talloc_get_type_abort(private_data, struct test_spoolss_context);
8250 const char *architectures[] = {
8251 SPOOLSS_ARCHITECTURE_NT_X86,
8252 SPOOLSS_ARCHITECTURE_x64
8254 int i;
8255 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8257 for (i=0; i < ARRAY_SIZE(architectures); i++) {
8259 torture_comment(tctx, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
8260 architectures[i],
8261 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
8263 torture_assert(tctx,
8264 test_get_core_printer_drivers_arch_guid(tctx, p,
8265 architectures[i],
8266 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
8267 NULL),
8268 "");
8271 return true;
8274 static bool test_get_printer_driver_package_path(struct torture_context *tctx,
8275 void *private_data)
8277 struct test_spoolss_context *ctx =
8278 talloc_get_type_abort(private_data, struct test_spoolss_context);
8280 const char *architectures[] = {
8281 SPOOLSS_ARCHITECTURE_NT_X86,
8282 SPOOLSS_ARCHITECTURE_x64
8284 int i;
8285 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8286 struct dcerpc_binding_handle *b = p->binding_handle;
8288 for (i=0; i < ARRAY_SIZE(architectures); i++) {
8289 struct spoolss_GetPrinterDriverPackagePath r;
8290 uint32_t required = 0;
8291 const char *package_id = NULL;
8293 test_get_core_printer_drivers_arch_guid(tctx, p,
8294 architectures[i],
8295 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
8296 &package_id),
8298 torture_comment(tctx, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
8299 architectures[i], package_id);
8301 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8302 r.in.architecture = "foobar";
8303 r.in.language = NULL;
8304 r.in.package_id = "";
8305 r.in.driver_package_cab_size = 0;
8306 r.in.driver_package_cab = NULL;
8308 r.out.required = &required;
8309 r.out.driver_package_cab = NULL;
8311 torture_assert_ntstatus_ok(tctx,
8312 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8313 "spoolss_GetPrinterDriverPackagePath failed");
8314 torture_assert_werr_equal(tctx,
8315 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
8316 "spoolss_GetPrinterDriverPackagePath failed");
8318 r.in.architecture = architectures[i];
8320 torture_assert_ntstatus_ok(tctx,
8321 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8322 "spoolss_GetPrinterDriverPackagePath failed");
8323 torture_assert_werr_equal(tctx,
8324 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
8325 "spoolss_GetPrinterDriverPackagePath failed");
8327 r.in.package_id = package_id;
8329 torture_assert_ntstatus_ok(tctx,
8330 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8331 "spoolss_GetPrinterDriverPackagePath failed");
8332 torture_assert_hresult_ok(tctx, r.out.result,
8333 "spoolss_GetPrinterDriverPackagePath failed");
8335 r.in.driver_package_cab_size = required;
8336 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
8337 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
8339 torture_assert_ntstatus_ok(tctx,
8340 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8341 "spoolss_GetPrinterDriverPackagePath failed");
8342 torture_assert_hresult_ok(tctx, r.out.result,
8343 "spoolss_GetPrinterDriverPackagePath failed");
8345 r.in.servername = NULL;
8347 torture_assert_ntstatus_ok(tctx,
8348 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8349 "spoolss_GetPrinterDriverPackagePath failed");
8350 torture_assert_werr_equal(tctx,
8351 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INSUFFICIENT_BUFFER,
8352 "spoolss_GetPrinterDriverPackagePath failed");
8354 r.in.driver_package_cab_size = required;
8355 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
8356 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
8358 torture_assert_ntstatus_ok(tctx,
8359 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
8360 "spoolss_GetPrinterDriverPackagePath failed");
8361 torture_assert_hresult_ok(tctx, r.out.result,
8362 "spoolss_GetPrinterDriverPackagePath failed");
8366 return true;
8369 static bool test_get_printer_printserverhandle(struct torture_context *tctx,
8370 void *private_data)
8372 struct test_spoolss_context *ctx =
8373 talloc_get_type_abort(private_data, struct test_spoolss_context);
8375 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8376 struct dcerpc_binding_handle *b = p->binding_handle;
8377 uint32_t levels[] = {0, 1, 2, /* 3,*/ 4, 5, 6, 7, 8};
8378 int i;
8380 for (i=0;i<ARRAY_SIZE(levels);i++) {
8382 torture_assert(tctx,
8383 test_GetPrinter_level_exp(tctx, b, &ctx->server_handle,
8384 levels[i], WERR_INVALID_LEVEL,
8385 NULL),
8386 "failed to call GetPrinter");
8389 torture_assert(tctx,
8390 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, NULL),
8391 "failed to call GetPrinter");
8393 return true;
8396 #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
8398 static bool test_set_printer_printserverhandle(struct torture_context *tctx,
8399 void *private_data)
8401 struct test_spoolss_context *ctx =
8402 talloc_get_type_abort(private_data, struct test_spoolss_context);
8404 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8405 struct dcerpc_binding_handle *b = p->binding_handle;
8406 union spoolss_PrinterInfo info;
8407 struct spoolss_SetPrinterInfoCtr info_ctr;
8408 struct spoolss_SetPrinterInfo3 info3;
8409 struct spoolss_DevmodeContainer devmode_ctr;
8410 struct sec_desc_buf secdesc_ctr;
8411 struct security_descriptor *sd;
8412 struct security_ace *ace;
8413 struct dom_sid sid;
8414 int i;
8416 torture_assert(tctx,
8417 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
8418 "failed to call GetPrinter");
8420 secdesc_ctr.sd = info.info3.secdesc;
8421 secdesc_ctr.sd->owner_sid = NULL;
8422 secdesc_ctr.sd->group_sid = NULL;
8424 sd = security_descriptor_copy(tctx, secdesc_ctr.sd);
8425 if (sd == NULL) {
8426 return false;
8429 ace = security_ace_create(tctx,
8430 TEST_SID,
8431 SEC_ACE_TYPE_ACCESS_ALLOWED,
8432 SEC_STD_REQUIRED,
8433 SEC_ACE_FLAG_CONTAINER_INHERIT);
8434 torture_assert(tctx, ace, "failed to create ace");
8436 torture_assert_ntstatus_ok(tctx,
8437 security_descriptor_dacl_add(sd, ace),
8438 "failed to add ace");
8440 secdesc_ctr.sd = sd;
8442 info3.sec_desc_ptr = 0;
8444 info_ctr.level = 3;
8445 info_ctr.info.info3 = &info3;
8447 ZERO_STRUCT(devmode_ctr);
8449 torture_assert(tctx,
8450 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
8451 &devmode_ctr, &secdesc_ctr, 0),
8452 "failed to call SetPrinter");
8454 torture_assert(tctx,
8455 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
8456 "failed to call GetPrinter");
8458 for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
8459 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
8460 break;
8464 if (i == info.info3.secdesc->dacl->num_aces) {
8465 torture_fail(tctx, "ace not present");
8468 torture_assert(tctx,
8469 dom_sid_parse(TEST_SID, &sid),
8470 "failed to parse sid");
8472 torture_assert_ntstatus_ok(tctx,
8473 security_descriptor_dacl_del(info.info3.secdesc, &sid),
8474 "failed to remove ace from sd");
8476 secdesc_ctr.sd = info.info3.secdesc;
8478 torture_assert(tctx,
8479 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
8480 &devmode_ctr, &secdesc_ctr, 0),
8481 "failed to call SetPrinter");
8483 torture_assert(tctx,
8484 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
8485 "failed to call GetPrinter");
8487 for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
8488 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
8489 torture_fail(tctx, "ace still present");
8493 return true;
8497 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
8498 void *private_data)
8500 struct test_spoolss_context *ctx =
8501 talloc_get_type_abort(private_data, struct test_spoolss_context);
8502 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8503 struct dcerpc_binding_handle *b = p->binding_handle;
8505 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
8508 static bool test_PrintServer_Forms(struct torture_context *tctx,
8509 void *private_data)
8511 struct test_spoolss_context *ctx =
8512 talloc_get_type_abort(private_data, struct test_spoolss_context);
8513 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8514 struct dcerpc_binding_handle *b = p->binding_handle;
8516 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
8519 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
8520 void *private_data)
8522 struct test_spoolss_context *ctx =
8523 talloc_get_type_abort(private_data, struct test_spoolss_context);
8524 struct dcerpc_pipe *p = ctx->spoolss_pipe;
8525 struct dcerpc_binding_handle *b = p->binding_handle;
8527 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
8530 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
8532 NTSTATUS status;
8534 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
8536 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
8538 torture_assert(tctx,
8539 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
8540 "failed to open printserver");
8541 torture_assert(tctx,
8542 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
8543 "failed to get environment");
8545 return true;
8548 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
8550 struct test_spoolss_context *t;
8552 *data = t = talloc_zero(tctx, struct test_spoolss_context);
8554 return torture_rpc_spoolss_setup_common(tctx, t);
8557 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
8559 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
8561 return true;
8564 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
8566 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
8567 bool ret;
8569 ret = torture_rpc_spoolss_teardown_common(tctx, t);
8570 talloc_free(t);
8572 return ret;
8575 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
8577 struct dcerpc_pipe *p;
8578 struct dcerpc_binding_handle *b;
8579 const char *server_name_slash;
8580 const char *driver_name;
8581 const char *printer_name;
8582 const char *port_name;
8584 torture_assert_ntstatus_ok(tctx,
8585 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
8586 "Error connecting to server");
8588 p = t->spoolss_pipe;
8589 b = p->binding_handle;
8590 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8592 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
8593 t->driver.info8.driver_name = TORTURE_DRIVER;
8594 t->driver.info8.driver_path = "pscript5.dll";
8595 t->driver.info8.data_file = "cups6.ppd";
8596 t->driver.info8.config_file = "ps5ui.dll";
8597 t->driver.info8.help_file = "pscript.hlp";
8598 t->driver.info8.default_datatype = "RAW";
8599 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
8600 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
8601 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
8602 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
8603 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
8604 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
8605 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
8606 t->driver.info8.dependent_files->string[5] = "cups6.ini";
8607 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
8608 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
8610 t->driver.local.driver_directory= "/usr/share/cups/drivers";
8612 t->info2.portname = "LPT1:";
8614 printer_name = t->info2.printername;
8615 port_name = t->info2.portname;
8617 torture_assert(tctx,
8618 fillup_printserver_info(tctx, p, &t->driver),
8619 "failed to fillup printserver info");
8621 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
8623 torture_assert(tctx,
8624 compose_local_driver_directory(tctx, t->driver.remote.environment,
8625 t->driver.local.driver_directory,
8626 &t->driver.local.driver_directory),
8627 "failed to compose local driver directory");
8629 t->info2.drivername = "Microsoft XPS Document Writer";
8631 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8632 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
8633 t->info2.drivername, t->driver.remote.environment);
8634 t->have_driver = true;
8635 goto try_add;
8638 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8639 t->info2.drivername, t->driver.remote.environment);
8641 t->info2.drivername = "Microsoft XPS Document Writer v4";
8643 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8644 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8645 t->info2.drivername, t->driver.remote.environment);
8646 t->have_driver = true;
8647 goto try_add;
8650 torture_comment(tctx, "trying to upload own driver\n");
8652 if (!directory_exist(t->driver.local.driver_directory)) {
8653 torture_warning(tctx, "no local driver is available!");
8654 t->have_driver = false;
8655 goto try_add;
8658 torture_assert(tctx,
8659 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
8660 "failed to upload printer driver");
8662 torture_assert(tctx,
8663 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
8664 "failed to add driver");
8666 t->added_driver = true;
8667 t->have_driver = true;
8669 try_add:
8670 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8672 if (t->wellknown) {
8673 torture_assert(tctx,
8674 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
8675 "failed to add wellknown printer");
8676 } else {
8677 torture_assert(tctx,
8678 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
8679 "failed to add printer");
8682 return true;
8685 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
8687 struct torture_printer_context *t;
8689 *data = t = talloc_zero(tctx, struct torture_printer_context);
8691 t->ex = false;
8692 t->wellknown = false;
8693 t->info2.printername = TORTURE_PRINTER;
8694 t->devmode = NULL;
8696 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8699 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
8701 struct torture_printer_context *t;
8703 *data = t = talloc_zero(tctx, struct torture_printer_context);
8705 t->ex = true;
8706 t->wellknown = false;
8707 t->info2.printername = TORTURE_PRINTER_EX;
8708 t->devmode = NULL;
8710 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8713 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
8715 struct torture_printer_context *t;
8717 *data = t = talloc_zero(tctx, struct torture_printer_context);
8719 t->ex = false;
8720 t->wellknown = true;
8721 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
8722 t->devmode = NULL;
8724 /* FIXME */
8725 if (t->wellknown) {
8726 torture_skip(tctx, "skipping AddPrinter level 1");
8729 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8732 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
8734 struct torture_printer_context *t;
8736 *data = t = talloc_zero(tctx, struct torture_printer_context);
8738 t->ex = true;
8739 t->wellknown = true;
8740 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8741 t->devmode = NULL;
8743 /* FIXME */
8744 if (t->wellknown) {
8745 torture_skip(tctx, "skipping AddPrinterEx level 1");
8748 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8751 #if 0
8752 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8754 struct torture_printer_context *t;
8756 *data = t = talloc_zero(tctx, struct torture_printer_context);
8758 t->ex = true;
8759 t->wellknown = false;
8760 t->info2.printername = TORTURE_PRINTER_EX;
8761 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8763 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8765 #endif
8767 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8768 struct dcerpc_binding_handle *b,
8769 const char *server,
8770 const char *driver,
8771 const char *environment,
8772 uint32_t delete_flags,
8773 uint32_t version,
8774 WERROR expected_result);
8776 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8778 bool found = false;
8779 struct dcerpc_pipe *p = t->spoolss_pipe;
8780 struct dcerpc_binding_handle *b = NULL;
8781 const char *server_name_slash;
8782 bool ok = true;
8784 if (p == NULL) {
8785 return true;
8787 b = p->binding_handle;
8789 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8791 if (!t->wellknown) {
8792 const char *printer_name = t->info2.printername;
8794 torture_assert_goto(tctx,
8795 test_DeletePrinter(tctx, b, &t->handle),
8797 remove_driver,
8798 "failed to delete printer");
8800 torture_assert_goto(tctx,
8801 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8802 printer_name, &found),
8804 remove_driver,
8805 "failed to enumerate printers");
8807 torture_assert_goto(tctx,
8808 !found,
8810 remove_driver,
8811 "deleted printer still there");
8815 remove_driver:
8816 if (t->added_driver) {
8817 ok = remove_printer_driver(tctx,
8818 dcerpc_server_name(p),
8819 &t->driver);
8820 if (!ok) {
8821 torture_warning(tctx,
8822 "failed to remove printer driver\n");
8825 ok = test_DeletePrinterDriverEx_exp(tctx, b,
8826 server_name_slash,
8827 t->driver.info8.driver_name,
8828 t->driver.info8.architecture,
8829 DPD_DELETE_ALL_FILES,
8830 t->driver.info8.version,
8831 WERR_OK);
8832 if (!ok) {
8833 torture_warning(tctx,
8834 "failed to delete printer driver via "
8835 "spoolss\n");
8839 return ok;
8842 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8844 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8845 bool ret;
8847 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8848 talloc_free(t);
8850 return ret;
8853 static bool test_print_test(struct torture_context *tctx,
8854 void *private_data)
8856 struct torture_printer_context *t =
8857 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8858 struct dcerpc_pipe *p = t->spoolss_pipe;
8859 struct dcerpc_binding_handle *b = p->binding_handle;
8861 torture_assert(tctx,
8862 test_PausePrinter(tctx, b, &t->handle),
8863 "failed to pause printer");
8865 torture_assert(tctx,
8866 test_DoPrintTest(tctx, b, &t->handle),
8867 "failed to do print test");
8869 torture_assert(tctx,
8870 test_ResumePrinter(tctx, b, &t->handle),
8871 "failed to resume printer");
8873 return true;
8876 static bool test_print_test_extended(struct torture_context *tctx,
8877 void *private_data)
8879 struct torture_printer_context *t =
8880 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8881 struct dcerpc_pipe *p = t->spoolss_pipe;
8882 struct dcerpc_binding_handle *b = p->binding_handle;
8883 bool ret = true;
8885 torture_assert(tctx,
8886 test_PausePrinter(tctx, b, &t->handle),
8887 "failed to pause printer");
8889 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8890 if (ret == false) {
8891 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8892 if (torture_setting_bool(tctx, "samba3", false)) {
8893 torture_comment(tctx, "non-critical for samba3\n");
8894 ret = true;
8895 tctx->last_result = TORTURE_SKIP;
8899 torture_assert(tctx,
8900 test_ResumePrinter(tctx, b, &t->handle),
8901 "failed to resume printer");
8903 return ret;
8906 static bool test_print_test_properties(struct torture_context *tctx,
8907 void *private_data)
8909 struct torture_printer_context *t =
8910 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8911 struct dcerpc_pipe *p = t->spoolss_pipe;
8912 struct dcerpc_binding_handle *b = p->binding_handle;
8914 if (torture_setting_bool(tctx, "samba3", false)) {
8915 torture_skip(tctx, "skip printer job property tests against samba");
8918 torture_assert(tctx,
8919 test_PausePrinter(tctx, b, &t->handle),
8920 "failed to pause printer");
8922 torture_assert(tctx,
8923 test_DoPrintTest_properties(tctx, b, &t->handle),
8924 "failed to test print job properties");
8926 torture_assert(tctx,
8927 test_ResumePrinter(tctx, b, &t->handle),
8928 "failed to resume printer");
8930 return true;
8933 /* use smbd file IO to spool a print job */
8934 static bool test_print_test_smbd(struct torture_context *tctx,
8935 void *private_data)
8937 struct torture_printer_context *t =
8938 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8939 struct dcerpc_pipe *p = t->spoolss_pipe;
8940 struct dcerpc_binding_handle *b = p->binding_handle;
8941 NTSTATUS status;
8942 uint32_t count;
8943 union spoolss_JobInfo *info = NULL;
8944 int i;
8946 struct smb2_tree *tree;
8947 struct smb2_handle job_h;
8948 struct smbcli_options options;
8949 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8951 * Do not test against the dynamically added printers, printing via
8952 * smbd means that a different spoolss process may handle the
8953 * OpenPrinter request to the one that handled the AddPrinter request.
8954 * This currently leads to an ugly race condition where one process
8955 * sees the new printer and one doesn't.
8957 const char *share = TORTURE_PRINTER_STATIC1;
8959 torture_comment(tctx, "Testing smbd job spooling\n");
8960 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8962 status = smb2_connect(mem_ctx,
8963 torture_setting_string(tctx, "host", NULL),
8964 lpcfg_smb_ports(tctx->lp_ctx),
8965 share,
8966 lpcfg_resolve_context(tctx->lp_ctx),
8967 samba_cmdline_get_creds(),
8968 &tree,
8969 tctx->ev,
8970 &options,
8971 lpcfg_socket_options(tctx->lp_ctx),
8972 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8973 if (!NT_STATUS_IS_OK(status)) {
8974 printf("Failed to connect to SMB2 printer %s - %s\n",
8975 share, nt_errstr(status));
8976 return false;
8979 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8980 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8982 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8983 sizeof("exciting print job data"));
8984 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8986 /* check back end spoolss job was created */
8987 torture_assert(tctx,
8988 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8989 &count, &info),
8990 "EnumJobs level 1 failed");
8992 for (i = 0; i < count; i++) {
8993 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8994 break;
8997 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8999 status = smb2_util_close(tree, job_h);
9000 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
9002 /* disconnect from printer share */
9003 talloc_free(mem_ctx);
9005 return true;
9008 static bool test_print_test_purge(struct torture_context *tctx,
9009 void *private_data)
9011 struct torture_printer_context *t =
9012 (struct torture_printer_context *)talloc_get_type_abort(private_data,
9013 struct torture_printer_context);
9014 struct dcerpc_pipe *p = t->spoolss_pipe;
9015 struct dcerpc_binding_handle *b = p->binding_handle;
9016 uint32_t num_jobs = 8;
9017 uint32_t *job_ids;
9018 int i;
9019 bool ret = true;
9020 uint32_t count;
9021 union spoolss_JobInfo *info;
9023 torture_assert(tctx,
9024 test_PausePrinter(tctx, b, &t->handle),
9025 "failed to pause printer");
9027 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
9028 for (i=0; i < num_jobs; i++) {
9029 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
9030 "TorturePrintJob",
9031 &job_ids[i]);
9032 torture_assert(tctx, ret, "failed to add print job");
9035 torture_assert(tctx,
9036 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9037 &count, &info),
9038 "EnumJobs level 1 failed");
9040 torture_assert_int_equal(tctx, count, num_jobs,
9041 "unexpected number of jobs in queue");
9043 torture_assert(tctx,
9044 test_printer_purge(tctx, b, &t->handle),
9045 "failed to purge printer");
9047 torture_assert(tctx,
9048 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9049 &count, &info),
9050 "EnumJobs level 1 failed");
9052 torture_assert_int_equal(tctx, count, 0,
9053 "unexpected number of jobs in queue");
9055 torture_assert(tctx,
9056 test_ResumePrinter(tctx, b, &t->handle),
9057 "failed to resume printer");
9059 return true;
9062 static bool test_printer_sd(struct torture_context *tctx,
9063 void *private_data)
9065 struct torture_printer_context *t =
9066 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9067 struct dcerpc_pipe *p = t->spoolss_pipe;
9068 struct dcerpc_binding_handle *b = p->binding_handle;
9070 torture_assert(tctx,
9071 test_PrinterInfo_SD(tctx, b, &t->handle),
9072 "failed to test security descriptors");
9074 return true;
9077 static bool test_printer_dm(struct torture_context *tctx,
9078 void *private_data)
9080 struct torture_printer_context *t =
9081 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9082 struct dcerpc_pipe *p = t->spoolss_pipe;
9084 torture_assert(tctx,
9085 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
9086 "failed to test devicemodes");
9088 return true;
9091 static bool test_printer_info_winreg(struct torture_context *tctx,
9092 void *private_data)
9094 struct torture_printer_context *t =
9095 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9096 struct dcerpc_pipe *p = t->spoolss_pipe;
9098 torture_assert(tctx,
9099 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
9100 "failed to test printer info winreg");
9102 return true;
9105 static bool test_printserver_info_winreg(struct torture_context *tctx,
9106 void *private_data)
9108 struct test_spoolss_context *t =
9109 (struct test_spoolss_context *)talloc_get_type_abort(private_data, struct test_spoolss_context);
9110 struct dcerpc_pipe *p = t->spoolss_pipe;
9112 torture_assert(tctx,
9113 test_PrintserverInfo_winreg(tctx, p, &t->server_handle),
9114 "failed to test printserver info winreg");
9116 return true;
9120 static bool test_printer_change_id(struct torture_context *tctx,
9121 void *private_data)
9123 struct torture_printer_context *t =
9124 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9125 struct dcerpc_pipe *p = t->spoolss_pipe;
9127 torture_assert(tctx,
9128 test_ChangeID(tctx, p, &t->handle),
9129 "failed to test change id");
9131 return true;
9134 static bool test_printer_keys(struct torture_context *tctx,
9135 void *private_data)
9137 struct torture_printer_context *t =
9138 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9139 struct dcerpc_pipe *p = t->spoolss_pipe;
9140 struct dcerpc_binding_handle *b = p->binding_handle;
9142 torture_assert(tctx,
9143 test_printer_all_keys(tctx, b, &t->handle),
9144 "failed to test printer keys");
9146 return true;
9149 static bool test_printer_data_consistency(struct torture_context *tctx,
9150 void *private_data)
9152 struct torture_printer_context *t =
9153 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9154 struct dcerpc_pipe *p = t->spoolss_pipe;
9156 torture_assert(tctx,
9157 test_EnumPrinterData_consistency(tctx, p, &t->handle),
9158 "failed to test printer data consistency");
9160 return true;
9163 static bool test_printer_data_keys(struct torture_context *tctx,
9164 void *private_data)
9166 struct torture_printer_context *t =
9167 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9168 struct dcerpc_pipe *p = t->spoolss_pipe;
9170 torture_assert(tctx,
9171 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
9172 "failed to test printer data keys");
9174 return true;
9177 static bool test_printer_data_values(struct torture_context *tctx,
9178 void *private_data)
9180 struct torture_printer_context *t =
9181 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9182 struct dcerpc_pipe *p = t->spoolss_pipe;
9184 torture_assert(tctx,
9185 test_SetPrinterDataEx_values(tctx, p, &t->handle),
9186 "failed to test printer data values");
9188 return true;
9191 static bool test_printer_data_set(struct torture_context *tctx,
9192 void *private_data)
9194 struct torture_printer_context *t =
9195 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9196 struct dcerpc_pipe *p = t->spoolss_pipe;
9198 torture_assert(tctx,
9199 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
9200 "failed to test printer data set");
9202 return true;
9205 static bool test_printer_data_winreg(struct torture_context *tctx,
9206 void *private_data)
9208 struct torture_printer_context *t =
9209 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9210 struct dcerpc_pipe *p = t->spoolss_pipe;
9212 torture_assert(tctx,
9213 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
9214 "failed to test printer data winreg");
9216 return true;
9219 static bool test_printer_data_dsspooler(struct torture_context *tctx,
9220 void *private_data)
9222 struct torture_printer_context *t =
9223 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9224 struct dcerpc_pipe *p = t->spoolss_pipe;
9226 torture_assert(tctx,
9227 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
9228 "failed to test printer data winreg dsspooler");
9230 return true;
9233 static bool test_printer_ic(struct torture_context *tctx,
9234 void *private_data)
9236 struct torture_printer_context *t =
9237 talloc_get_type_abort(private_data,
9238 struct torture_printer_context);
9239 struct dcerpc_pipe *p = t->spoolss_pipe;
9240 struct dcerpc_binding_handle *b = p->binding_handle;
9241 struct policy_handle gdi_handle;
9243 if (torture_setting_bool(tctx, "samba3", false)) {
9244 torture_skip(tctx, "skip printer information context tests against samba");
9248 struct spoolss_CreatePrinterIC r;
9249 struct spoolss_DevmodeContainer devmode_ctr;
9251 ZERO_STRUCT(devmode_ctr);
9253 r.in.handle = &t->handle;
9254 r.in.devmode_ctr = &devmode_ctr;
9255 r.out.gdi_handle = &gdi_handle;
9257 torture_assert_ntstatus_ok(tctx,
9258 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
9259 "CreatePrinterIC failed");
9260 torture_assert_werr_ok(tctx, r.out.result,
9261 "CreatePrinterIC failed");
9265 struct spoolss_PlayGDIScriptOnPrinterIC r;
9266 DATA_BLOB in,out;
9267 int i;
9268 uint32_t num_fonts = 0;
9270 in = data_blob_string_const("");
9272 r.in.gdi_handle = &gdi_handle;
9273 r.in.pIn = in.data;
9274 r.in.cIn = in.length;
9275 r.in.ul = 0;
9277 for (i = 0; i < 4; i++) {
9279 out = data_blob_talloc_zero(tctx, i);
9281 r.in.cOut = out.length;
9282 r.out.pOut = out.data;
9284 torture_assert_ntstatus_ok(tctx,
9285 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
9286 "PlayGDIScriptOnPrinterIC failed");
9287 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_ENOUGH_MEMORY,
9288 "PlayGDIScriptOnPrinterIC failed");
9291 out = data_blob_talloc_zero(tctx, 4);
9293 r.in.cOut = out.length;
9294 r.out.pOut = out.data;
9296 torture_assert_ntstatus_ok(tctx,
9297 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
9298 "PlayGDIScriptOnPrinterIC failed");
9299 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9300 "PlayGDIScriptOnPrinterIC failed");
9302 /* now we should have the required length, so retry with a
9303 * buffer which is large enough to carry all font ids */
9305 num_fonts = IVAL(r.out.pOut, 0);
9307 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
9309 out = data_blob_talloc_zero(tctx,
9310 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
9312 r.in.cOut = out.length;
9313 r.out.pOut = out.data;
9315 torture_assert_ntstatus_ok(tctx,
9316 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
9317 "PlayGDIScriptOnPrinterIC failed");
9318 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9319 "PlayGDIScriptOnPrinterIC failed");
9324 struct spoolss_DeletePrinterIC r;
9326 r.in.gdi_handle = &gdi_handle;
9327 r.out.gdi_handle = &gdi_handle;
9329 torture_assert_ntstatus_ok(tctx,
9330 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
9331 "DeletePrinterIC failed");
9332 torture_assert_werr_ok(tctx, r.out.result,
9333 "DeletePrinterIC failed");
9337 return true;
9340 static bool test_printer_bidi(struct torture_context *tctx,
9341 void *private_data)
9343 struct torture_printer_context *t =
9344 talloc_get_type_abort(private_data,
9345 struct torture_printer_context);
9346 struct dcerpc_pipe *p = t->spoolss_pipe;
9347 struct dcerpc_binding_handle *b = p->binding_handle;
9348 struct spoolss_SendRecvBidiData r;
9349 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
9350 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
9352 if (torture_setting_bool(tctx, "samba3", false)) {
9353 torture_skip(tctx, "skip printer bidirectional tests against samba");
9356 ZERO_STRUCT(bidi_req);
9358 r.in.hPrinter = t->handle;
9359 r.in.pAction = "foobar";
9360 r.in.pReqData = &bidi_req;
9361 r.out.ppRespData = &bidi_rep;
9363 torture_assert_ntstatus_ok(tctx,
9364 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
9365 "SendRecvBidiData failed");
9366 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
9367 "SendRecvBidiData failed");
9369 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
9370 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
9373 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
9375 torture_assert_ntstatus_ok(tctx,
9376 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
9377 "SendRecvBidiData failed");
9378 torture_assert_werr_ok(tctx, r.out.result,
9379 "SendRecvBidiData failed");
9381 return true;
9384 static bool test_printer_set_publish(struct torture_context *tctx,
9385 struct dcerpc_binding_handle *b,
9386 struct policy_handle *handle)
9388 union spoolss_PrinterInfo info;
9389 struct spoolss_SetPrinterInfo7 info7;
9390 struct spoolss_SetPrinterInfoCtr info_ctr;
9391 struct spoolss_DevmodeContainer devmode_ctr;
9392 struct sec_desc_buf secdesc_ctr;
9394 info7.guid = "";
9395 info7.action = DSPRINT_PUBLISH;
9397 ZERO_STRUCT(info_ctr);
9398 ZERO_STRUCT(devmode_ctr);
9399 ZERO_STRUCT(secdesc_ctr);
9400 info_ctr.level = 7;
9401 info_ctr.info.info7 = &info7;
9403 torture_assert(tctx,
9404 test_SetPrinter(tctx, b, handle, &info_ctr,
9405 &devmode_ctr, &secdesc_ctr, 0), "");
9407 torture_assert(tctx,
9408 test_GetPrinter_level(tctx, b, handle, 2, &info),
9409 "");
9410 torture_assert(tctx,
9411 (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
9412 "info2 publish flag not set");
9413 torture_assert(tctx,
9414 test_GetPrinter_level(tctx, b, handle, 7, &info),
9415 "");
9416 if (info.info7.action & DSPRINT_PENDING) {
9417 torture_comment(tctx, "publish is pending\n");
9418 torture_assert_int_equal(tctx,
9419 info.info7.action,
9420 (DSPRINT_PENDING | DSPRINT_PUBLISH),
9421 "info7 publish flag not set");
9422 } else {
9423 struct GUID guid;
9424 char *ref_guid;
9425 torture_assert_int_equal(tctx,
9426 info.info7.action,
9427 DSPRINT_PUBLISH,
9428 "info7 publish flag not set");
9430 /* GUID_from_string is able to parse both plain and
9431 * curly-braced guids */
9432 torture_assert_ntstatus_ok(tctx,
9433 GUID_from_string(info.info7.guid,
9434 &guid),
9435 "invalid published printer GUID");
9437 /* Build reference GUID string */
9438 ref_guid = GUID_string2(tctx, &guid);
9439 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
9440 ref_guid = talloc_strdup_upper(tctx, ref_guid);
9441 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
9442 torture_assert_str_equal(tctx, info.info7.guid, ref_guid,
9443 "invalid GUID format");
9446 return true;
9449 static bool test_printer_set_unpublish(struct torture_context *tctx,
9450 struct dcerpc_binding_handle *b,
9451 struct policy_handle *handle)
9453 union spoolss_PrinterInfo info;
9454 struct spoolss_SetPrinterInfo7 info7;
9455 struct spoolss_SetPrinterInfoCtr info_ctr;
9456 struct spoolss_DevmodeContainer devmode_ctr;
9457 struct sec_desc_buf secdesc_ctr;
9459 info7.action = DSPRINT_UNPUBLISH;
9460 info7.guid = "";
9462 ZERO_STRUCT(info_ctr);
9463 ZERO_STRUCT(devmode_ctr);
9464 ZERO_STRUCT(secdesc_ctr);
9465 info_ctr.level = 7;
9466 info_ctr.info.info7 = &info7;
9468 torture_assert(tctx,
9469 test_SetPrinter(tctx, b, handle, &info_ctr,
9470 &devmode_ctr, &secdesc_ctr, 0), "");
9472 torture_assert(tctx,
9473 test_GetPrinter_level(tctx, b, handle, 2, &info),
9474 "");
9475 torture_assert(tctx,
9476 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
9477 "info2 publish flag still set");
9478 torture_assert(tctx,
9479 test_GetPrinter_level(tctx, b, handle, 7, &info),
9480 "");
9482 if (info.info7.action & DSPRINT_PENDING) {
9483 struct GUID guid;
9484 torture_comment(tctx, "unpublish is pending\n");
9485 torture_assert_int_equal(tctx,
9486 info.info7.action,
9487 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
9488 "info7 unpublish flag not set");
9489 torture_assert_ntstatus_ok(tctx,
9490 GUID_from_string(info.info7.guid,
9491 &guid),
9492 "invalid printer GUID");
9493 } else {
9494 torture_assert_int_equal(tctx,
9495 info.info7.action, DSPRINT_UNPUBLISH,
9496 "info7 unpublish flag not set");
9499 return true;
9502 static bool test_printer_publish_toggle(struct torture_context *tctx,
9503 void *private_data)
9505 struct torture_printer_context *t =
9506 talloc_get_type_abort(private_data,
9507 struct torture_printer_context);
9508 struct dcerpc_pipe *p = t->spoolss_pipe;
9509 struct dcerpc_binding_handle *b = p->binding_handle;
9510 struct policy_handle *handle = &t->handle;
9511 union spoolss_PrinterInfo info7;
9512 union spoolss_PrinterInfo info2;
9514 /* check publish status via level 7 and level 2 */
9515 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
9516 "");
9517 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
9518 "");
9520 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
9521 torture_assert_int_equal(tctx,
9522 info7.info7.action, DSPRINT_PUBLISH,
9523 "info7 publish flag not set");
9524 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
9525 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
9526 } else {
9527 torture_assert_int_equal(tctx,
9528 info7.info7.action, DSPRINT_UNPUBLISH,
9529 "info7 unpublish flag not set");
9530 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
9531 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
9534 return true;
9537 static bool test_driver_info_winreg(struct torture_context *tctx,
9538 void *private_data)
9540 struct torture_printer_context *t =
9541 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9542 struct dcerpc_pipe *p = t->spoolss_pipe;
9543 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
9545 if (!t->have_driver) {
9546 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
9549 torture_assert(tctx,
9550 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
9551 "failed to test driver info winreg");
9553 return true;
9556 static bool test_print_job_enum(struct torture_context *tctx,
9557 void *private_data)
9559 struct torture_printer_context *t =
9560 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9561 struct dcerpc_pipe *p = t->spoolss_pipe;
9562 struct dcerpc_binding_handle *b = p->binding_handle;
9563 bool ret = true;
9564 uint32_t num_jobs = 8;
9565 uint32_t *job_ids;
9566 int i;
9567 union spoolss_JobInfo *info = NULL;
9568 uint32_t count;
9570 torture_assert(tctx,
9571 test_PausePrinter(tctx, b, &t->handle),
9572 "failed to pause printer");
9574 /* purge in case of any jobs from previous tests */
9575 torture_assert(tctx,
9576 test_printer_purge(tctx, b, &t->handle),
9577 "failed to purge printer");
9579 /* enum before jobs, valid level */
9580 torture_assert(tctx,
9581 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9582 &count, &info),
9583 "EnumJobs with valid level");
9584 torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
9585 torture_assert(tctx,
9586 test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
9587 &count, &info),
9588 "EnumJobs with valid level");
9589 torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
9590 /* enum before jobs, invalid level - expect failure */
9591 torture_assert(tctx,
9592 test_EnumJobs_args(tctx, b, &t->handle, 100,
9593 WERR_INVALID_LEVEL,
9594 &count, &info),
9595 "EnumJobs with invalid level");
9597 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
9599 for (i = 0; i < num_jobs; i++) {
9600 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
9601 "TorturePrintJob",
9602 &job_ids[i]);
9603 torture_assert(tctx, ret, "failed to add print job");
9606 /* enum after jobs, valid level */
9607 torture_assert(tctx,
9608 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
9609 &count, &info),
9610 "EnumJobs with valid level");
9611 torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
9612 torture_assert(tctx,
9613 test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
9614 &count, &info),
9615 "EnumJobs with valid level");
9616 torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
9617 /* enum after jobs, invalid level - expect failure */
9618 torture_assert(tctx,
9619 test_EnumJobs_args(tctx, b, &t->handle, 100,
9620 WERR_INVALID_LEVEL,
9621 &count, &info),
9622 "EnumJobs with invalid level");
9624 for (i = 0; i < num_jobs; i++) {
9625 test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
9626 SPOOLSS_JOB_CONTROL_DELETE);
9629 torture_assert(tctx,
9630 test_ResumePrinter(tctx, b, &t->handle),
9631 "failed to resume printer");
9633 return true;
9636 static bool test_printer_log_jobinfo(struct torture_context *tctx,
9637 void *private_data)
9639 struct torture_printer_context *t =
9640 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9641 struct dcerpc_pipe *p = t->spoolss_pipe;
9642 struct dcerpc_binding_handle *b = p->binding_handle;
9643 struct spoolss_BranchOfficeJobDataContainer info;
9644 int i;
9646 struct spoolss_LogJobInfoForBranchOffice r;
9648 torture_comment(tctx, "Testing LogJobInfoForBranchOffice\n");
9650 info.cJobDataEntries = 0;
9651 info.JobData = NULL;
9653 r.in.hPrinter = &t->handle;
9654 r.in.pBranchOfficeJobDataContainer = &info;
9656 torture_assert_ntstatus_ok(tctx,
9657 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
9658 "LogJobInfoForBranchOffice failed");
9659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
9660 "LogJobInfoForBranchOffice failed");
9662 info.cJobDataEntries = 1;
9663 info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
9665 info.JobData[0].eEventType = kLogOfflineFileFull;
9666 info.JobData[0].JobId = 42;
9667 info.JobData[0].JobInfo.LogOfflineFileFull.pMachineName = talloc_strdup(tctx, "mthelena");
9669 torture_assert_ntstatus_ok(tctx,
9670 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
9671 "LogJobInfoForBranchOffice failed");
9672 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9673 "LogJobInfoForBranchOffice failed");
9675 info.cJobDataEntries = 42;
9676 info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
9678 for (i=0; i < info.cJobDataEntries; i++) {
9679 info.JobData[i].eEventType = kLogOfflineFileFull;
9680 info.JobData[i].JobId = i;
9681 info.JobData[i].JobInfo.LogOfflineFileFull.pMachineName = talloc_asprintf(tctx, "torture_%d", i);
9684 torture_assert_ntstatus_ok(tctx,
9685 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
9686 "LogJobInfoForBranchOffice failed");
9687 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
9688 "LogJobInfoForBranchOffice failed");
9690 return true;
9693 static bool test_printer_os_versions(struct torture_context *tctx,
9694 void *private_data)
9696 struct torture_printer_context *t =
9697 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
9698 struct dcerpc_pipe *p = t->spoolss_pipe;
9699 struct dcerpc_binding_handle *b = p->binding_handle;
9700 union spoolss_PrinterInfo info;
9701 DATA_BLOB blob;
9702 uint8_t *data;
9703 uint32_t length;
9704 struct spoolss_OSVersion osversion;
9705 uint8_t os_major, os_minor;
9706 uint16_t os_build;
9707 struct policy_handle server_handle;
9709 torture_comment(tctx, "Testing OSVersion vs. PRINTER_INFO_STRESS\n");
9711 torture_assert(tctx,
9712 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
9713 "failed to get level 0 printer info");
9715 torture_assert(tctx,
9716 test_OpenPrinter_server(tctx, p, &server_handle),
9717 "failed to open printserver");
9719 torture_assert(tctx,
9720 test_GetPrinterData_checktype(tctx, b, &server_handle, "OSVersion",
9721 NULL, NULL, &data, &length),
9722 "failed to fetch OSVersion printer data");
9724 test_ClosePrinter(tctx, b, &server_handle);
9726 blob = data_blob_const(data, length);
9728 torture_assert_ndr_success(tctx,
9729 ndr_pull_struct_blob(&blob, tctx, &osversion,
9730 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion),
9731 "failed to pull OSVersion");
9733 os_major = CVAL(&info.info0.version, 0);
9734 os_minor = CVAL(&info.info0.version, 1);
9735 os_build = SVAL(&info.info0.version, 2);
9737 torture_assert_int_equal(tctx, os_major, osversion.major, "major");
9738 torture_assert_int_equal(tctx, os_minor, osversion.minor, "minor");
9739 torture_assert_int_equal(tctx, os_build, osversion.build, "build");
9741 return true;
9745 void torture_tcase_printer(struct torture_tcase *tcase)
9747 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
9748 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
9749 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
9750 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
9751 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
9752 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
9753 torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
9754 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
9755 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
9756 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
9757 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
9758 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
9759 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
9760 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
9761 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
9762 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
9763 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
9764 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
9765 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
9766 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
9767 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
9768 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
9769 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
9770 torture_tcase_add_simple_test(tcase, "publish_toggle",
9771 test_printer_publish_toggle);
9772 torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
9773 torture_tcase_add_simple_test(tcase, "log_jobinfo", test_printer_log_jobinfo);
9774 torture_tcase_add_simple_test(tcase, "os_versions", test_printer_os_versions);
9777 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
9779 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
9780 struct torture_tcase *tcase;
9782 tcase = torture_suite_add_tcase(suite, "addprinter");
9784 torture_tcase_set_fixture(tcase,
9785 torture_rpc_spoolss_printer_setup,
9786 torture_rpc_spoolss_printer_teardown);
9788 torture_tcase_printer(tcase);
9790 tcase = torture_suite_add_tcase(suite, "addprinterex");
9792 torture_tcase_set_fixture(tcase,
9793 torture_rpc_spoolss_printerex_setup,
9794 torture_rpc_spoolss_printer_teardown);
9796 torture_tcase_printer(tcase);
9798 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
9800 torture_tcase_set_fixture(tcase,
9801 torture_rpc_spoolss_printerwkn_setup,
9802 torture_rpc_spoolss_printer_teardown);
9804 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
9806 torture_tcase_set_fixture(tcase,
9807 torture_rpc_spoolss_printerexwkn_setup,
9808 torture_rpc_spoolss_printer_teardown);
9810 #if 0
9811 /* test is not correct */
9812 tcase = torture_suite_add_tcase(suite, "addprinterdm");
9814 torture_tcase_set_fixture(tcase,
9815 torture_rpc_spoolss_printerdm_setup,
9816 torture_rpc_spoolss_printer_teardown);
9818 torture_tcase_printer(tcase);
9819 #endif
9820 return suite;
9823 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
9825 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
9826 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
9828 torture_tcase_set_fixture(tcase,
9829 torture_rpc_spoolss_setup,
9830 torture_rpc_spoolss_teardown);
9832 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
9833 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
9834 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
9835 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
9836 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
9837 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
9838 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
9839 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
9840 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
9841 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
9842 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
9843 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
9844 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
9845 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
9846 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcessorDataTypes);
9847 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
9848 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
9849 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
9850 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
9851 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
9852 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
9853 torture_tcase_add_simple_test(tcase, "get_core_printer_drivers", test_get_core_printer_drivers);
9854 torture_tcase_add_simple_test(tcase, "get_printer_driver_package_path", test_get_printer_driver_package_path);
9855 torture_tcase_add_simple_test(tcase, "get_printer", test_get_printer_printserverhandle);
9856 torture_tcase_add_simple_test(tcase, "set_printer", test_set_printer_printserverhandle);
9857 torture_tcase_add_simple_test(tcase, "printserver_info_winreg", test_printserver_info_winreg);
9858 torture_tcase_add_simple_test(tcase, "addpermachineconnection", test_addpermachineconnection);
9860 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
9862 return suite;
9865 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
9866 struct dcerpc_binding_handle *b,
9867 const char *server,
9868 const char *environment,
9869 const char **dir_p)
9871 struct spoolss_GetPrinterDriverDirectory r;
9872 uint32_t needed;
9874 r.in.server = server;
9875 r.in.environment = environment;
9876 r.in.level = 1;
9877 r.in.buffer = NULL;
9878 r.in.offered = 0;
9879 r.out.needed = &needed;
9881 torture_assert_ntstatus_ok(tctx,
9882 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9883 "failed to query driver directory");
9885 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
9886 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
9887 r.in.buffer = &blob;
9888 r.in.offered = needed;
9890 torture_assert_ntstatus_ok(tctx,
9891 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9892 "failed to query driver directory");
9895 torture_assert_werr_ok(tctx, r.out.result,
9896 "failed to query driver directory");
9898 if (dir_p) {
9899 *dir_p = r.out.info->info1.directory_name;
9902 return true;
9905 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9907 if (info_ctr == NULL) {
9908 return NULL;
9911 switch (info_ctr->level) {
9912 case 1:
9913 return info_ctr->info.info1->driver_name;
9914 case 2:
9915 return info_ctr->info.info2->driver_name;
9916 case 3:
9917 return info_ctr->info.info3->driver_name;
9918 case 4:
9919 return info_ctr->info.info4->driver_name;
9920 case 6:
9921 return info_ctr->info.info6->driver_name;
9922 case 8:
9923 return info_ctr->info.info8->driver_name;
9924 default:
9925 return NULL;
9929 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9931 if (info_ctr == NULL) {
9932 return NULL;
9935 switch (info_ctr->level) {
9936 case 2:
9937 return info_ctr->info.info2->architecture;
9938 case 3:
9939 return info_ctr->info.info3->architecture;
9940 case 4:
9941 return info_ctr->info.info4->architecture;
9942 case 6:
9943 return info_ctr->info.info6->architecture;
9944 case 8:
9945 return info_ctr->info.info8->architecture;
9946 default:
9947 return NULL;
9952 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
9953 struct dcerpc_binding_handle *b,
9954 const char *servername,
9955 struct spoolss_AddDriverInfoCtr *info_ctr,
9956 WERROR expected_result)
9958 struct spoolss_AddPrinterDriver r;
9959 const char *drivername = get_driver_from_info(info_ctr);
9960 const char *environment = get_environment_from_info(info_ctr);
9962 r.in.servername = servername;
9963 r.in.info_ctr = info_ctr;
9965 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9966 drivername, info_ctr->level, environment);
9968 torture_assert_ntstatus_ok(tctx,
9969 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
9970 "spoolss_AddPrinterDriver failed");
9971 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9972 "spoolss_AddPrinterDriver failed with unexpected result");
9974 return true;
9978 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
9979 struct dcerpc_binding_handle *b,
9980 const char *servername,
9981 struct spoolss_AddDriverInfoCtr *info_ctr,
9982 uint32_t flags,
9983 WERROR expected_result)
9985 struct spoolss_AddPrinterDriverEx r;
9986 const char *drivername = get_driver_from_info(info_ctr);
9987 const char *environment = get_environment_from_info(info_ctr);
9989 r.in.servername = servername;
9990 r.in.info_ctr = info_ctr;
9991 r.in.flags = flags;
9993 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9994 drivername, info_ctr->level, environment);
9996 torture_assert_ntstatus_ok(tctx,
9997 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
9998 "AddPrinterDriverEx failed");
9999 torture_assert_werr_equal(tctx, r.out.result, expected_result,
10000 "AddPrinterDriverEx failed with unexpected result");
10002 return true;
10005 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
10006 if (path && strlen(path)) {\
10007 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
10010 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
10011 struct dcerpc_binding_handle *b,
10012 const char *server_name,
10013 struct spoolss_AddDriverInfo8 *r,
10014 uint32_t flags,
10015 bool ex,
10016 const char *remote_driver_dir)
10018 struct spoolss_AddDriverInfoCtr info_ctr;
10019 struct spoolss_AddDriverInfo1 info1;
10021 ZERO_STRUCT(info1);
10023 info_ctr.level = 1;
10024 info_ctr.info.info1 = &info1;
10026 if (ex) {
10027 torture_assert(tctx,
10028 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_LEVEL),
10029 "failed to test AddPrinterDriverEx level 1");
10030 } else {
10031 torture_assert(tctx,
10032 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
10033 "failed to test AddPrinterDriver level 1");
10036 info1.driver_name = r->driver_name;
10038 if (ex) {
10039 torture_assert(tctx,
10040 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_LEVEL),
10041 "failed to test AddPrinterDriverEx level 1");
10042 } else {
10043 torture_assert(tctx,
10044 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
10045 "failed to test AddPrinterDriver level 1");
10048 return true;
10051 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
10052 struct dcerpc_binding_handle *b,
10053 const char *server_name,
10054 struct spoolss_AddDriverInfo8 *r,
10055 uint32_t flags,
10056 bool ex,
10057 const char *remote_driver_dir)
10059 struct spoolss_AddDriverInfoCtr info_ctr;
10060 struct spoolss_AddDriverInfo2 info2;
10061 union spoolss_DriverInfo info;
10063 ZERO_STRUCT(info2);
10065 info_ctr.level = 2;
10066 info_ctr.info.info2 = &info2;
10068 if (ex) {
10069 torture_assert(tctx,
10070 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
10071 "failed to test AddPrinterDriverEx level 2");
10072 } else {
10073 torture_assert(tctx,
10074 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
10075 "failed to test AddPrinterDriver level 2");
10078 info2.driver_name = r->driver_name;
10080 if (ex) {
10081 torture_assert(tctx,
10082 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
10083 "failed to test AddPrinterDriverEx level 2");
10084 } else {
10085 torture_assert(tctx,
10086 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
10087 "failed to test AddPrinterDriver level 2");
10090 info2.version = r->version;
10092 if (ex) {
10093 torture_assert(tctx,
10094 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
10095 "failed to test AddPrinterDriverEx level 2");
10096 } else {
10097 torture_assert(tctx,
10098 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
10099 "failed to test AddPrinterDriver level 2");
10102 info2.architecture = r->architecture;
10104 if (ex) {
10105 torture_assert(tctx,
10106 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
10107 "failed to test AddPrinterDriverEx level 2");
10108 } else {
10109 torture_assert(tctx,
10110 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
10111 "failed to test AddPrinterDriver level 2");
10114 info2.driver_path = r->driver_path;
10116 if (ex) {
10117 torture_assert(tctx,
10118 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
10119 "failed to test AddPrinterDriverEx level 2");
10120 } else {
10121 torture_assert(tctx,
10122 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
10123 "failed to test AddPrinterDriver level 2");
10126 info2.data_file = r->data_file;
10128 if (ex) {
10129 torture_assert(tctx,
10130 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
10131 "failed to test AddPrinterDriverEx level 2");
10132 } else {
10133 torture_assert(tctx,
10134 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
10135 "failed to test AddPrinterDriver level 2");
10138 info2.config_file = r->config_file;
10140 if (ex) {
10141 torture_assert(tctx,
10142 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAMETER),
10143 "failed to test AddPrinterDriverEx");
10146 if (ex) {
10147 torture_assert(tctx,
10148 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10149 "failed to test AddPrinterDriverEx level 2");
10150 } else {
10151 torture_assert(tctx,
10152 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
10153 "failed to test AddPrinterDriver level 2");
10156 torture_assert(tctx,
10157 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
10158 "failed to find added printer driver");
10160 if (remote_driver_dir) {
10161 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
10162 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
10163 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
10166 return true;
10169 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
10170 struct dcerpc_binding_handle *b,
10171 const char *server_name,
10172 struct spoolss_AddDriverInfo8 *r,
10173 uint32_t flags,
10174 bool ex,
10175 const char *remote_driver_dir)
10177 struct spoolss_AddDriverInfoCtr info_ctr;
10178 struct spoolss_AddDriverInfo3 info3;
10179 union spoolss_DriverInfo info;
10181 info3.driver_name = r->driver_name;
10182 info3.version = r->version;
10183 info3.architecture = r->architecture;
10184 info3.driver_path = r->driver_path;
10185 info3.data_file = r->data_file;
10186 info3.config_file = r->config_file;
10187 info3.help_file = r->help_file;
10188 info3.monitor_name = r->monitor_name;
10189 info3.default_datatype = r->default_datatype;
10190 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
10191 info3.dependent_files = r->dependent_files;
10193 info_ctr.level = 3;
10194 info_ctr.info.info3 = &info3;
10196 if (ex) {
10197 torture_assert(tctx,
10198 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10199 "failed to test AddPrinterDriverEx level 3");
10200 } else {
10201 torture_assert(tctx,
10202 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
10203 "failed to test AddPrinterDriver level 3");
10206 torture_assert(tctx,
10207 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
10208 "failed to find added printer driver");
10210 if (remote_driver_dir) {
10211 int i;
10212 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
10213 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
10214 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
10215 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
10216 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
10217 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
10221 return true;
10224 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
10225 struct dcerpc_binding_handle *b,
10226 const char *server_name,
10227 struct spoolss_AddDriverInfo8 *r,
10228 uint32_t flags,
10229 bool ex,
10230 const char *remote_driver_dir)
10232 struct spoolss_AddDriverInfoCtr info_ctr;
10233 struct spoolss_AddDriverInfo4 info4;
10234 union spoolss_DriverInfo info;
10236 info4.version = r->version;
10237 info4.driver_name = r->driver_name;
10238 info4.architecture = r->architecture;
10239 info4.driver_path = r->driver_path;
10240 info4.data_file = r->data_file;
10241 info4.config_file = r->config_file;
10242 info4.help_file = r->help_file;
10243 info4.monitor_name = r->monitor_name;
10244 info4.default_datatype = r->default_datatype;
10245 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
10246 info4.dependent_files = r->dependent_files;
10247 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
10248 info4.previous_names = r->previous_names;
10250 info_ctr.level = 4;
10251 info_ctr.info.info4 = &info4;
10253 if (ex) {
10254 torture_assert(tctx,
10255 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10256 "failed to test AddPrinterDriverEx level 4");
10257 } else {
10258 torture_assert(tctx,
10259 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
10260 "failed to test AddPrinterDriver level 4");
10263 torture_assert(tctx,
10264 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
10265 "failed to find added printer driver");
10267 if (remote_driver_dir) {
10268 int i;
10269 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
10270 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
10271 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
10272 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
10273 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
10274 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
10278 return true;
10281 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
10282 struct dcerpc_binding_handle *b,
10283 const char *server_name,
10284 struct spoolss_AddDriverInfo8 *r,
10285 uint32_t flags,
10286 bool ex,
10287 const char *remote_driver_dir)
10289 struct spoolss_AddDriverInfoCtr info_ctr;
10290 struct spoolss_AddDriverInfo6 info6;
10291 union spoolss_DriverInfo info;
10293 info6.version = r->version;
10294 info6.driver_name = r->driver_name;
10295 info6.architecture = r->architecture;
10296 info6.driver_path = r->driver_path;
10297 info6.data_file = r->data_file;
10298 info6.config_file = r->config_file;
10299 info6.help_file = r->help_file;
10300 info6.monitor_name = r->monitor_name;
10301 info6.default_datatype = r->default_datatype;
10302 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
10303 info6.dependent_files = r->dependent_files;
10304 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
10305 info6.previous_names = r->previous_names;
10306 info6.driver_date = r->driver_date;
10307 info6.driver_version = r->driver_version;
10308 info6.manufacturer_name = r->manufacturer_name;
10309 info6.manufacturer_url = r->manufacturer_url;
10310 info6.hardware_id = r->hardware_id;
10311 info6.provider = r->provider;
10313 info_ctr.level = 6;
10314 info_ctr.info.info6 = &info6;
10316 if (ex) {
10317 torture_assert(tctx,
10318 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10319 "failed to test AddPrinterDriverEx level 6");
10320 } else {
10321 torture_assert(tctx,
10322 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
10323 "failed to test AddPrinterDriver level 6");
10326 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10328 if (!ex) {
10329 return true;
10332 torture_assert(tctx,
10333 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
10334 "failed to find added printer driver");
10336 if (remote_driver_dir) {
10337 int i;
10338 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
10339 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
10340 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
10341 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
10342 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
10343 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
10347 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
10348 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
10350 return true;
10353 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
10354 struct dcerpc_binding_handle *b,
10355 const char *server_name,
10356 struct spoolss_AddDriverInfo8 *r,
10357 uint32_t flags,
10358 bool ex,
10359 const char *remote_driver_dir)
10361 struct spoolss_AddDriverInfoCtr info_ctr;
10362 union spoolss_DriverInfo info;
10364 info_ctr.level = 8;
10365 info_ctr.info.info8 = r;
10367 if (ex) {
10368 torture_assert(tctx,
10369 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
10370 "failed to test AddPrinterDriverEx level 8");
10371 } else {
10372 torture_assert(tctx,
10373 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
10374 "failed to test AddPrinterDriver level 8");
10377 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10379 if (!ex) {
10380 return true;
10383 torture_assert(tctx,
10384 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
10385 "failed to find added printer driver");
10387 if (remote_driver_dir) {
10388 int i;
10389 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
10390 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
10391 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
10392 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
10393 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
10394 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
10398 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
10399 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
10401 return true;
10404 #undef ASSERT_DRIVER_PATH
10406 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
10407 struct dcerpc_binding_handle *b,
10408 const char *server,
10409 const char *driver,
10410 const char *environment,
10411 WERROR expected_result)
10413 struct spoolss_DeletePrinterDriver r;
10415 r.in.server = server;
10416 r.in.architecture = environment;
10417 r.in.driver = driver;
10419 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
10421 torture_assert_ntstatus_ok(tctx,
10422 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
10423 "DeletePrinterDriver failed");
10424 torture_assert_werr_equal(tctx, r.out.result, expected_result,
10425 "DeletePrinterDriver failed with unexpected result");
10427 return true;
10430 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
10431 struct dcerpc_binding_handle *b,
10432 const char *server,
10433 const char *driver,
10434 const char *environment,
10435 uint32_t delete_flags,
10436 uint32_t version,
10437 WERROR expected_result)
10439 struct spoolss_DeletePrinterDriverEx r;
10441 r.in.server = server;
10442 r.in.architecture = environment;
10443 r.in.driver = driver;
10444 r.in.delete_flags = delete_flags;
10445 r.in.version = version;
10447 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
10449 torture_assert_ntstatus_ok(tctx,
10450 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
10451 "DeletePrinterDriverEx failed");
10452 torture_assert_werr_equal(tctx, r.out.result, expected_result,
10453 "DeletePrinterDriverEx failed with unexpected result");
10455 return true;
10458 static bool test_DeletePrinterDriver(struct torture_context *tctx,
10459 struct dcerpc_binding_handle *b,
10460 const char *server_name,
10461 const char *driver,
10462 const char *environment)
10464 torture_assert(tctx,
10465 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
10466 "failed to delete driver");
10468 torture_assert(tctx,
10469 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
10470 "failed to delete driver");
10472 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
10473 torture_fail(tctx, "deleted driver still enumerated");
10476 torture_assert(tctx,
10477 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
10478 "2nd delete failed");
10480 return true;
10483 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
10484 struct dcerpc_binding_handle *b,
10485 const char *server_name,
10486 const char *driver,
10487 const char *environment,
10488 uint32_t delete_flags,
10489 uint32_t version)
10491 torture_assert(tctx,
10492 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
10493 "failed to delete driver");
10495 torture_assert(tctx,
10496 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
10497 "failed to delete driver");
10499 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
10500 torture_fail(tctx, "deleted driver still enumerated");
10503 torture_assert(tctx,
10504 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
10505 "2nd delete failed");
10507 return true;
10510 static bool test_PrinterDriver_args(struct torture_context *tctx,
10511 struct dcerpc_binding_handle *b,
10512 const char *server_name,
10513 uint32_t level,
10514 struct spoolss_AddDriverInfo8 *r,
10515 uint32_t add_flags,
10516 uint32_t delete_flags,
10517 uint32_t delete_version,
10518 bool ex,
10519 const char *remote_driver_dir)
10521 bool ret = true;
10523 switch (level) {
10524 case 1:
10525 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10526 break;
10527 case 2:
10528 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10529 break;
10530 case 3:
10531 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10532 break;
10533 case 4:
10534 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10535 break;
10536 case 6:
10537 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10538 break;
10539 case 8:
10540 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
10541 break;
10542 default:
10543 return false;
10546 if (ret == false) {
10547 return ret;
10550 if (level == 1) {
10551 return ret;
10554 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10556 if (!ex && (level == 6 || level == 8)) {
10557 return ret;
10561 struct dcerpc_pipe *p2;
10562 struct policy_handle hive_handle;
10563 struct dcerpc_binding_handle *b2;
10565 torture_assert_ntstatus_ok(tctx,
10566 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
10567 "could not open winreg pipe");
10568 b2 = p2->binding_handle;
10570 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
10572 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
10574 test_winreg_CloseKey(tctx, b2, &hive_handle);
10576 talloc_free(p2);
10579 if (ex) {
10580 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
10581 } else {
10582 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
10586 static bool fillup_printserver_info(struct torture_context *tctx,
10587 struct dcerpc_pipe *p,
10588 struct torture_driver_context *d)
10590 struct policy_handle server_handle;
10591 struct dcerpc_binding_handle *b = p->binding_handle;
10592 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10594 torture_assert(tctx,
10595 test_OpenPrinter_server(tctx, p, &server_handle),
10596 "failed to open printserver");
10597 torture_assert(tctx,
10598 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
10599 "failed to get environment");
10600 torture_assert(tctx,
10601 test_ClosePrinter(tctx, b, &server_handle),
10602 "failed to close printserver");
10604 torture_assert(tctx,
10605 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
10606 d->local.environment ? d->local.environment : d->remote.environment,
10607 &d->remote.driver_directory),
10608 "failed to get driver directory");
10610 return true;
10613 static const char *driver_directory_dir(const char *driver_directory)
10615 char *p;
10617 p = strrchr(driver_directory, '\\');
10618 if (p) {
10619 return p+1;
10622 return NULL;
10625 static const char *driver_directory_share(struct torture_context *tctx,
10626 const char *driver_directory)
10628 const char *p;
10629 char *tok;
10631 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
10632 driver_directory += 2;
10635 p = talloc_strdup(tctx, driver_directory);
10637 torture_assert(tctx,
10638 next_token_talloc(tctx, &p, &tok, "\\"),
10639 "cannot explode uri");
10640 torture_assert(tctx,
10641 next_token_talloc(tctx, &p, &tok, "\\"),
10642 "cannot explode uri");
10644 return tok;
10647 #define CREATE_PRINTER_DRIVER_PATH(_d, _file) \
10648 talloc_asprintf((_d), "%s\\%s\\%s", (_d)->remote.driver_directory, (_d)->remote.driver_upload_directory, (_file))
10651 static bool create_printer_driver_directory(struct torture_context *tctx,
10652 struct smbcli_state *cli,
10653 struct torture_driver_context *d)
10655 char *driver_dir;
10657 if (d->remote.driver_upload_directory == NULL) {
10658 return true;
10661 driver_dir = talloc_asprintf(tctx,
10662 "%s\\%s",
10663 driver_directory_dir(d->remote.driver_directory),
10664 d->remote.driver_upload_directory);
10665 torture_assert_not_null(tctx, driver_dir, "ENOMEM");
10667 torture_comment(tctx,
10668 "Create remote driver directory: %s\n",
10669 driver_dir);
10671 torture_assert_ntstatus_ok(tctx,
10672 smbcli_mkdir(cli->tree,
10673 driver_dir),
10674 "Failed to create driver directory");
10676 return true;
10679 static bool upload_printer_driver_file(struct torture_context *tctx,
10680 struct smbcli_state *cli,
10681 struct torture_driver_context *d,
10682 const char *file_name)
10684 FILE *f;
10685 int fnum;
10686 uint8_t *buf;
10687 int maxwrite = 64512;
10688 off_t nread = 0;
10689 size_t start = 0;
10690 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
10691 const char *remote_name;
10692 const char *local_name;
10693 const char *p;
10695 if (!file_name || strlen(file_name) == 0) {
10696 return true;
10699 p = strrchr(file_name, '\\');
10700 if (p == NULL) {
10701 p = file_name;
10702 } else {
10703 p++;
10706 local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, p);
10707 torture_assert_not_null(tctx, local_name, "ENOMEM");
10708 if (d->remote.driver_upload_directory != NULL) {
10709 remote_name = talloc_asprintf(tctx,
10710 "%s\\%s\\%s",
10711 remote_dir,
10712 d->remote.driver_upload_directory,
10714 } else {
10715 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, p);
10717 torture_assert_not_null(tctx, remote_name, "ENOMEM");
10719 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
10721 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
10722 if (fnum == -1) {
10723 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
10726 f = fopen(local_name, "r");
10727 if (f == NULL) {
10728 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
10731 buf = talloc_array(tctx, uint8_t, maxwrite);
10732 if (!buf) {
10733 fclose(f);
10734 return false;
10737 while (!feof(f)) {
10738 int n = maxwrite;
10739 int ret;
10741 if ((n = fread(buf, 1, n, f)) < 1) {
10742 if((n == 0) && feof(f))
10743 break; /* Empty local file. */
10745 torture_warning(tctx,
10746 "failed to read file: %s\n", strerror(errno));
10747 break;
10750 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
10752 if (n != ret) {
10753 torture_warning(tctx,
10754 "failed to write file: %s\n", smbcli_errstr(cli->tree));
10755 break;
10758 nread += n;
10761 fclose(f);
10763 torture_assert_ntstatus_ok(tctx,
10764 smbcli_close(cli->tree, fnum),
10765 "failed to close file");
10767 return true;
10770 static bool connect_printer_driver_share(struct torture_context *tctx,
10771 const char *server_name,
10772 const char *share_name,
10773 struct smbcli_state **cli)
10775 struct smbcli_options smb_options;
10776 struct smbcli_session_options smb_session_options;
10778 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
10779 share_name, server_name);
10781 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
10782 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
10784 torture_assert_ntstatus_ok(tctx,
10785 smbcli_full_connection(tctx, cli, server_name,
10786 lpcfg_smb_ports(tctx->lp_ctx),
10787 share_name, NULL,
10788 lpcfg_socket_options(tctx->lp_ctx),
10789 samba_cmdline_get_creds(),
10790 lpcfg_resolve_context(tctx->lp_ctx),
10791 tctx->ev,
10792 &smb_options,
10793 &smb_session_options,
10794 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
10795 "failed to open driver share");
10797 return true;
10800 static bool upload_printer_driver(struct torture_context *tctx,
10801 const char *server_name,
10802 struct torture_driver_context *d)
10804 struct smbcli_state *cli;
10805 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10806 int i;
10808 torture_assert(tctx,
10809 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10810 "failed to connect to driver share");
10812 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
10813 server_name, share_name);
10815 torture_assert(tctx,
10816 create_printer_driver_directory(tctx, cli, d),
10817 "failed to create driver directory");
10819 torture_assert(tctx,
10820 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10821 "failed to upload driver_path");
10822 torture_assert(tctx,
10823 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
10824 "failed to upload data_file");
10825 torture_assert(tctx,
10826 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
10827 "failed to upload config_file");
10828 torture_assert(tctx,
10829 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
10830 "failed to upload help_file");
10831 if (d->info8.dependent_files) {
10832 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10833 torture_assert(tctx,
10834 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10835 "failed to upload dependent_files");
10839 talloc_free(cli);
10841 return true;
10844 static bool check_printer_driver_file(struct torture_context *tctx,
10845 struct smbcli_state *cli,
10846 struct torture_driver_context *d,
10847 const char *file_name)
10849 const char *remote_arch_dir = NULL;
10850 const char *remote_name = NULL;
10851 int fnum;
10853 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
10855 remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
10856 torture_assert_not_null(tctx, remote_arch_dir, "remote_arch_dir is null");
10858 remote_name = talloc_asprintf(tctx,
10859 "%s\\%d\\%s",
10860 remote_arch_dir,
10861 d->info8.version,
10862 file_name);
10863 torture_assert_not_null(tctx, remote_name, "renote_name is null");
10865 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
10867 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
10868 if (fnum == -1) {
10869 return false;
10872 torture_assert_ntstatus_ok(tctx,
10873 smbcli_close(cli->tree, fnum),
10874 "failed to close driver file");
10876 return true;
10879 static bool check_printer_driver_files(struct torture_context *tctx,
10880 const char *server_name,
10881 struct torture_driver_context *d,
10882 bool expect_exist)
10884 struct smbcli_state *cli;
10885 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10886 int i;
10888 torture_assert(tctx,
10889 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10890 "failed to connect to driver share");
10892 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
10893 (expect_exist ? "": "non-"),
10894 server_name, share_name);
10896 if (d->info8.driver_path && d->info8.driver_path[0]) {
10897 torture_assert(tctx,
10898 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
10899 "failed driver_path check");
10901 if (d->info8.data_file && d->info8.data_file[0]) {
10902 torture_assert(tctx,
10903 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
10904 "failed data_file check");
10906 if (d->info8.config_file && d->info8.config_file[0]) {
10907 torture_assert(tctx,
10908 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
10909 "failed config_file check");
10911 if (d->info8.help_file && d->info8.help_file[0]) {
10912 torture_assert(tctx,
10913 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
10914 "failed help_file check");
10916 if (d->info8.dependent_files) {
10917 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10918 torture_assert(tctx,
10919 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
10920 "failed dependent_files check");
10924 talloc_free(cli);
10926 return true;
10929 static bool remove_printer_driver_file(struct torture_context *tctx,
10930 struct smbcli_state *cli,
10931 struct torture_driver_context *d,
10932 const char *file_name)
10934 const char *remote_name;
10935 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
10937 if (!file_name || strlen(file_name) == 0) {
10938 return true;
10941 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
10943 torture_comment(tctx, "Removing %s\n", remote_name);
10945 torture_assert_ntstatus_ok(tctx,
10946 smbcli_unlink(cli->tree, remote_name),
10947 "failed to unlink");
10949 return true;
10952 static bool remove_printer_driver(struct torture_context *tctx,
10953 const char *server_name,
10954 struct torture_driver_context *d)
10956 struct smbcli_state *cli;
10957 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10958 int i;
10960 torture_assert(tctx,
10961 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10962 "failed to connect to driver share");
10964 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
10965 server_name, share_name);
10967 torture_assert(tctx,
10968 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10969 "failed to remove driver_path");
10970 torture_assert(tctx,
10971 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
10972 "failed to remove data_file");
10973 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
10974 torture_assert(tctx,
10975 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
10976 "failed to remove config_file");
10978 torture_assert(tctx,
10979 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
10980 "failed to remove help_file");
10981 if (d->info8.dependent_files) {
10982 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10983 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
10984 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
10985 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
10986 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
10987 continue;
10989 torture_assert(tctx,
10990 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10991 "failed to remove dependent_files");
10995 talloc_free(cli);
10997 return true;
11001 static bool test_add_driver_arg(struct torture_context *tctx,
11002 struct dcerpc_pipe *p,
11003 struct torture_driver_context *d)
11005 bool ret = true;
11006 struct dcerpc_binding_handle *b = p->binding_handle;
11007 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11008 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
11009 int i;
11010 struct spoolss_AddDriverInfo8 info8;
11011 uint32_t add_flags = APD_COPY_NEW_FILES;
11012 uint32_t delete_flags = 0;
11014 ZERO_STRUCT(info8);
11016 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
11017 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
11019 torture_assert(tctx,
11020 fillup_printserver_info(tctx, p, d),
11021 "failed to fillup printserver info");
11023 if (!directory_exist(d->local.driver_directory)) {
11024 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11027 torture_assert(tctx,
11028 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11029 "failed to upload printer driver");
11031 info8 = d->info8;
11032 if (d->info8.dependent_files) {
11033 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
11034 if (d->info8.dependent_files->string) {
11035 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
11037 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
11038 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
11039 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
11044 for (i=0; i < ARRAY_SIZE(levels); i++) {
11046 if (torture_setting_bool(tctx, "samba3", false)) {
11047 switch (levels[i]) {
11048 case 2:
11049 case 4:
11050 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
11051 continue;
11052 default:
11053 break;
11056 if (torture_setting_bool(tctx, "w2k3", false)) {
11057 switch (levels[i]) {
11058 case 8:
11059 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
11060 continue;
11061 default:
11062 break;
11066 torture_comment(tctx,
11067 "Testing PrinterDriver%s '%s' add & delete level %d\n",
11068 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
11070 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);
11073 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
11074 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
11075 if (d->info8.config_file) {
11076 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
11078 if (d->info8.help_file) {
11079 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
11081 if (d->info8.dependent_files && d->info8.dependent_files->string) {
11082 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
11083 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
11087 for (i=0; i < ARRAY_SIZE(levels); i++) {
11089 if (torture_setting_bool(tctx, "samba3", false)) {
11090 switch (levels[i]) {
11091 case 2:
11092 case 4:
11093 continue;
11094 default:
11095 break;
11098 if (torture_setting_bool(tctx, "w2k3", false)) {
11099 switch (levels[i]) {
11100 case 8:
11101 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
11102 continue;
11103 default:
11104 break;
11108 torture_comment(tctx,
11109 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
11110 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
11112 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);
11115 torture_assert(tctx,
11116 remove_printer_driver(tctx, dcerpc_server_name(p), d),
11117 "failed to remove printer driver");
11119 torture_comment(tctx, "\n");
11121 return ret;
11124 static bool test_add_driver_ex_64(struct torture_context *tctx,
11125 struct dcerpc_pipe *p)
11127 struct torture_driver_context *d;
11129 d = talloc_zero(tctx, struct torture_driver_context);
11131 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
11132 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
11134 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11135 d->info8.driver_name = TORTURE_DRIVER_EX;
11136 d->info8.architecture = d->local.environment;
11137 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11138 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11139 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11140 d->ex = true;
11142 return test_add_driver_arg(tctx, p, d);
11145 static bool test_add_driver_ex_32(struct torture_context *tctx,
11146 struct dcerpc_pipe *p)
11148 struct torture_driver_context *d;
11150 d = talloc_zero(tctx, struct torture_driver_context);
11152 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
11153 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
11155 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11156 d->info8.driver_name = TORTURE_DRIVER_EX;
11157 d->info8.architecture = d->local.environment;
11158 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11159 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11160 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11161 d->ex = true;
11163 return test_add_driver_arg(tctx, p, d);
11166 static bool test_add_driver_64(struct torture_context *tctx,
11167 struct dcerpc_pipe *p)
11169 struct torture_driver_context *d;
11171 d = talloc_zero(tctx, struct torture_driver_context);
11173 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
11174 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
11176 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11177 d->info8.driver_name = TORTURE_DRIVER_ADD;
11178 d->info8.architecture = d->local.environment;
11179 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11180 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11181 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11182 d->ex = false;
11184 return test_add_driver_arg(tctx, p, d);
11187 static bool test_add_driver_32(struct torture_context *tctx,
11188 struct dcerpc_pipe *p)
11190 struct torture_driver_context *d;
11192 d = talloc_zero(tctx, struct torture_driver_context);
11194 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
11195 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
11197 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11198 d->info8.driver_name = TORTURE_DRIVER_ADD;
11199 d->info8.architecture = d->local.environment;
11200 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11201 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11202 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11203 d->ex = false;
11205 return test_add_driver_arg(tctx, p, d);
11208 static bool test_add_driver_adobe(struct torture_context *tctx,
11209 struct dcerpc_pipe *p)
11211 struct torture_driver_context *d;
11213 if (!torture_setting_bool(tctx, "samba3", false)) {
11214 torture_skip(tctx, "skipping adobe test which only works against samba3");
11217 d = talloc_zero(tctx, struct torture_driver_context);
11219 d->local.environment = talloc_strdup(d, "Windows 4.0");
11220 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
11222 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
11223 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
11224 d->info8.architecture = d->local.environment;
11225 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
11226 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
11227 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
11228 #if 0
11229 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
11230 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
11231 #endif
11232 d->ex = false;
11234 return test_add_driver_arg(tctx, p, d);
11237 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
11238 struct dcerpc_pipe *p)
11240 struct torture_driver_context *d;
11241 struct spoolss_StringArray *a;
11243 if (!torture_setting_bool(tctx, "samba3", false)) {
11244 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
11247 d = talloc_zero(tctx, struct torture_driver_context);
11249 d->local.environment = talloc_strdup(d, "Windows 4.0");
11250 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
11252 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
11253 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
11254 d->info8.architecture = d->local.environment;
11255 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
11256 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
11257 d->info8.config_file = NULL;
11258 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
11259 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
11260 d->info8.default_datatype = talloc_strdup(d, "RAW");
11262 a = talloc_zero(d, struct spoolss_StringArray);
11263 a->string = talloc_zero_array(a, const char *, 7);
11264 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
11265 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
11266 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
11267 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
11268 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
11269 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
11271 d->info8.dependent_files = a;
11272 d->ex = false;
11274 return test_add_driver_arg(tctx, p, d);
11277 static bool test_add_driver_timestamps(struct torture_context *tctx,
11278 struct dcerpc_pipe *p)
11280 struct torture_driver_context *d;
11281 struct timeval t = timeval_current();
11283 d = talloc_zero(tctx, struct torture_driver_context);
11285 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
11286 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
11288 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11289 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
11290 d->info8.architecture = d->local.environment;
11291 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11292 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11293 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11294 d->info8.driver_date = timeval_to_nttime(&t);
11295 d->ex = true;
11297 torture_assert(tctx,
11298 test_add_driver_arg(tctx, p, d),
11299 "");
11301 unix_to_nt_time(&d->info8.driver_date, 1);
11303 torture_assert(tctx,
11304 test_add_driver_arg(tctx, p, d),
11305 "");
11307 return true;
11310 static bool test_multiple_drivers(struct torture_context *tctx,
11311 struct dcerpc_pipe *p)
11313 struct torture_driver_context *d;
11314 struct dcerpc_binding_handle *b = p->binding_handle;
11315 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11316 int i;
11317 struct spoolss_AddDriverInfo8 info8;
11318 uint32_t add_flags = APD_COPY_NEW_FILES;
11319 uint32_t delete_flags = 0;
11321 d = talloc_zero(tctx, struct torture_driver_context);
11323 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
11324 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
11326 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11327 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11328 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11329 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11330 d->info8.architecture = d->local.environment;
11331 d->ex = true;
11333 torture_assert(tctx,
11334 fillup_printserver_info(tctx, p, d),
11335 "failed to fillup printserver info");
11337 if (!directory_exist(d->local.driver_directory)) {
11338 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11341 torture_assert(tctx,
11342 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11343 "failed to upload printer driver");
11345 info8 = d->info8;
11347 for (i=0; i < 3; i++) {
11348 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
11350 torture_assert(tctx,
11351 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
11352 "failed to add driver");
11355 torture_assert(tctx,
11356 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
11357 "failed to delete driver");
11359 torture_assert(tctx,
11360 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
11361 "torture_test_driver_1 no longer on the server");
11363 torture_assert(tctx,
11364 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
11365 "torture_test_driver_2 no longer on the server");
11367 torture_assert(tctx,
11368 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
11369 "failed to delete driver");
11371 torture_assert(tctx,
11372 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
11373 "torture_test_driver_2 no longer on the server");
11375 torture_assert(tctx,
11376 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
11377 "failed to delete driver");
11379 torture_assert(tctx,
11380 remove_printer_driver(tctx, dcerpc_server_name(p), d),
11381 "failed to remove printer driver");
11383 return true;
11386 static bool test_driver_copy_from_directory(struct torture_context *tctx,
11387 struct dcerpc_pipe *p,
11388 const char *architecture)
11390 struct torture_driver_context *d;
11391 struct spoolss_StringArray *a;
11392 uint32_t add_flags = APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY|APD_RETURN_BLOCKING_STATUS_CODE;
11393 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
11394 struct dcerpc_binding_handle *b = p->binding_handle;
11395 const char *server_name_slash = talloc_asprintf(tctx,
11396 "\\\\%s",
11397 dcerpc_server_name(p));
11398 struct GUID guid = GUID_random();
11399 bool ok = false;
11401 d = talloc_zero(tctx, struct torture_driver_context);
11402 torture_assert_not_null(tctx, d, "ENOMEM");
11404 d->local.environment = talloc_strdup(d, architecture);
11405 torture_assert_not_null_goto(tctx, d->local.environment, ok, done, "ENOMEM");
11407 if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
11408 d->local.driver_directory =
11409 talloc_strdup(d, "/usr/share/cups/drivers/x64");
11410 } else {
11411 d->local.driver_directory =
11412 talloc_strdup(d, "/usr/share/cups/drivers/i386");
11414 torture_assert_not_null_goto(tctx, d->local.driver_directory, ok, done, "ENOMEM");
11416 d->remote.driver_upload_directory = GUID_string2(d, &guid);
11417 torture_assert_not_null_goto(tctx, d->remote.driver_upload_directory, ok, done, "ENOMEM");
11419 torture_assert(tctx,
11420 fillup_printserver_info(tctx, p, d),
11421 "failed to fillup printserver info");
11423 d->ex = true;
11424 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11425 d->info8.driver_name = TORTURE_DRIVER_COPY_DIR;
11426 d->info8.architecture = d->local.environment;
11428 d->info8.driver_path = CREATE_PRINTER_DRIVER_PATH(d, "pscript5.dll");
11429 torture_assert_not_null_goto(tctx, d->info8.driver_path, ok, done, "ENOMEM");
11430 d->info8.data_file = CREATE_PRINTER_DRIVER_PATH(d, "cups6.ppd");
11431 torture_assert_not_null_goto(tctx, d->info8.data_file, ok, done, "ENOMEM");
11432 d->info8.config_file = CREATE_PRINTER_DRIVER_PATH(d, "cupsui6.dll");
11433 torture_assert_not_null_goto(tctx, d->info8.config_file, ok, done, "ENOMEM");
11434 d->info8.help_file = CREATE_PRINTER_DRIVER_PATH(d, "pscript.hlp");
11435 torture_assert_not_null_goto(tctx, d->info8.help_file, ok, done, "ENOMEM");
11437 a = talloc_zero(d, struct spoolss_StringArray);
11438 torture_assert_not_null_goto(tctx, a, ok, done, "ENOMEM");
11439 a->string = talloc_zero_array(a, const char *, 3);
11440 torture_assert_not_null_goto(tctx, a->string, ok, done, "ENOMEM");
11441 a->string[0] = CREATE_PRINTER_DRIVER_PATH(d, "cups6.inf");
11442 torture_assert_not_null_goto(tctx, a->string[0], ok, done, "ENOMEM");
11443 a->string[1] = CREATE_PRINTER_DRIVER_PATH(d, "cups6.ini");
11444 torture_assert_not_null_goto(tctx, a->string[1], ok, done, "ENOMEM");
11446 d->info8.dependent_files = a;
11448 if (!directory_exist(d->local.driver_directory)) {
11449 torture_skip(tctx,
11450 "Skipping Printer Driver test as no local drivers "
11451 "are available");
11454 torture_assert(tctx,
11455 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11456 "failed to upload printer driver");
11458 torture_assert(tctx,
11459 test_AddPrinterDriver_args_level_3(tctx,
11461 server_name_slash,
11462 &d->info8,
11463 add_flags,
11464 true,
11465 NULL),
11466 "failed to add driver");
11468 torture_assert(tctx,
11469 test_DeletePrinterDriverEx(tctx,
11471 server_name_slash,
11472 d->info8.driver_name,
11473 d->local.environment,
11474 delete_flags,
11475 d->info8.version),
11476 "failed to delete driver");
11478 torture_assert(tctx,
11479 check_printer_driver_files(tctx,
11480 dcerpc_server_name(p),
11482 false),
11483 "printer driver file check failed");
11485 ok = true;
11486 done:
11487 talloc_free(d);
11488 return ok;
11491 static bool test_driver_copy_from_directory_64(struct torture_context *tctx,
11492 struct dcerpc_pipe *p)
11494 return test_driver_copy_from_directory(tctx, p, SPOOLSS_ARCHITECTURE_x64);
11497 static bool test_driver_copy_from_directory_32(struct torture_context *tctx,
11498 struct dcerpc_pipe *p)
11500 return test_driver_copy_from_directory(tctx, p, SPOOLSS_ARCHITECTURE_NT_X86);
11503 static bool test_del_driver_all_files(struct torture_context *tctx,
11504 struct dcerpc_pipe *p)
11506 struct torture_driver_context *d;
11507 struct spoolss_StringArray *a;
11508 uint32_t add_flags = APD_COPY_NEW_FILES;
11509 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
11510 struct dcerpc_binding_handle *b = p->binding_handle;
11511 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11513 d = talloc_zero(tctx, struct torture_driver_context);
11515 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
11516 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
11518 d->ex = true;
11519 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11520 d->info8.driver_name = TORTURE_DRIVER_DELETER;
11521 d->info8.architecture = d->local.environment;
11522 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
11523 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
11524 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
11525 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
11527 a = talloc_zero(d, struct spoolss_StringArray);
11528 a->string = talloc_zero_array(a, const char *, 3);
11529 a->string[0] = talloc_strdup(a->string, "cups6.inf");
11530 a->string[1] = talloc_strdup(a->string, "cups6.ini");
11532 d->info8.dependent_files = a;
11534 torture_assert(tctx,
11535 fillup_printserver_info(tctx, p, d),
11536 "failed to fillup printserver info");
11538 if (!directory_exist(d->local.driver_directory)) {
11539 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11542 torture_assert(tctx,
11543 upload_printer_driver(tctx, dcerpc_server_name(p), d),
11544 "failed to upload printer driver");
11546 torture_assert(tctx,
11547 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
11548 "failed to add driver");
11550 torture_assert(tctx,
11551 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
11552 d->info8.driver_name,
11553 d->info8.architecture,
11554 delete_flags,
11555 d->info8.version),
11556 "failed to delete driver");
11558 torture_assert(tctx,
11559 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
11560 "printer driver file check failed");
11562 talloc_free(d);
11563 return true;
11566 static bool test_del_driver_unused_files(struct torture_context *tctx,
11567 struct dcerpc_pipe *p)
11569 struct torture_driver_context *d1;
11570 struct torture_driver_context *d2;
11571 uint32_t add_flags = APD_COPY_NEW_FILES;
11572 struct dcerpc_binding_handle *b = p->binding_handle;
11573 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
11575 d1 = talloc_zero(tctx, struct torture_driver_context);
11576 d1->ex = true;
11578 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
11579 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
11581 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11582 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
11583 d1->info8.architecture = NULL;
11584 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
11585 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
11586 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
11587 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
11588 d1->info8.architecture = d1->local.environment;
11590 d2 = talloc_zero(tctx, struct torture_driver_context);
11591 d2->ex = true;
11593 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
11594 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
11596 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
11597 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
11598 d2->info8.architecture = NULL;
11599 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
11600 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
11601 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
11602 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
11603 d2->info8.architecture = d2->local.environment;
11605 torture_assert(tctx,
11606 fillup_printserver_info(tctx, p, d1),
11607 "failed to fillup printserver info");
11608 torture_assert(tctx,
11609 fillup_printserver_info(tctx, p, d2),
11610 "failed to fillup printserver info");
11612 if (!directory_exist(d1->local.driver_directory)) {
11613 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
11616 torture_assert(tctx,
11617 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
11618 "failed to upload printer driver");
11619 torture_assert(tctx,
11620 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
11621 "failed to add driver");
11623 torture_assert(tctx,
11624 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
11625 "failed to upload printer driver");
11626 torture_assert(tctx,
11627 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
11628 "failed to add driver");
11630 /* some files are in use by a separate driver, should fail */
11631 torture_assert(tctx,
11632 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
11633 d1->info8.driver_name,
11634 d1->info8.architecture,
11635 DPD_DELETE_ALL_FILES,
11636 d1->info8.version,
11637 WERR_PRINTER_DRIVER_IN_USE),
11638 "invalid delete driver response");
11640 /* should only delete files not in use by other driver */
11641 torture_assert(tctx,
11642 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
11643 d1->info8.driver_name,
11644 d1->info8.architecture,
11645 DPD_DELETE_UNUSED_FILES,
11646 d1->info8.version,
11647 WERR_OK),
11648 "failed to delete driver (unused files)");
11650 /* check non-overlapping were deleted */
11651 d1->info8.driver_path = NULL;
11652 d1->info8.help_file = NULL;
11653 torture_assert(tctx,
11654 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
11655 "printer driver file check failed");
11656 /* d2 files should be uneffected */
11657 torture_assert(tctx,
11658 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
11659 "printer driver file check failed");
11661 torture_assert(tctx,
11662 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
11663 d2->info8.driver_name,
11664 d2->info8.architecture,
11665 DPD_DELETE_ALL_FILES,
11666 d2->info8.version,
11667 WERR_OK),
11668 "failed to delete driver");
11670 torture_assert(tctx,
11671 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
11672 "printer driver file check failed");
11674 talloc_free(d1);
11675 talloc_free(d2);
11676 return true;
11679 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
11681 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
11683 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
11684 "driver", &ndr_table_spoolss);
11685 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
11686 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
11688 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
11689 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
11691 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
11693 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
11695 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
11697 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
11699 torture_rpc_tcase_add_test(tcase,
11700 "test_driver_copy_from_directory_64",
11701 test_driver_copy_from_directory_64);
11703 torture_rpc_tcase_add_test(tcase,
11704 "test_driver_copy_from_directory_32",
11705 test_driver_copy_from_directory_32);
11707 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
11709 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
11711 return suite;