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