torture: support printer publish pending responses
[Samba/id10ts.git] / source4 / torture / rpc / spoolss.c
blob4c84bc0d1386e586c2b3c3ddb9e695649b1df200
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(tctx, (W_ERROR_EQUAL(r.out.result, WERR_OK)
1251 || W_ERROR_EQUAL(r.out.result, WERR_IO_PENDING)),
1252 "SetPrinter failed");
1254 return true;
1257 static bool test_SetPrinter_errors(struct torture_context *tctx,
1258 struct dcerpc_binding_handle *b,
1259 struct policy_handle *handle)
1261 struct spoolss_SetPrinter r;
1262 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1263 int i;
1265 struct spoolss_SetPrinterInfoCtr info_ctr;
1266 struct spoolss_DevmodeContainer devmode_ctr;
1267 struct sec_desc_buf secdesc_ctr;
1269 info_ctr.level = 0;
1270 info_ctr.info.info0 = NULL;
1272 ZERO_STRUCT(devmode_ctr);
1273 ZERO_STRUCT(secdesc_ctr);
1275 r.in.handle = handle;
1276 r.in.info_ctr = &info_ctr;
1277 r.in.devmode_ctr = &devmode_ctr;
1278 r.in.secdesc_ctr = &secdesc_ctr;
1279 r.in.command = 0;
1281 torture_comment(tctx, "Testing SetPrinter all zero\n");
1283 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1284 "failed to call SetPrinter");
1285 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1286 "failed to call SetPrinter");
1288 again:
1289 for (i=0; i < ARRAY_SIZE(levels); i++) {
1291 struct spoolss_SetPrinterInfo0 info0;
1292 struct spoolss_SetPrinterInfo1 info1;
1293 struct spoolss_SetPrinterInfo2 info2;
1294 struct spoolss_SetPrinterInfo3 info3;
1295 struct spoolss_SetPrinterInfo4 info4;
1296 struct spoolss_SetPrinterInfo5 info5;
1297 struct spoolss_SetPrinterInfo6 info6;
1298 struct spoolss_SetPrinterInfo7 info7;
1299 struct spoolss_SetPrinterInfo8 info8;
1300 struct spoolss_SetPrinterInfo9 info9;
1303 info_ctr.level = levels[i];
1304 switch (levels[i]) {
1305 case 0:
1306 ZERO_STRUCT(info0);
1307 info_ctr.info.info0 = &info0;
1308 break;
1309 case 1:
1310 ZERO_STRUCT(info1);
1311 info_ctr.info.info1 = &info1;
1312 break;
1313 case 2:
1314 ZERO_STRUCT(info2);
1315 info_ctr.info.info2 = &info2;
1316 break;
1317 case 3:
1318 ZERO_STRUCT(info3);
1319 info_ctr.info.info3 = &info3;
1320 break;
1321 case 4:
1322 ZERO_STRUCT(info4);
1323 info_ctr.info.info4 = &info4;
1324 break;
1325 case 5:
1326 ZERO_STRUCT(info5);
1327 info_ctr.info.info5 = &info5;
1328 break;
1329 case 6:
1330 ZERO_STRUCT(info6);
1331 info_ctr.info.info6 = &info6;
1332 break;
1333 case 7:
1334 ZERO_STRUCT(info7);
1335 info_ctr.info.info7 = &info7;
1336 break;
1337 case 8:
1338 ZERO_STRUCT(info8);
1339 info_ctr.info.info8 = &info8;
1340 break;
1341 case 9:
1342 ZERO_STRUCT(info9);
1343 info_ctr.info.info9 = &info9;
1344 break;
1347 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1348 info_ctr.level, r.in.command);
1350 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1351 "failed to call SetPrinter");
1353 switch (r.in.command) {
1354 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1355 /* is ignored for all levels other then 0 */
1356 if (info_ctr.level > 0) {
1357 /* ignored then */
1358 break;
1360 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1361 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1362 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1363 if (info_ctr.level > 0) {
1364 /* is invalid for all levels other then 0 */
1365 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1366 "unexpected error code returned");
1367 continue;
1368 } else {
1369 torture_assert_werr_ok(tctx, r.out.result,
1370 "failed to call SetPrinter with non 0 command");
1371 continue;
1373 break;
1375 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1376 /* FIXME: gd needs further investigation */
1377 default:
1378 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1379 "unexpected error code returned");
1380 continue;
1383 switch (info_ctr.level) {
1384 case 1:
1385 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1386 "unexpected error code returned");
1387 break;
1388 case 2:
1389 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1390 "unexpected error code returned");
1391 break;
1392 case 3:
1393 case 4:
1394 case 5:
1395 case 7:
1396 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1397 "unexpected error code returned");
1398 break;
1399 case 9:
1400 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1401 "unexpected error code returned");
1402 break;
1403 default:
1404 torture_assert_werr_ok(tctx, r.out.result,
1405 "failed to call SetPrinter");
1406 break;
1410 if (r.in.command < 5) {
1411 r.in.command++;
1412 goto again;
1415 return true;
1418 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1420 if ((r->level == 2) && (r->info.info2)) {
1421 r->info.info2->secdesc_ptr = NULL;
1422 r->info.info2->devmode_ptr = NULL;
1426 static bool test_PrinterInfo(struct torture_context *tctx,
1427 struct dcerpc_binding_handle *b,
1428 struct policy_handle *handle)
1430 NTSTATUS status;
1431 struct spoolss_SetPrinter s;
1432 struct spoolss_GetPrinter q;
1433 struct spoolss_GetPrinter q0;
1434 struct spoolss_SetPrinterInfoCtr info_ctr;
1435 union spoolss_PrinterInfo info;
1436 struct spoolss_DevmodeContainer devmode_ctr;
1437 struct sec_desc_buf secdesc_ctr;
1438 uint32_t needed;
1439 bool ret = true;
1440 int i;
1442 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1444 uint32_t status_list[] = {
1445 /* these do not stick
1446 PRINTER_STATUS_PAUSED,
1447 PRINTER_STATUS_ERROR,
1448 PRINTER_STATUS_PENDING_DELETION, */
1449 PRINTER_STATUS_PAPER_JAM,
1450 PRINTER_STATUS_PAPER_OUT,
1451 PRINTER_STATUS_MANUAL_FEED,
1452 PRINTER_STATUS_PAPER_PROBLEM,
1453 PRINTER_STATUS_OFFLINE,
1454 PRINTER_STATUS_IO_ACTIVE,
1455 PRINTER_STATUS_BUSY,
1456 PRINTER_STATUS_PRINTING,
1457 PRINTER_STATUS_OUTPUT_BIN_FULL,
1458 PRINTER_STATUS_NOT_AVAILABLE,
1459 PRINTER_STATUS_WAITING,
1460 PRINTER_STATUS_PROCESSING,
1461 PRINTER_STATUS_INITIALIZING,
1462 PRINTER_STATUS_WARMING_UP,
1463 PRINTER_STATUS_TONER_LOW,
1464 PRINTER_STATUS_NO_TONER,
1465 PRINTER_STATUS_PAGE_PUNT,
1466 PRINTER_STATUS_USER_INTERVENTION,
1467 PRINTER_STATUS_OUT_OF_MEMORY,
1468 PRINTER_STATUS_DOOR_OPEN,
1469 PRINTER_STATUS_SERVER_UNKNOWN,
1470 PRINTER_STATUS_POWER_SAVE,
1471 /* these do not stick
1472 0x02000000,
1473 0x04000000,
1474 0x08000000,
1475 0x10000000,
1476 0x20000000,
1477 0x40000000,
1478 0x80000000 */
1480 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1481 uint32_t attribute_list[] = {
1482 PRINTER_ATTRIBUTE_QUEUED,
1483 /* fails with WERR_INVALID_DATATYPE:
1484 PRINTER_ATTRIBUTE_DIRECT, */
1485 /* does not stick
1486 PRINTER_ATTRIBUTE_DEFAULT, */
1487 PRINTER_ATTRIBUTE_SHARED,
1488 /* does not stick
1489 PRINTER_ATTRIBUTE_NETWORK, */
1490 PRINTER_ATTRIBUTE_HIDDEN,
1491 PRINTER_ATTRIBUTE_LOCAL,
1492 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1493 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1494 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1495 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1496 /* does not stick
1497 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1498 /* fails with WERR_INVALID_DATATYPE:
1499 PRINTER_ATTRIBUTE_RAW_ONLY, */
1500 /* these do not stick
1501 PRINTER_ATTRIBUTE_PUBLISHED,
1502 PRINTER_ATTRIBUTE_FAX,
1503 PRINTER_ATTRIBUTE_TS,
1504 0x00010000,
1505 0x00020000,
1506 0x00040000,
1507 0x00080000,
1508 0x00100000,
1509 0x00200000,
1510 0x00400000,
1511 0x00800000,
1512 0x01000000,
1513 0x02000000,
1514 0x04000000,
1515 0x08000000,
1516 0x10000000,
1517 0x20000000,
1518 0x40000000,
1519 0x80000000 */
1522 ZERO_STRUCT(devmode_ctr);
1523 ZERO_STRUCT(secdesc_ctr);
1525 s.in.handle = handle;
1526 s.in.command = 0;
1527 s.in.info_ctr = &info_ctr;
1528 s.in.devmode_ctr = &devmode_ctr;
1529 s.in.secdesc_ctr = &secdesc_ctr;
1531 q.in.handle = handle;
1532 q.out.info = &info;
1533 q0 = q;
1535 #define TESTGETCALL(call, r) \
1536 r.in.buffer = NULL; \
1537 r.in.offered = 0;\
1538 r.out.needed = &needed; \
1539 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1540 if (!NT_STATUS_IS_OK(status)) { \
1541 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1542 r.in.level, nt_errstr(status), __location__); \
1543 ret = false; \
1544 break; \
1546 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1547 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1548 r.in.buffer = &blob; \
1549 r.in.offered = needed; \
1551 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1552 if (!NT_STATUS_IS_OK(status)) { \
1553 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1554 r.in.level, nt_errstr(status), __location__); \
1555 ret = false; \
1556 break; \
1558 if (!W_ERROR_IS_OK(r.out.result)) { \
1559 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1560 r.in.level, win_errstr(r.out.result), __location__); \
1561 ret = false; \
1562 break; \
1566 #define TESTSETCALL_EXP(call, r, err) \
1567 clear_info2(&info_ctr);\
1568 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1569 if (!NT_STATUS_IS_OK(status)) { \
1570 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1571 r.in.info_ctr->level, nt_errstr(status), __location__); \
1572 ret = false; \
1573 break; \
1575 if (!W_ERROR_IS_OK(err)) { \
1576 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1577 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1578 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1579 ret = false; \
1581 break; \
1583 if (!W_ERROR_IS_OK(r.out.result)) { \
1584 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1585 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1586 ret = false; \
1587 break; \
1590 #define TESTSETCALL(call, r) \
1591 TESTSETCALL_EXP(call, r, WERR_OK)
1593 #define STRING_EQUAL(s1, s2, field) \
1594 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1595 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1596 #field, s2, __location__); \
1597 ret = false; \
1598 break; \
1601 #define MEM_EQUAL(s1, s2, length, field) \
1602 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1603 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1604 #field, (const char *)s2, __location__); \
1605 ret = false; \
1606 break; \
1609 #define INT_EQUAL(i1, i2, field) \
1610 if (i1 != i2) { \
1611 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1612 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1613 ret = false; \
1614 break; \
1617 #define SD_EQUAL(sd1, sd2, field) \
1618 if (!security_descriptor_equal(sd1, sd2)) { \
1619 torture_comment(tctx, "Failed to set %s (%s)\n", \
1620 #field, __location__); \
1621 ret = false; \
1622 break; \
1625 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1626 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1627 q.in.level = lvl1; \
1628 TESTGETCALL(GetPrinter, q) \
1629 info_ctr.level = lvl1; \
1630 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1631 info_ctr.info.info ## lvl1->field1 = value;\
1632 TESTSETCALL_EXP(SetPrinter, s, err) \
1633 info_ctr.info.info ## lvl1->field1 = ""; \
1634 TESTGETCALL(GetPrinter, q) \
1635 info_ctr.info.info ## lvl1->field1 = value; \
1636 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1637 q.in.level = lvl2; \
1638 TESTGETCALL(GetPrinter, q) \
1639 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1640 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1641 } while (0)
1643 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1644 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1645 } while (0);
1647 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1648 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1649 q.in.level = lvl1; \
1650 TESTGETCALL(GetPrinter, q) \
1651 info_ctr.level = lvl1; \
1652 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1653 info_ctr.info.info ## lvl1->field1 = value; \
1654 TESTSETCALL(SetPrinter, s) \
1655 info_ctr.info.info ## lvl1->field1 = 0; \
1656 TESTGETCALL(GetPrinter, q) \
1657 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1658 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1659 q.in.level = lvl2; \
1660 TESTGETCALL(GetPrinter, q) \
1661 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1662 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1663 } while (0)
1665 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1666 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1667 } while (0)
1669 q0.in.level = 0;
1670 do { TESTGETCALL(GetPrinter, q0) } while (0);
1672 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1673 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1675 /* level 0 printername does not stick */
1676 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1677 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1680 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1681 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1682 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1685 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1686 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1687 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1690 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1692 /* servername can be set but does not stick
1693 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1695 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1698 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1702 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1704 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1705 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1706 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1707 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1708 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1709 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1710 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1711 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1712 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1713 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1715 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1716 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1717 attribute_list[i],
1718 (attribute_list[i] | default_attribute)
1719 ); */
1720 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1721 attribute_list[i],
1722 (attribute_list[i] | default_attribute)
1724 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1725 attribute_list[i],
1726 (attribute_list[i] | default_attribute)
1728 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1729 attribute_list[i],
1730 (attribute_list[i] | default_attribute)
1732 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1733 attribute_list[i],
1734 (attribute_list[i] | default_attribute)
1735 ); */
1736 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1737 attribute_list[i],
1738 (attribute_list[i] | default_attribute)
1740 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1741 attribute_list[i],
1742 (attribute_list[i] | default_attribute)
1744 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1745 attribute_list[i],
1746 (attribute_list[i] | default_attribute)
1748 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1749 attribute_list[i],
1750 (attribute_list[i] | default_attribute)
1751 ); */
1752 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1753 attribute_list[i],
1754 (attribute_list[i] | default_attribute)
1756 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1757 attribute_list[i],
1758 (attribute_list[i] | default_attribute)
1760 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1761 attribute_list[i],
1762 (attribute_list[i] | default_attribute)
1766 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1767 /* level 2 sets do not stick
1768 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1770 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1771 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1773 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1776 /* priorities need to be between 0 and 99
1777 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1780 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1781 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1784 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1785 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1787 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1788 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1790 /* does not stick
1791 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1792 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1794 /* does not stick
1795 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1796 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1798 /* FIXME: gd also test devmode and secdesc behavior */
1801 /* verify composition of level 1 description field */
1802 const char *description;
1803 const char *tmp;
1805 q0.in.level = 1;
1806 do { TESTGETCALL(GetPrinter, q0) } while (0);
1808 description = talloc_strdup(tctx, q0.out.info->info1.description);
1810 q0.in.level = 2;
1811 do { TESTGETCALL(GetPrinter, q0) } while (0);
1813 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1814 q0.out.info->info2.printername,
1815 q0.out.info->info2.drivername,
1816 q0.out.info->info2.location);
1818 do { STRING_EQUAL(description, tmp, "description")} while (0);
1821 return ret;
1824 static bool test_security_descriptor_equal(struct torture_context *tctx,
1825 const struct security_descriptor *sd1,
1826 const struct security_descriptor *sd2)
1828 if (sd1 == sd2) {
1829 return true;
1832 if (!sd1 || !sd2) {
1833 torture_comment(tctx, "%s\n", __location__);
1834 return false;
1837 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1838 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1840 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1841 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1843 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1844 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1845 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1846 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1847 return false;
1849 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1850 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1851 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1852 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1853 return false;
1856 return true;
1859 static bool test_sd_set_level(struct torture_context *tctx,
1860 struct dcerpc_binding_handle *b,
1861 struct policy_handle *handle,
1862 uint32_t level,
1863 struct security_descriptor *sd)
1865 struct spoolss_SetPrinterInfoCtr info_ctr;
1866 struct spoolss_DevmodeContainer devmode_ctr;
1867 struct sec_desc_buf secdesc_ctr;
1868 union spoolss_SetPrinterInfo sinfo;
1870 ZERO_STRUCT(devmode_ctr);
1871 ZERO_STRUCT(secdesc_ctr);
1873 switch (level) {
1874 case 2: {
1875 union spoolss_PrinterInfo info;
1876 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1877 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1879 info_ctr.level = 2;
1880 info_ctr.info = sinfo;
1882 break;
1884 case 3: {
1885 struct spoolss_SetPrinterInfo3 info3;
1887 info3.sec_desc_ptr = NULL;
1889 info_ctr.level = 3;
1890 info_ctr.info.info3 = &info3;
1892 break;
1894 default:
1895 return false;
1898 secdesc_ctr.sd = sd;
1900 torture_assert(tctx,
1901 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1903 return true;
1906 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1907 struct dcerpc_binding_handle *b,
1908 struct policy_handle *handle)
1910 union spoolss_PrinterInfo info;
1911 struct security_descriptor *sd1, *sd2;
1912 int i;
1914 /* just compare level 2 and level 3 */
1916 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1918 sd1 = info.info2.secdesc;
1920 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1922 sd2 = info.info3.secdesc;
1924 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1925 "SD level 2 != SD level 3");
1928 /* query level 2, set level 2, query level 2 */
1930 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1932 sd1 = info.info2.secdesc;
1934 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1936 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1938 sd2 = info.info2.secdesc;
1939 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1940 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1941 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1944 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1945 "SD level 2 != SD level 2 after SD has been set via level 2");
1948 /* query level 2, set level 3, query level 2 */
1950 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1952 sd1 = info.info2.secdesc;
1954 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1956 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1958 sd2 = info.info2.secdesc;
1960 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1961 "SD level 2 != SD level 2 after SD has been set via level 3");
1963 /* set modified sd level 3, query level 2 */
1965 for (i=0; i < 93; i++) {
1966 struct security_ace a;
1967 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1968 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1969 a.flags = 0;
1970 a.size = 0; /* autogenerated */
1971 a.access_mask = 0;
1972 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1973 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1976 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1978 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1979 sd2 = info.info2.secdesc;
1981 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1982 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1983 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1986 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1987 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1990 return true;
1994 * wrapper call that saves original sd, runs tests, and restores sd
1997 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1998 struct dcerpc_binding_handle *b,
1999 struct policy_handle *handle)
2001 union spoolss_PrinterInfo info;
2002 struct security_descriptor *sd;
2003 bool ret = true;
2005 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2007 /* save original sd */
2009 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2010 "failed to get initial security descriptor");
2012 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2014 /* run tests */
2016 ret = test_PrinterInfo_SDs(tctx, b, handle);
2018 /* restore original sd */
2020 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2021 "failed to restore initial security descriptor");
2023 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2024 ret ? "succeeded" : "failed");
2027 return ret;
2030 static bool test_devmode_set_level(struct torture_context *tctx,
2031 struct dcerpc_binding_handle *b,
2032 struct policy_handle *handle,
2033 uint32_t level,
2034 struct spoolss_DeviceMode *devmode)
2036 struct spoolss_SetPrinterInfoCtr info_ctr;
2037 struct spoolss_DevmodeContainer devmode_ctr;
2038 struct sec_desc_buf secdesc_ctr;
2039 union spoolss_SetPrinterInfo sinfo;
2041 ZERO_STRUCT(devmode_ctr);
2042 ZERO_STRUCT(secdesc_ctr);
2044 switch (level) {
2045 case 2: {
2046 union spoolss_PrinterInfo info;
2047 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2048 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2050 info_ctr.level = 2;
2051 info_ctr.info = sinfo;
2053 break;
2055 case 8: {
2056 struct spoolss_SetPrinterInfo8 info8;
2058 info8.devmode_ptr = NULL;
2060 info_ctr.level = 8;
2061 info_ctr.info.info8 = &info8;
2063 break;
2065 default:
2066 return false;
2069 devmode_ctr.devmode = devmode;
2071 torture_assert(tctx,
2072 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2074 return true;
2078 static bool test_devicemode_equal(struct torture_context *tctx,
2079 const struct spoolss_DeviceMode *d1,
2080 const struct spoolss_DeviceMode *d2)
2082 if (d1 == d2) {
2083 return true;
2086 if (!d1 || !d2) {
2087 torture_comment(tctx, "%s\n", __location__);
2088 return false;
2090 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2091 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2092 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2093 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2094 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2095 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2096 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2097 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2098 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2099 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2100 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2101 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2102 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2103 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2104 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2105 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2106 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2107 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2108 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2109 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2110 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2111 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2112 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2113 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2114 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2115 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2116 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2117 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2118 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2119 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2121 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2122 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2123 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2124 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2126 return true;
2129 static bool test_devicemode_full(struct torture_context *tctx,
2130 struct dcerpc_binding_handle *b,
2131 struct policy_handle *handle)
2133 struct spoolss_SetPrinter s;
2134 struct spoolss_GetPrinter q;
2135 struct spoolss_GetPrinter q0;
2136 struct spoolss_SetPrinterInfoCtr info_ctr;
2137 struct spoolss_SetPrinterInfo8 info8;
2138 union spoolss_PrinterInfo info;
2139 struct spoolss_DevmodeContainer devmode_ctr;
2140 struct sec_desc_buf secdesc_ctr;
2141 uint32_t needed;
2142 bool ret = true;
2143 NTSTATUS status;
2145 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2146 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2147 q.in.level = lvl1; \
2148 TESTGETCALL(GetPrinter, q) \
2149 info_ctr.level = lvl1; \
2150 if (lvl1 == 2) {\
2151 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2152 } else if (lvl1 == 8) {\
2153 info_ctr.info.info ## lvl1 = &info8; \
2155 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2156 devmode_ctr.devmode->field1 = value; \
2157 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2158 if (W_ERROR_IS_OK(expected_result)) { \
2159 TESTGETCALL(GetPrinter, q) \
2160 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2161 q.in.level = lvl2; \
2162 TESTGETCALL(GetPrinter, q) \
2163 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2165 } while (0)
2167 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2168 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2169 } while (0)
2171 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2172 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2173 } while (0)
2175 ZERO_STRUCT(devmode_ctr);
2176 ZERO_STRUCT(secdesc_ctr);
2177 ZERO_STRUCT(info8);
2179 s.in.handle = handle;
2180 s.in.command = 0;
2181 s.in.info_ctr = &info_ctr;
2182 s.in.devmode_ctr = &devmode_ctr;
2183 s.in.secdesc_ctr = &secdesc_ctr;
2185 q.in.handle = handle;
2186 q.out.info = &info;
2187 q0 = q;
2189 #if 0
2190 const char *devicename;/* [charset(UTF16)] */
2191 enum spoolss_DeviceModeSpecVersion specversion;
2192 uint16_t driverversion;
2193 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2194 uint32_t fields;
2195 #endif
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2199 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);
2200 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2202 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2203 torture_assert(tctx,
2204 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2205 "failed to set devmode");
2207 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);
2208 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2210 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2211 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2212 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2213 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2214 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2215 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2216 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2217 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2218 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2219 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2220 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2221 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2222 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2223 #if 0
2224 const char *formname;/* [charset(UTF16)] */
2225 #endif
2226 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2227 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2228 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2229 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2230 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2231 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2232 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2233 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2234 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2235 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2237 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2238 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2239 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2241 return ret;
2244 static bool call_OpenPrinterEx(struct torture_context *tctx,
2245 struct dcerpc_pipe *p,
2246 const char *name,
2247 struct spoolss_DeviceMode *devmode,
2248 struct policy_handle *handle);
2250 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2251 struct dcerpc_pipe *p,
2252 struct policy_handle *handle,
2253 const char *name)
2255 union spoolss_PrinterInfo info;
2256 struct spoolss_DeviceMode *devmode;
2257 struct spoolss_DeviceMode *devmode2;
2258 struct policy_handle handle_devmode;
2259 struct dcerpc_binding_handle *b = p->binding_handle;
2261 /* simply compare level8 and level2 devmode */
2263 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2265 devmode = info.info8.devmode;
2267 if (devmode && devmode->size == 0) {
2268 torture_fail(tctx,
2269 "devmode of zero size!");
2272 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2274 devmode2 = info.info2.devmode;
2276 if (devmode2 && devmode2->size == 0) {
2277 torture_fail(tctx,
2278 "devmode of zero size!");
2281 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2282 "DM level 8 != DM level 2");
2285 /* set devicemode level 8 and see if it persists */
2287 devmode->copies = 93;
2288 devmode->formname = talloc_strdup(tctx, "Legal");
2290 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2292 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2294 devmode2 = info.info8.devmode;
2296 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2297 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2299 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2301 devmode2 = info.info2.devmode;
2303 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2304 "modified DM level 8 != DM level 2");
2307 /* set devicemode level 2 and see if it persists */
2309 devmode->copies = 39;
2310 devmode->formname = talloc_strdup(tctx, "Executive");
2312 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2314 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2316 devmode2 = info.info8.devmode;
2318 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2319 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2321 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2323 devmode2 = info.info2.devmode;
2325 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2326 "modified DM level 8 != DM level 2");
2329 /* check every single bit in public part of devicemode */
2331 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2332 "failed to set every single devicemode component");
2335 /* change formname upon open and see if it persists in getprinter calls */
2337 devmode->formname = talloc_strdup(tctx, "A4");
2338 devmode->copies = 42;
2340 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2341 "failed to open printer handle");
2343 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2345 devmode2 = info.info8.devmode;
2347 if (strequal(devmode->devicename, devmode2->devicename)) {
2348 torture_warning(tctx, "devicenames are the same\n");
2349 } else {
2350 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2351 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2354 if (strequal(devmode->formname, devmode2->formname)) {
2355 torture_warning(tctx, "formname are the same\n");
2356 } else {
2357 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2358 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2361 if (devmode->copies == devmode2->copies) {
2362 torture_warning(tctx, "copies are the same\n");
2363 } else {
2364 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2365 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2368 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2370 devmode2 = info.info2.devmode;
2372 if (strequal(devmode->devicename, devmode2->devicename)) {
2373 torture_warning(tctx, "devicenames are the same\n");
2374 } else {
2375 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2376 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2379 if (strequal(devmode->formname, devmode2->formname)) {
2380 torture_warning(tctx, "formname is the same\n");
2381 } else {
2382 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2383 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2386 if (devmode->copies == devmode2->copies) {
2387 torture_warning(tctx, "copies are the same\n");
2388 } else {
2389 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2390 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2393 test_ClosePrinter(tctx, b, &handle_devmode);
2395 return true;
2399 * wrapper call that saves original devmode, runs tests, and restores devmode
2402 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2403 struct dcerpc_pipe *p,
2404 struct policy_handle *handle,
2405 const char *name,
2406 struct spoolss_DeviceMode *addprinter_devmode)
2408 union spoolss_PrinterInfo info;
2409 struct spoolss_DeviceMode *devmode;
2410 bool ret = true;
2411 struct dcerpc_binding_handle *b = p->binding_handle;
2413 torture_comment(tctx, "Testing Printer Devicemodes\n");
2415 /* save original devmode */
2417 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2418 "failed to get initial global devicemode");
2420 devmode = info.info8.devmode;
2422 if (devmode && devmode->size == 0) {
2423 torture_fail(tctx,
2424 "devmode of zero size!");
2427 if (addprinter_devmode) {
2428 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2429 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2433 /* run tests */
2435 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2437 /* restore original devmode */
2439 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2440 "failed to restore initial global device mode");
2442 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2443 ret ? "succeeded" : "failed");
2446 return ret;
2449 bool test_ClosePrinter(struct torture_context *tctx,
2450 struct dcerpc_binding_handle *b,
2451 struct policy_handle *handle)
2453 NTSTATUS status;
2454 struct spoolss_ClosePrinter r;
2456 r.in.handle = handle;
2457 r.out.handle = handle;
2459 torture_comment(tctx, "Testing ClosePrinter\n");
2461 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2462 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2463 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2465 return true;
2468 static bool test_GetForm_args(struct torture_context *tctx,
2469 struct dcerpc_binding_handle *b,
2470 struct policy_handle *handle,
2471 const char *form_name,
2472 uint32_t level,
2473 union spoolss_FormInfo *info_p)
2475 NTSTATUS status;
2476 struct spoolss_GetForm r;
2477 uint32_t needed;
2479 r.in.handle = handle;
2480 r.in.form_name = form_name;
2481 r.in.level = level;
2482 r.in.buffer = NULL;
2483 r.in.offered = 0;
2484 r.out.needed = &needed;
2486 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2488 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2489 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2491 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2492 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2493 r.in.buffer = &blob;
2494 r.in.offered = needed;
2495 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2496 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2498 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2500 torture_assert(tctx, r.out.info, "No form info returned");
2503 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2505 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2507 if (info_p) {
2508 *info_p = *r.out.info;
2511 return true;
2514 static bool test_GetForm(struct torture_context *tctx,
2515 struct dcerpc_binding_handle *b,
2516 struct policy_handle *handle,
2517 const char *form_name,
2518 uint32_t level)
2520 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2523 static bool test_EnumForms(struct torture_context *tctx,
2524 struct dcerpc_binding_handle *b,
2525 struct policy_handle *handle,
2526 bool print_server,
2527 uint32_t level,
2528 uint32_t *count_p,
2529 union spoolss_FormInfo **info_p)
2531 struct spoolss_EnumForms r;
2532 uint32_t needed;
2533 uint32_t count;
2534 union spoolss_FormInfo *info;
2536 r.in.handle = handle;
2537 r.in.level = level;
2538 r.in.buffer = NULL;
2539 r.in.offered = 0;
2540 r.out.needed = &needed;
2541 r.out.count = &count;
2542 r.out.info = &info;
2544 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2546 torture_assert_ntstatus_ok(tctx,
2547 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2548 "EnumForms failed");
2550 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2551 torture_skip(tctx, "EnumForms level 2 not supported");
2554 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2555 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2558 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2559 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2560 r.in.buffer = &blob;
2561 r.in.offered = needed;
2563 torture_assert_ntstatus_ok(tctx,
2564 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2565 "EnumForms failed");
2567 torture_assert(tctx, info, "No forms returned");
2570 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2572 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2574 if (info_p) {
2575 *info_p = info;
2577 if (count_p) {
2578 *count_p = count;
2581 return true;
2584 static bool test_EnumForms_all(struct torture_context *tctx,
2585 struct dcerpc_binding_handle *b,
2586 struct policy_handle *handle,
2587 bool print_server)
2589 uint32_t levels[] = { 1, 2 };
2590 int i, j;
2592 for (i=0; i<ARRAY_SIZE(levels); i++) {
2594 uint32_t count = 0;
2595 union spoolss_FormInfo *info = NULL;
2597 torture_assert(tctx,
2598 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2599 "failed to enum forms");
2601 for (j = 0; j < count; j++) {
2602 if (!print_server) {
2603 torture_assert(tctx,
2604 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2605 "failed to get form");
2610 return true;
2613 static bool test_EnumForms_find_one(struct torture_context *tctx,
2614 struct dcerpc_binding_handle *b,
2615 struct policy_handle *handle,
2616 bool print_server,
2617 const char *form_name)
2619 union spoolss_FormInfo *info;
2620 uint32_t count;
2621 bool found = false;
2622 int i;
2624 torture_assert(tctx,
2625 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2626 "failed to enumerate forms");
2628 for (i=0; i<count; i++) {
2629 if (strequal(form_name, info[i].info1.form_name)) {
2630 found = true;
2631 break;
2635 return found;
2638 static bool test_DeleteForm(struct torture_context *tctx,
2639 struct dcerpc_binding_handle *b,
2640 struct policy_handle *handle,
2641 const char *form_name,
2642 WERROR expected_result)
2644 struct spoolss_DeleteForm r;
2646 r.in.handle = handle;
2647 r.in.form_name = form_name;
2649 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2651 torture_assert_ntstatus_ok(tctx,
2652 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2653 "DeleteForm failed");
2654 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2655 "DeleteForm gave unexpected result");
2656 if (W_ERROR_IS_OK(r.out.result)) {
2657 torture_assert_ntstatus_ok(tctx,
2658 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2659 "2nd DeleteForm failed");
2660 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2661 "2nd DeleteForm failed");
2664 return true;
2667 static bool test_AddForm(struct torture_context *tctx,
2668 struct dcerpc_binding_handle *b,
2669 struct policy_handle *handle,
2670 uint32_t level,
2671 union spoolss_AddFormInfo *info,
2672 WERROR expected_result)
2674 struct spoolss_AddForm r;
2675 struct spoolss_AddFormInfoCtr info_ctr;
2677 info_ctr.level = level;
2678 info_ctr.info = *info;
2680 if (level != 1) {
2681 torture_skip(tctx, "only level 1 supported");
2684 r.in.handle = handle;
2685 r.in.info_ctr = &info_ctr;
2687 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2688 r.in.info_ctr->info.info1->form_name, level,
2689 r.in.info_ctr->info.info1->flags);
2691 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2692 "AddForm failed");
2693 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2694 "AddForm gave unexpected result");
2696 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2697 "2nd AddForm failed");
2698 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2699 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2700 "2nd AddForm gave unexpected result");
2701 } else {
2702 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2703 "2nd AddForm gave unexpected result");
2706 return true;
2709 static bool test_SetForm(struct torture_context *tctx,
2710 struct dcerpc_binding_handle *b,
2711 struct policy_handle *handle,
2712 const char *form_name,
2713 uint32_t level,
2714 union spoolss_AddFormInfo *info)
2716 struct spoolss_SetForm r;
2717 struct spoolss_AddFormInfoCtr info_ctr;
2719 info_ctr.level = level;
2720 info_ctr.info = *info;
2722 r.in.handle = handle;
2723 r.in.form_name = form_name;
2724 r.in.info_ctr = &info_ctr;
2726 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2727 form_name, level);
2729 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2730 "SetForm failed");
2732 torture_assert_werr_ok(tctx, r.out.result,
2733 "SetForm failed");
2735 return true;
2738 static bool test_GetForm_winreg(struct torture_context *tctx,
2739 struct dcerpc_binding_handle *b,
2740 struct policy_handle *handle,
2741 const char *key_name,
2742 const char *form_name,
2743 enum winreg_Type *w_type,
2744 uint32_t *w_size,
2745 uint32_t *w_length,
2746 uint8_t **w_data);
2748 static bool test_Forms_args(struct torture_context *tctx,
2749 struct dcerpc_binding_handle *b,
2750 struct policy_handle *handle,
2751 bool print_server,
2752 const char *printer_name,
2753 struct dcerpc_binding_handle *winreg_handle,
2754 struct policy_handle *hive_handle,
2755 const char *form_name,
2756 struct spoolss_AddFormInfo1 *info1,
2757 WERROR expected_add_result,
2758 WERROR expected_delete_result)
2760 union spoolss_FormInfo info;
2761 union spoolss_AddFormInfo add_info;
2763 enum winreg_Type w_type;
2764 uint32_t w_size;
2765 uint32_t w_length;
2766 uint8_t *w_data;
2768 add_info.info1 = info1;
2770 torture_assert(tctx,
2771 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2772 "failed to add form");
2774 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2776 struct spoolss_FormInfo1 i1;
2778 torture_assert(tctx,
2779 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2780 "failed to get form via winreg");
2782 i1.size.width = IVAL(w_data, 0);
2783 i1.size.height = IVAL(w_data, 4);
2784 i1.area.left = IVAL(w_data, 8);
2785 i1.area.top = IVAL(w_data, 12);
2786 i1.area.right = IVAL(w_data, 16);
2787 i1.area.bottom = IVAL(w_data, 20);
2788 /* skip index here */
2789 i1.flags = IVAL(w_data, 28);
2791 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2792 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2793 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2794 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2795 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2796 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2797 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2798 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2799 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2800 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2803 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2804 torture_assert(tctx,
2805 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2806 "failed to get added form");
2808 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2809 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2810 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2811 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2812 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2813 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2814 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2816 if (winreg_handle && hive_handle) {
2818 struct spoolss_FormInfo1 i1;
2820 i1.size.width = IVAL(w_data, 0);
2821 i1.size.height = IVAL(w_data, 4);
2822 i1.area.left = IVAL(w_data, 8);
2823 i1.area.top = IVAL(w_data, 12);
2824 i1.area.right = IVAL(w_data, 16);
2825 i1.area.bottom = IVAL(w_data, 20);
2826 /* skip index here */
2827 i1.flags = IVAL(w_data, 28);
2829 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2830 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2831 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2832 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2833 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2834 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2835 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2838 add_info.info1->size.width = 1234;
2840 torture_assert(tctx,
2841 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2842 "failed to set form");
2843 torture_assert(tctx,
2844 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2845 "failed to get setted form");
2847 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2850 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2851 torture_assert(tctx,
2852 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2853 "Newly added form not found in enum call");
2856 torture_assert(tctx,
2857 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2858 "failed to delete form");
2860 return true;
2863 static bool test_Forms(struct torture_context *tctx,
2864 struct dcerpc_binding_handle *b,
2865 struct policy_handle *handle,
2866 bool print_server,
2867 const char *printer_name,
2868 struct dcerpc_binding_handle *winreg_handle,
2869 struct policy_handle *hive_handle)
2871 const struct spoolss_FormSize size = {
2872 .width = 50,
2873 .height = 25
2875 const struct spoolss_FormArea area = {
2876 .left = 5,
2877 .top = 10,
2878 .right = 45,
2879 .bottom = 15
2881 int i;
2883 struct {
2884 struct spoolss_AddFormInfo1 info1;
2885 WERROR expected_add_result;
2886 WERROR expected_delete_result;
2887 } forms[] = {
2889 .info1 = {
2890 .flags = SPOOLSS_FORM_USER,
2891 .form_name = "testform_user",
2892 .size = size,
2893 .area = area,
2895 .expected_add_result = WERR_OK,
2896 .expected_delete_result = WERR_OK
2899 weird, we can add a builtin form but we can never remove it
2900 again - gd
2903 .info1 = {
2904 .flags = SPOOLSS_FORM_BUILTIN,
2905 .form_name = "testform_builtin",
2906 .size = size,
2907 .area = area,
2909 .expected_add_result = WERR_OK,
2910 .expected_delete_result = WERR_INVALID_PARAM,
2914 .info1 = {
2915 .flags = SPOOLSS_FORM_PRINTER,
2916 .form_name = "testform_printer",
2917 .size = size,
2918 .area = area,
2920 .expected_add_result = WERR_OK,
2921 .expected_delete_result = WERR_OK
2924 .info1 = {
2925 .flags = SPOOLSS_FORM_USER,
2926 .form_name = "Letter",
2927 .size = size,
2928 .area = area,
2930 .expected_add_result = WERR_FILE_EXISTS,
2931 .expected_delete_result = WERR_INVALID_PARAM
2934 .info1 = {
2935 .flags = SPOOLSS_FORM_BUILTIN,
2936 .form_name = "Letter",
2937 .size = size,
2938 .area = area,
2940 .expected_add_result = WERR_FILE_EXISTS,
2941 .expected_delete_result = WERR_INVALID_PARAM
2944 .info1 = {
2945 .flags = SPOOLSS_FORM_PRINTER,
2946 .form_name = "Letter",
2947 .size = size,
2948 .area = area,
2950 .expected_add_result = WERR_FILE_EXISTS,
2951 .expected_delete_result = WERR_INVALID_PARAM
2954 .info1 = {
2955 .flags = 12345,
2956 .form_name = "invalid_flags",
2957 .size = size,
2958 .area = area,
2960 .expected_add_result = WERR_INVALID_PARAM,
2961 .expected_delete_result = WERR_INVALID_FORM_NAME
2966 for (i=0; i < ARRAY_SIZE(forms); i++) {
2967 torture_assert(tctx,
2968 test_Forms_args(tctx, b, handle, print_server, printer_name,
2969 winreg_handle, hive_handle,
2970 forms[i].info1.form_name,
2971 &forms[i].info1,
2972 forms[i].expected_add_result,
2973 forms[i].expected_delete_result),
2974 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2977 return true;
2980 static bool test_EnumPorts_old(struct torture_context *tctx,
2981 void *private_data)
2983 struct test_spoolss_context *ctx =
2984 talloc_get_type_abort(private_data, struct test_spoolss_context);
2986 NTSTATUS status;
2987 struct spoolss_EnumPorts r;
2988 uint32_t needed;
2989 uint32_t count;
2990 union spoolss_PortInfo *info;
2991 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2992 struct dcerpc_binding_handle *b = p->binding_handle;
2994 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2995 dcerpc_server_name(p));
2996 r.in.level = 2;
2997 r.in.buffer = NULL;
2998 r.in.offered = 0;
2999 r.out.needed = &needed;
3000 r.out.count = &count;
3001 r.out.info = &info;
3003 torture_comment(tctx, "Testing EnumPorts\n");
3005 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3007 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3009 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3010 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3011 r.in.buffer = &blob;
3012 r.in.offered = needed;
3014 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3015 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3016 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3018 torture_assert(tctx, info, "No ports returned");
3021 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3023 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3025 return true;
3028 static bool test_AddPort(struct torture_context *tctx,
3029 void *private_data)
3031 struct test_spoolss_context *ctx =
3032 talloc_get_type_abort(private_data, struct test_spoolss_context);
3034 NTSTATUS status;
3035 struct spoolss_AddPort r;
3036 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3037 struct dcerpc_binding_handle *b = p->binding_handle;
3039 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3040 dcerpc_server_name(p));
3041 r.in.unknown = 0;
3042 r.in.monitor_name = "foo";
3044 torture_comment(tctx, "Testing AddPort\n");
3046 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3048 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3050 /* win2k3 returns WERR_NOT_SUPPORTED */
3052 #if 0
3054 if (!W_ERROR_IS_OK(r.out.result)) {
3055 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3056 return false;
3059 #endif
3061 return true;
3064 static bool test_GetJob_args(struct torture_context *tctx,
3065 struct dcerpc_binding_handle *b,
3066 struct policy_handle *handle,
3067 uint32_t job_id,
3068 uint32_t level,
3069 union spoolss_JobInfo *info_p)
3071 NTSTATUS status;
3072 struct spoolss_GetJob r;
3073 union spoolss_JobInfo info;
3074 uint32_t needed;
3076 r.in.handle = handle;
3077 r.in.job_id = job_id;
3078 r.in.level = level;
3079 r.in.buffer = NULL;
3080 r.in.offered = 0;
3081 r.out.needed = &needed;
3082 r.out.info = &info;
3084 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3086 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3087 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3088 if (level == 0) {
3089 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3092 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3093 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3094 r.in.buffer = &blob;
3095 r.in.offered = needed;
3097 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3098 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3101 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3102 torture_assert(tctx, r.out.info, "No job info returned");
3104 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3106 if (info_p) {
3107 *info_p = *r.out.info;
3110 return true;
3113 static bool test_GetJob(struct torture_context *tctx,
3114 struct dcerpc_binding_handle *b,
3115 struct policy_handle *handle,
3116 uint32_t job_id)
3118 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3119 uint32_t i;
3121 for (i=0; i < ARRAY_SIZE(levels); i++) {
3122 torture_assert(tctx,
3123 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3124 "GetJob failed");
3127 return true;
3130 static bool test_SetJob(struct torture_context *tctx,
3131 struct dcerpc_binding_handle *b,
3132 struct policy_handle *handle,
3133 uint32_t job_id,
3134 struct spoolss_JobInfoContainer *ctr,
3135 enum spoolss_JobControl command)
3137 NTSTATUS status;
3138 struct spoolss_SetJob r;
3140 r.in.handle = handle;
3141 r.in.job_id = job_id;
3142 r.in.ctr = ctr;
3143 r.in.command = command;
3145 switch (command) {
3146 case SPOOLSS_JOB_CONTROL_PAUSE:
3147 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3148 break;
3149 case SPOOLSS_JOB_CONTROL_RESUME:
3150 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3151 break;
3152 case SPOOLSS_JOB_CONTROL_CANCEL:
3153 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3154 break;
3155 case SPOOLSS_JOB_CONTROL_RESTART:
3156 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3157 break;
3158 case SPOOLSS_JOB_CONTROL_DELETE:
3159 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3160 break;
3161 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3162 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3163 break;
3164 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3165 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3166 break;
3167 case SPOOLSS_JOB_CONTROL_RETAIN:
3168 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3169 break;
3170 case SPOOLSS_JOB_CONTROL_RELEASE:
3171 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3172 break;
3173 default:
3174 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3175 break;
3178 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3179 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3180 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3182 return true;
3185 static bool test_AddJob(struct torture_context *tctx,
3186 struct dcerpc_binding_handle *b,
3187 struct policy_handle *handle)
3189 NTSTATUS status;
3190 struct spoolss_AddJob r;
3191 uint32_t needed;
3193 r.in.level = 0;
3194 r.in.handle = handle;
3195 r.in.offered = 0;
3196 r.out.needed = &needed;
3197 r.in.buffer = r.out.buffer = NULL;
3199 torture_comment(tctx, "Testing AddJob\n");
3201 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3202 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3203 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3205 r.in.level = 1;
3207 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3208 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3209 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3211 return true;
3215 static bool test_EnumJobs_args(struct torture_context *tctx,
3216 struct dcerpc_binding_handle *b,
3217 struct policy_handle *handle,
3218 uint32_t level,
3219 uint32_t *count_p,
3220 union spoolss_JobInfo **info_p)
3222 NTSTATUS status;
3223 struct spoolss_EnumJobs r;
3224 uint32_t needed;
3225 uint32_t count;
3226 union spoolss_JobInfo *info;
3228 r.in.handle = handle;
3229 r.in.firstjob = 0;
3230 r.in.numjobs = 0xffffffff;
3231 r.in.level = level;
3232 r.in.buffer = NULL;
3233 r.in.offered = 0;
3234 r.out.needed = &needed;
3235 r.out.count = &count;
3236 r.out.info = &info;
3238 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3240 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3242 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3244 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3245 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3246 r.in.buffer = &blob;
3247 r.in.offered = needed;
3249 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3251 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3252 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3253 torture_assert(tctx, info, "No jobs returned");
3255 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3257 } else {
3258 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3261 if (count_p) {
3262 *count_p = count;
3264 if (info_p) {
3265 *info_p = info;
3268 return true;
3271 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3272 struct dcerpc_binding_handle *b,
3273 struct policy_handle *handle,
3274 uint32_t job_id)
3276 struct spoolss_RpcEnumJobNamedProperties r;
3277 uint32_t pcProperties = 0;
3278 struct RPC_PrintNamedProperty *ppProperties = NULL;
3280 r.in.hPrinter = handle;
3281 r.in.JobId = job_id;
3282 r.out.pcProperties = &pcProperties;
3283 r.out.ppProperties = &ppProperties;
3285 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3287 torture_assert_ntstatus_ok(tctx,
3288 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3289 "spoolss_RpcEnumJobNamedProperties failed");
3290 torture_assert_werr_ok(tctx, r.out.result,
3291 "spoolss_RpcEnumJobNamedProperties failed");
3293 return true;
3296 static bool test_JobPropertySet(struct torture_context *tctx,
3297 struct dcerpc_binding_handle *b,
3298 struct policy_handle *handle,
3299 uint32_t job_id,
3300 struct RPC_PrintNamedProperty *property)
3302 struct spoolss_RpcSetJobNamedProperty r;
3304 r.in.hPrinter = handle;
3305 r.in.JobId = job_id;
3306 r.in.pProperty = property;
3308 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3309 job_id, property->propertyName,
3310 property->propertyValue.ePropertyType);
3312 torture_assert_ntstatus_ok(tctx,
3313 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3314 "spoolss_RpcSetJobNamedProperty failed");
3315 torture_assert_werr_ok(tctx, r.out.result,
3316 "spoolss_RpcSetJobNamedProperty failed");
3318 return true;
3321 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3322 struct dcerpc_binding_handle *b,
3323 struct policy_handle *handle,
3324 uint32_t job_id,
3325 const char *property_name,
3326 struct RPC_PrintPropertyValue *value)
3328 struct spoolss_RpcGetJobNamedPropertyValue r;
3330 r.in.hPrinter = handle;
3331 r.in.JobId = job_id;
3332 r.in.pszName = property_name;
3333 r.out.pValue = value;
3335 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3336 job_id, property_name);
3338 torture_assert_ntstatus_ok(tctx,
3339 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3340 "spoolss_RpcGetJobNamedPropertyValue failed");
3341 torture_assert_werr_ok(tctx, r.out.result,
3342 "spoolss_RpcGetJobNamedPropertyValue failed");
3344 return true;
3347 static bool test_JobPropertyDelete(struct torture_context *tctx,
3348 struct dcerpc_binding_handle *b,
3349 struct policy_handle *handle,
3350 uint32_t job_id,
3351 const char *property_name)
3353 struct spoolss_RpcDeleteJobNamedProperty r;
3355 r.in.hPrinter = handle;
3356 r.in.JobId = job_id;
3357 r.in.pszName = property_name;
3359 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3360 job_id, property_name);
3362 torture_assert_ntstatus_ok(tctx,
3363 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3364 "spoolss_RpcDeleteJobNamedProperty failed");
3365 torture_assert_werr_ok(tctx, r.out.result,
3366 "spoolss_RpcDeleteJobNamedProperty failed");
3368 return true;
3372 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3373 struct dcerpc_binding_handle *b,
3374 struct policy_handle *handle,
3375 const char *document_name,
3376 uint32_t *job_id)
3378 NTSTATUS status;
3379 struct spoolss_StartDocPrinter s;
3380 struct spoolss_DocumentInfoCtr info_ctr;
3381 struct spoolss_DocumentInfo1 info1;
3382 struct spoolss_StartPagePrinter sp;
3383 struct spoolss_WritePrinter w;
3384 struct spoolss_EndPagePrinter ep;
3385 struct spoolss_EndDocPrinter e;
3386 int i;
3387 uint32_t num_written;
3389 torture_comment(tctx, "Testing StartDocPrinter\n");
3391 s.in.handle = handle;
3392 s.in.info_ctr = &info_ctr;
3393 s.out.job_id = job_id;
3395 info1.document_name = document_name;
3396 info1.output_file = NULL;
3397 info1.datatype = "RAW";
3399 info_ctr.level = 1;
3400 info_ctr.info.info1 = &info1;
3402 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3403 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3404 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3406 for (i=1; i < 4; i++) {
3407 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3409 sp.in.handle = handle;
3411 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3412 torture_assert_ntstatus_ok(tctx, status,
3413 "dcerpc_spoolss_StartPagePrinter failed");
3414 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3416 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3418 w.in.handle = handle;
3419 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3420 w.out.num_written = &num_written;
3422 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3423 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3424 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3426 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3428 ep.in.handle = handle;
3430 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3431 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3432 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3435 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3437 e.in.handle = handle;
3439 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3440 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3441 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3443 return true;
3446 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3447 struct dcerpc_binding_handle *b,
3448 struct policy_handle *handle,
3449 uint32_t num_jobs,
3450 uint32_t *job_ids)
3452 uint32_t count;
3453 union spoolss_JobInfo *info = NULL;
3454 int i;
3456 torture_assert(tctx,
3457 test_AddJob(tctx, b, handle),
3458 "AddJob failed");
3460 torture_assert(tctx,
3461 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3462 "EnumJobs level 1 failed");
3464 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3466 for (i=0; i < num_jobs; i++) {
3467 union spoolss_JobInfo ginfo;
3468 const char *document_name;
3469 const char *new_document_name = "any_other_docname";
3470 struct spoolss_JobInfoContainer ctr;
3471 struct spoolss_SetJobInfo1 info1;
3473 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3475 torture_assert(tctx,
3476 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3477 "failed to call test_GetJob");
3479 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3481 document_name = ginfo.info1.document_name;
3483 info1.job_id = ginfo.info1.job_id;
3484 info1.printer_name = ginfo.info1.printer_name;
3485 info1.server_name = ginfo.info1.server_name;
3486 info1.user_name = ginfo.info1.user_name;
3487 info1.document_name = new_document_name;
3488 info1.data_type = ginfo.info1.data_type;
3489 info1.text_status = ginfo.info1.text_status;
3490 info1.status = ginfo.info1.status;
3491 info1.priority = ginfo.info1.priority;
3492 info1.position = ginfo.info1.position;
3493 info1.total_pages = ginfo.info1.total_pages;
3494 info1.pages_printed = ginfo.info1.pages_printed;
3495 info1.submitted = ginfo.info1.submitted;
3497 ctr.level = 1;
3498 ctr.info.info1 = &info1;
3500 torture_assert(tctx,
3501 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3502 "failed to call test_SetJob level 1");
3504 torture_assert(tctx,
3505 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3506 "failed to call test_GetJob");
3508 if (strequal(ginfo.info1.document_name, document_name)) {
3509 torture_warning(tctx,
3510 "document_name did *NOT* change from '%s' to '%s'\n",
3511 document_name, new_document_name);
3515 for (i=0; i < num_jobs; i++) {
3516 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3517 torture_warning(tctx, "failed to pause printjob\n");
3519 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3520 torture_warning(tctx, "failed to resume printjob\n");
3524 return true;
3527 static bool test_DoPrintTest(struct torture_context *tctx,
3528 struct dcerpc_binding_handle *b,
3529 struct policy_handle *handle)
3531 bool ret = true;
3532 uint32_t num_jobs = 8;
3533 uint32_t *job_ids;
3534 int i;
3536 torture_comment(tctx, "Testing real print operations\n");
3538 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3540 for (i=0; i < num_jobs; i++) {
3541 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3544 for (i=0; i < num_jobs; i++) {
3545 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3548 if (ret == true) {
3549 torture_comment(tctx, "real print operations test succeeded\n\n");
3552 return ret;
3555 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3556 struct dcerpc_binding_handle *b,
3557 struct policy_handle *handle)
3559 bool ret = true;
3560 uint32_t num_jobs = 8;
3561 uint32_t *job_ids;
3562 int i;
3563 torture_comment(tctx, "Testing real print operations (extended)\n");
3565 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3567 for (i=0; i < num_jobs; i++) {
3568 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3571 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3573 for (i=0; i < num_jobs; i++) {
3574 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3577 if (ret == true) {
3578 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3581 return ret;
3584 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3585 struct RPC_PrintPropertyValue *got,
3586 struct RPC_PrintNamedProperty *exp)
3588 torture_assert_int_equal(tctx,
3589 got->ePropertyType,
3590 exp->propertyValue.ePropertyType,
3591 "ePropertyType");
3593 switch (exp->propertyValue.ePropertyType) {
3594 case kRpcPropertyTypeString:
3595 torture_assert_str_equal(tctx,
3596 got->value.propertyString,
3597 exp->propertyValue.value.propertyString,
3598 "propertyString");
3599 break;
3600 case kRpcPropertyTypeInt32:
3601 torture_assert_int_equal(tctx,
3602 got->value.propertyInt32,
3603 exp->propertyValue.value.propertyInt32,
3604 "propertyInt32");
3605 break;
3606 case kRpcPropertyTypeInt64:
3607 torture_assert_u64_equal(tctx,
3608 got->value.propertyInt64,
3609 exp->propertyValue.value.propertyInt64,
3610 "propertyInt64");
3611 break;
3612 case kRpcPropertyTypeByte:
3613 torture_assert_int_equal(tctx,
3614 got->value.propertyByte,
3615 exp->propertyValue.value.propertyByte,
3616 "propertyByte");
3617 break;
3618 case kRpcPropertyTypeBuffer:
3619 torture_assert_int_equal(tctx,
3620 got->value.propertyBlob.cbBuf,
3621 exp->propertyValue.value.propertyBlob.cbBuf,
3622 "propertyBlob.cbBuf");
3623 torture_assert_mem_equal(tctx,
3624 got->value.propertyBlob.pBuf,
3625 exp->propertyValue.value.propertyBlob.pBuf,
3626 exp->propertyValue.value.propertyBlob.cbBuf,
3627 "propertyBlob.pBuf");
3629 break;
3633 return true;
3636 static bool test_JobPrintProperties(struct torture_context *tctx,
3637 struct dcerpc_binding_handle *b,
3638 struct policy_handle *handle,
3639 uint32_t job_id)
3641 struct RPC_PrintNamedProperty in;
3642 struct RPC_PrintPropertyValue out;
3643 int i;
3644 DATA_BLOB blob = data_blob_string_const("blob");
3645 struct {
3646 const char *property_name;
3647 enum RPC_EPrintPropertyType type;
3648 union RPC_PrintPropertyValueUnion value;
3649 WERROR expected_result;
3650 } tests[] = {
3652 .property_name = "torture_property_string",
3653 .type = kRpcPropertyTypeString,
3654 .value.propertyString = "torture_property_value_string",
3656 .property_name = "torture_property_int32",
3657 .type = kRpcPropertyTypeInt32,
3658 .value.propertyInt32 = 42,
3660 .property_name = "torture_property_int64",
3661 .type = kRpcPropertyTypeInt64,
3662 .value.propertyInt64 = 0xaffe,
3664 .property_name = "torture_property_byte",
3665 .type = kRpcPropertyTypeByte,
3666 .value.propertyByte = 0xab,
3668 .property_name = "torture_property_buffer",
3669 .type = kRpcPropertyTypeBuffer,
3670 .value.propertyBlob.cbBuf = blob.length,
3671 .value.propertyBlob.pBuf = blob.data,
3675 torture_assert(tctx,
3676 test_JobPropertiesEnum(tctx, b, handle, job_id),
3677 "failed to enum properties");
3679 for (i=0; i <ARRAY_SIZE(tests); i++) {
3681 in.propertyName = tests[i].property_name;
3682 in.propertyValue.ePropertyType = tests[i].type;
3683 in.propertyValue.value = tests[i].value;
3685 torture_assert(tctx,
3686 test_JobPropertySet(tctx, b, handle, job_id, &in),
3687 "failed to set property");
3689 torture_assert(tctx,
3690 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3691 "failed to get property");
3693 torture_assert(tctx,
3694 test_JobPrintProperties_equal(tctx, &out, &in),
3695 "property unequal");
3697 torture_assert(tctx,
3698 test_JobPropertiesEnum(tctx, b, handle, job_id),
3699 "failed to enum properties");
3701 torture_assert(tctx,
3702 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3703 "failed to delete job property");
3706 torture_assert(tctx,
3707 test_JobPropertiesEnum(tctx, b, handle, job_id),
3708 "failed to enum properties");
3710 return true;
3713 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3714 struct dcerpc_binding_handle *b,
3715 struct policy_handle *handle)
3717 uint32_t num_jobs = 8;
3718 uint32_t *job_ids;
3719 int i;
3720 torture_comment(tctx, "Testing real print operations (properties)\n");
3722 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3724 for (i=0; i < num_jobs; i++) {
3725 torture_assert(tctx,
3726 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3727 "failed to create print job");
3730 for (i=0; i < num_jobs; i++) {
3731 torture_assert(tctx,
3732 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3733 "failed to test job properties");
3737 for (i=0; i < num_jobs; i++) {
3738 torture_assert(tctx,
3739 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3740 "failed to delete printjob");
3743 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3745 return true;
3748 static bool test_PausePrinter(struct torture_context *tctx,
3749 struct dcerpc_binding_handle *b,
3750 struct policy_handle *handle)
3752 NTSTATUS status;
3753 struct spoolss_SetPrinter r;
3754 struct spoolss_SetPrinterInfoCtr info_ctr;
3755 struct spoolss_DevmodeContainer devmode_ctr;
3756 struct sec_desc_buf secdesc_ctr;
3758 info_ctr.level = 0;
3759 info_ctr.info.info0 = NULL;
3761 ZERO_STRUCT(devmode_ctr);
3762 ZERO_STRUCT(secdesc_ctr);
3764 r.in.handle = handle;
3765 r.in.info_ctr = &info_ctr;
3766 r.in.devmode_ctr = &devmode_ctr;
3767 r.in.secdesc_ctr = &secdesc_ctr;
3768 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3770 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3772 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3774 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3776 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3778 return true;
3781 static bool test_ResumePrinter(struct torture_context *tctx,
3782 struct dcerpc_binding_handle *b,
3783 struct policy_handle *handle)
3785 NTSTATUS status;
3786 struct spoolss_SetPrinter r;
3787 struct spoolss_SetPrinterInfoCtr info_ctr;
3788 struct spoolss_DevmodeContainer devmode_ctr;
3789 struct sec_desc_buf secdesc_ctr;
3791 info_ctr.level = 0;
3792 info_ctr.info.info0 = NULL;
3794 ZERO_STRUCT(devmode_ctr);
3795 ZERO_STRUCT(secdesc_ctr);
3797 r.in.handle = handle;
3798 r.in.info_ctr = &info_ctr;
3799 r.in.devmode_ctr = &devmode_ctr;
3800 r.in.secdesc_ctr = &secdesc_ctr;
3801 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3803 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3805 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3807 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3809 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3811 return true;
3814 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3815 struct dcerpc_binding_handle *b,
3816 struct policy_handle *handle,
3817 const char *value_name,
3818 enum winreg_Type *expected_type,
3819 enum winreg_Type *type_p,
3820 uint8_t **data_p,
3821 uint32_t *needed_p)
3823 NTSTATUS status;
3824 struct spoolss_GetPrinterData r;
3825 uint32_t needed;
3826 enum winreg_Type type;
3827 union spoolss_PrinterData data;
3829 r.in.handle = handle;
3830 r.in.value_name = value_name;
3831 r.in.offered = 0;
3832 r.out.needed = &needed;
3833 r.out.type = &type;
3834 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3836 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3838 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3839 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3841 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3842 if (expected_type) {
3843 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3845 r.in.offered = needed;
3846 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3847 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3848 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3851 torture_assert_werr_ok(tctx, r.out.result,
3852 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3854 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3856 if (type_p) {
3857 *type_p = type;
3860 if (data_p) {
3861 *data_p = r.out.data;
3864 if (needed_p) {
3865 *needed_p = needed;
3868 return true;
3871 static bool test_GetPrinterData(struct torture_context *tctx,
3872 struct dcerpc_binding_handle *b,
3873 struct policy_handle *handle,
3874 const char *value_name,
3875 enum winreg_Type *type_p,
3876 uint8_t **data_p,
3877 uint32_t *needed_p)
3879 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3880 NULL, type_p, data_p, needed_p);
3883 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3884 struct dcerpc_pipe *p,
3885 struct policy_handle *handle,
3886 const char *key_name,
3887 const char *value_name,
3888 enum winreg_Type *expected_type,
3889 enum winreg_Type *type_p,
3890 uint8_t **data_p,
3891 uint32_t *needed_p)
3893 NTSTATUS status;
3894 struct spoolss_GetPrinterDataEx r;
3895 enum winreg_Type type;
3896 uint32_t needed;
3897 union spoolss_PrinterData data;
3898 struct dcerpc_binding_handle *b = p->binding_handle;
3900 r.in.handle = handle;
3901 r.in.key_name = key_name;
3902 r.in.value_name = value_name;
3903 r.in.offered = 0;
3904 r.out.type = &type;
3905 r.out.needed = &needed;
3906 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3908 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3909 r.in.key_name, r.in.value_name);
3911 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3914 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3916 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3919 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3920 if (expected_type) {
3921 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3923 r.in.offered = needed;
3924 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3925 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3926 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3929 torture_assert_werr_ok(tctx, r.out.result,
3930 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3932 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3934 if (type_p) {
3935 *type_p = type;
3938 if (data_p) {
3939 *data_p = r.out.data;
3942 if (needed_p) {
3943 *needed_p = needed;
3946 return true;
3949 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3950 struct dcerpc_pipe *p,
3951 struct policy_handle *handle,
3952 const char *key_name,
3953 const char *value_name,
3954 enum winreg_Type *type_p,
3955 uint8_t **data_p,
3956 uint32_t *needed_p)
3958 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3959 NULL, type_p, data_p, needed_p);
3962 static bool test_get_environment(struct torture_context *tctx,
3963 struct dcerpc_binding_handle *b,
3964 struct policy_handle *handle,
3965 const char **architecture)
3967 DATA_BLOB blob;
3968 enum winreg_Type type;
3969 uint8_t *data;
3970 uint32_t needed;
3972 torture_assert(tctx,
3973 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3974 "failed to get Architecture");
3976 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3978 blob = data_blob_const(data, needed);
3979 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3981 return true;
3984 static bool test_GetPrinterData_list(struct torture_context *tctx,
3985 void *private_data)
3987 struct test_spoolss_context *ctx =
3988 talloc_get_type_abort(private_data, struct test_spoolss_context);
3989 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3990 struct dcerpc_binding_handle *b = p->binding_handle;
3991 const char *list[] = {
3992 "W3SvcInstalled",
3993 "BeepEnabled",
3994 "EventLog",
3995 /* "NetPopup", not on w2k8 */
3996 /* "NetPopupToComputer", not on w2k8 */
3997 "MajorVersion",
3998 "MinorVersion",
3999 "DefaultSpoolDirectory",
4000 "Architecture",
4001 "DsPresent",
4002 "OSVersion",
4003 /* "OSVersionEx", not on s3 */
4004 "DNSMachineName"
4006 int i;
4008 for (i=0; i < ARRAY_SIZE(list); i++) {
4009 enum winreg_Type type, type_ex;
4010 uint8_t *data, *data_ex;
4011 uint32_t needed, needed_ex;
4013 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4014 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4015 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4016 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4017 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4018 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4019 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4022 return true;
4025 static bool test_EnumPrinterData(struct torture_context *tctx,
4026 struct dcerpc_pipe *p,
4027 struct policy_handle *handle,
4028 uint32_t enum_index,
4029 uint32_t value_offered,
4030 uint32_t data_offered,
4031 enum winreg_Type *type_p,
4032 uint32_t *value_needed_p,
4033 uint32_t *data_needed_p,
4034 const char **value_name_p,
4035 uint8_t **data_p,
4036 WERROR *result_p)
4038 struct spoolss_EnumPrinterData r;
4039 uint32_t data_needed;
4040 uint32_t value_needed;
4041 enum winreg_Type type;
4042 struct dcerpc_binding_handle *b = p->binding_handle;
4044 r.in.handle = handle;
4045 r.in.enum_index = enum_index;
4046 r.in.value_offered = value_offered;
4047 r.in.data_offered = data_offered;
4048 r.out.data_needed = &data_needed;
4049 r.out.value_needed = &value_needed;
4050 r.out.type = &type;
4051 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4052 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4054 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4056 torture_assert_ntstatus_ok(tctx,
4057 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4058 "EnumPrinterData failed");
4060 if (type_p) {
4061 *type_p = type;
4063 if (value_needed_p) {
4064 *value_needed_p = value_needed;
4066 if (data_needed_p) {
4067 *data_needed_p = data_needed;
4069 if (value_name_p) {
4070 *value_name_p = r.out.value_name;
4072 if (data_p) {
4073 *data_p = r.out.data;
4075 if (result_p) {
4076 *result_p = r.out.result;
4079 return true;
4083 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4084 struct dcerpc_pipe *p,
4085 struct policy_handle *handle)
4087 uint32_t enum_index = 0;
4088 enum winreg_Type type;
4089 uint32_t value_needed;
4090 uint32_t data_needed;
4091 uint8_t *data;
4092 const char *value_name;
4093 WERROR result;
4095 torture_comment(tctx, "Testing EnumPrinterData\n");
4097 do {
4098 torture_assert(tctx,
4099 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4100 &type, &value_needed, &data_needed,
4101 &value_name, &data, &result),
4102 "EnumPrinterData failed");
4104 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4105 break;
4108 torture_assert(tctx,
4109 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4110 &type, &value_needed, &data_needed,
4111 &value_name, &data, &result),
4112 "EnumPrinterData failed");
4114 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4115 break;
4118 enum_index++;
4120 } while (W_ERROR_IS_OK(result));
4122 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4124 return true;
4127 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4128 struct dcerpc_binding_handle *b,
4129 struct policy_handle *handle,
4130 const char *key_name,
4131 uint32_t *count_p,
4132 struct spoolss_PrinterEnumValues **info_p)
4134 struct spoolss_EnumPrinterDataEx r;
4135 struct spoolss_PrinterEnumValues *info;
4136 uint32_t needed;
4137 uint32_t count;
4139 r.in.handle = handle;
4140 r.in.key_name = key_name;
4141 r.in.offered = 0;
4142 r.out.needed = &needed;
4143 r.out.count = &count;
4144 r.out.info = &info;
4146 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4148 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4149 "EnumPrinterDataEx failed");
4150 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4151 r.in.offered = needed;
4152 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4153 "EnumPrinterDataEx failed");
4156 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4158 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4160 if (count_p) {
4161 *count_p = count;
4163 if (info_p) {
4164 *info_p = info;
4167 return true;
4170 static bool test_SetPrinterData(struct torture_context *tctx,
4171 struct dcerpc_binding_handle *b,
4172 struct policy_handle *handle,
4173 const char *value_name,
4174 enum winreg_Type type,
4175 uint8_t *data,
4176 uint32_t offered);
4177 static bool test_DeletePrinterData(struct torture_context *tctx,
4178 struct dcerpc_binding_handle *b,
4179 struct policy_handle *handle,
4180 const char *value_name);
4182 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4183 struct dcerpc_pipe *p,
4184 struct policy_handle *handle)
4186 uint32_t count;
4187 struct spoolss_PrinterEnumValues *info;
4188 int i;
4189 uint32_t value_needed, data_needed;
4190 uint32_t value_offered, data_offered;
4191 WERROR result;
4192 struct dcerpc_binding_handle *b = p->binding_handle;
4194 enum winreg_Type type;
4195 DATA_BLOB blob;
4197 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4199 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4200 type = REG_SZ;
4202 torture_assert(tctx,
4203 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4204 "SetPrinterData failed");
4206 blob = data_blob_string_const("torture_data2");
4208 torture_assert(tctx,
4209 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4210 "SetPrinterData failed");
4212 blob = data_blob_talloc(tctx, NULL, 4);
4213 SIVAL(blob.data, 0, 0x11223344);
4215 torture_assert(tctx,
4216 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4217 "SetPrinterData failed");
4219 torture_assert(tctx,
4220 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4221 "failed to call EnumPrinterDataEx");
4223 /* get the max sizes for value and data */
4225 torture_assert(tctx,
4226 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4227 NULL, &value_needed, &data_needed,
4228 NULL, NULL, &result),
4229 "EnumPrinterData failed");
4230 torture_assert_werr_ok(tctx, result, "unexpected result");
4232 /* check if the reply from the EnumPrinterData really matches max values */
4234 for (i=0; i < count; i++) {
4235 if (info[i].value_name_len > value_needed) {
4236 torture_fail(tctx,
4237 talloc_asprintf(tctx,
4238 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4239 info[i].value_name_len, value_needed));
4241 if (info[i].data_length > data_needed) {
4242 torture_fail(tctx,
4243 talloc_asprintf(tctx,
4244 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4245 info[i].data_length, data_needed));
4249 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4250 * sort or not sort the replies by value name, we should be able to do
4251 * the following entry comparison */
4253 data_offered = data_needed;
4254 value_offered = value_needed;
4256 for (i=0; i < count; i++) {
4258 const char *value_name;
4259 uint8_t *data;
4261 torture_assert(tctx,
4262 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4263 &type, &value_needed, &data_needed,
4264 &value_name, &data, &result),
4265 "EnumPrinterData failed");
4267 if (i -1 == count) {
4268 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4269 "unexpected result");
4270 break;
4271 } else {
4272 torture_assert_werr_ok(tctx, result, "unexpected result");
4275 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4276 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4277 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4278 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4279 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4282 torture_assert(tctx,
4283 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4284 "DeletePrinterData failed");
4285 torture_assert(tctx,
4286 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4287 "DeletePrinterData failed");
4288 torture_assert(tctx,
4289 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4290 "DeletePrinterData failed");
4292 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4294 return true;
4297 static bool test_DeletePrinterData(struct torture_context *tctx,
4298 struct dcerpc_binding_handle *b,
4299 struct policy_handle *handle,
4300 const char *value_name)
4302 NTSTATUS status;
4303 struct spoolss_DeletePrinterData r;
4305 r.in.handle = handle;
4306 r.in.value_name = value_name;
4308 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4309 r.in.value_name);
4311 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4313 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4314 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4316 return true;
4319 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4320 struct dcerpc_binding_handle *b,
4321 struct policy_handle *handle,
4322 const char *key_name,
4323 const char *value_name)
4325 struct spoolss_DeletePrinterDataEx r;
4327 r.in.handle = handle;
4328 r.in.key_name = key_name;
4329 r.in.value_name = value_name;
4331 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4332 r.in.key_name, r.in.value_name);
4334 torture_assert_ntstatus_ok(tctx,
4335 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4336 "DeletePrinterDataEx failed");
4337 torture_assert_werr_ok(tctx, r.out.result,
4338 "DeletePrinterDataEx failed");
4340 return true;
4343 static bool test_DeletePrinterKey(struct torture_context *tctx,
4344 struct dcerpc_binding_handle *b,
4345 struct policy_handle *handle,
4346 const char *key_name)
4348 struct spoolss_DeletePrinterKey r;
4350 r.in.handle = handle;
4351 r.in.key_name = key_name;
4353 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4355 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4356 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4357 return true;
4360 torture_assert_ntstatus_ok(tctx,
4361 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4362 "DeletePrinterKey failed");
4363 torture_assert_werr_ok(tctx, r.out.result,
4364 "DeletePrinterKey failed");
4366 return true;
4369 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4370 struct dcerpc_binding_handle *b,
4371 struct policy_handle *handle)
4373 struct winreg_OpenHKLM r;
4375 r.in.system_name = NULL;
4376 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4377 r.out.handle = handle;
4379 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4381 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4382 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4384 return true;
4387 static void init_winreg_String(struct winreg_String *name, const char *s)
4389 name->name = s;
4390 if (s) {
4391 name->name_len = 2 * (strlen_m(s) + 1);
4392 name->name_size = name->name_len;
4393 } else {
4394 name->name_len = 0;
4395 name->name_size = 0;
4399 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4400 struct dcerpc_binding_handle *b,
4401 struct policy_handle *hive_handle,
4402 const char *keyname,
4403 uint32_t options,
4404 struct policy_handle *key_handle)
4406 struct winreg_OpenKey r;
4408 r.in.parent_handle = hive_handle;
4409 init_winreg_String(&r.in.keyname, keyname);
4410 r.in.options = options;
4411 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4412 r.out.handle = key_handle;
4414 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4416 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4417 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4419 return true;
4422 static bool test_winreg_OpenKey(struct torture_context *tctx,
4423 struct dcerpc_binding_handle *b,
4424 struct policy_handle *hive_handle,
4425 const char *keyname,
4426 struct policy_handle *key_handle)
4428 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4429 REG_OPTION_NON_VOLATILE, key_handle);
4432 static bool test_winreg_CloseKey(struct torture_context *tctx,
4433 struct dcerpc_binding_handle *b,
4434 struct policy_handle *handle)
4436 struct winreg_CloseKey r;
4438 r.in.handle = handle;
4439 r.out.handle = handle;
4441 torture_comment(tctx, "Testing winreg_CloseKey\n");
4443 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4444 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4446 return true;
4449 bool test_winreg_QueryValue(struct torture_context *tctx,
4450 struct dcerpc_binding_handle *b,
4451 struct policy_handle *handle,
4452 const char *value_name,
4453 enum winreg_Type *type_p,
4454 uint32_t *data_size_p,
4455 uint32_t *data_length_p,
4456 uint8_t **data_p)
4458 struct winreg_QueryValue r;
4459 enum winreg_Type type = REG_NONE;
4460 uint32_t data_size = 0;
4461 uint32_t data_length = 0;
4462 struct winreg_String valuename;
4463 uint8_t *data = NULL;
4465 init_winreg_String(&valuename, value_name);
4467 data = talloc_zero_array(tctx, uint8_t, 0);
4469 r.in.handle = handle;
4470 r.in.value_name = &valuename;
4471 r.in.type = &type;
4472 r.in.data_size = &data_size;
4473 r.in.data_length = &data_length;
4474 r.in.data = data;
4475 r.out.type = &type;
4476 r.out.data = data;
4477 r.out.data_size = &data_size;
4478 r.out.data_length = &data_length;
4480 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4482 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4483 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4484 *r.in.data_size = *r.out.data_size;
4485 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4486 r.in.data = data;
4487 r.out.data = data;
4488 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4490 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4492 if (type_p) {
4493 *type_p = *r.out.type;
4495 if (data_size_p) {
4496 *data_size_p = *r.out.data_size;
4498 if (data_length_p) {
4499 *data_length_p = *r.out.data_length;
4501 if (data_p) {
4502 *data_p = r.out.data;
4505 return true;
4508 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4509 struct dcerpc_binding_handle *b,
4510 struct policy_handle *handle,
4511 const char *printer_name,
4512 const char *key_name,
4513 const char *value_name,
4514 enum winreg_Type *w_type,
4515 uint32_t *w_size,
4516 uint32_t *w_length,
4517 uint8_t **w_data)
4519 const char *printer_key;
4520 struct policy_handle key_handle;
4522 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4523 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4525 torture_assert(tctx,
4526 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4528 torture_assert(tctx,
4529 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4531 torture_assert(tctx,
4532 test_winreg_CloseKey(tctx, b, &key_handle), "");
4534 return true;
4537 static bool test_GetForm_winreg(struct torture_context *tctx,
4538 struct dcerpc_binding_handle *b,
4539 struct policy_handle *handle,
4540 const char *key_name,
4541 const char *form_name,
4542 enum winreg_Type *w_type,
4543 uint32_t *w_size,
4544 uint32_t *w_length,
4545 uint8_t **w_data)
4547 struct policy_handle key_handle;
4549 torture_assert(tctx,
4550 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4552 torture_assert(tctx,
4553 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4555 torture_assert(tctx,
4556 test_winreg_CloseKey(tctx, b, &key_handle), "");
4558 return true;
4561 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4562 struct dcerpc_binding_handle *b,
4563 struct policy_handle *handle,
4564 const char *symlink_keyname,
4565 const char *symlink_destination)
4567 /* check if the first key is a symlink to the second key */
4569 enum winreg_Type w_type;
4570 uint32_t w_size;
4571 uint32_t w_length;
4572 uint8_t *w_data;
4573 struct policy_handle key_handle;
4574 DATA_BLOB blob;
4575 const char *str;
4577 if (torture_setting_bool(tctx, "samba3", false)) {
4578 torture_skip(tctx, "skip winreg symlink test against samba");
4581 torture_assert(tctx,
4582 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4583 "failed to open key link");
4585 torture_assert(tctx,
4586 test_winreg_QueryValue(tctx, b, &key_handle,
4587 "SymbolicLinkValue",
4588 &w_type, &w_size, &w_length, &w_data),
4589 "failed to query for 'SymbolicLinkValue' attribute");
4591 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4593 blob = data_blob(w_data, w_size);
4594 str = reg_val_data_string(tctx, REG_SZ, blob);
4596 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4598 torture_assert(tctx,
4599 test_winreg_CloseKey(tctx, b, &key_handle),
4600 "failed to close key link");
4602 return true;
4605 static const char *strip_unc(const char *unc)
4607 char *name;
4609 if (!unc) {
4610 return NULL;
4613 if (unc[0] == '\\' && unc[1] == '\\') {
4614 unc +=2;
4617 name = strchr(unc, '\\');
4618 if (name) {
4619 return name+1;
4622 return unc;
4625 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4626 struct dcerpc_binding_handle *b,
4627 struct policy_handle *handle,
4628 const char *printer_name,
4629 struct dcerpc_binding_handle *winreg_handle,
4630 struct policy_handle *hive_handle)
4632 union spoolss_PrinterInfo info;
4633 const char *keys[] = {
4634 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4635 TOP_LEVEL_PRINT_PRINTERS_KEY
4637 int i;
4638 const char *printername, *sharename;
4640 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4642 torture_assert(tctx,
4643 test_GetPrinter_level(tctx, b, handle, 2, &info),
4644 "failed to get printer info level 2");
4646 printername = strip_unc(info.info2.printername);
4647 sharename = strip_unc(info.info2.sharename);
4649 #define test_sz(wname, iname) \
4650 do {\
4651 DATA_BLOB blob;\
4652 const char *str;\
4653 enum winreg_Type w_type;\
4654 uint32_t w_size;\
4655 uint32_t w_length;\
4656 uint8_t *w_data;\
4657 torture_assert(tctx,\
4658 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4659 &w_type, &w_size, &w_length, &w_data),\
4660 "failed to query winreg");\
4661 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4662 blob = data_blob(w_data, w_size);\
4663 str = reg_val_data_string(tctx, REG_SZ, blob);\
4664 if (w_size == 2 && iname == NULL) {\
4665 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4666 } else {\
4667 torture_assert_str_equal(tctx, str, iname,\
4668 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4670 } while(0);
4672 #define test_dword(wname, iname) \
4673 do {\
4674 uint32_t value;\
4675 enum winreg_Type w_type;\
4676 uint32_t w_size;\
4677 uint32_t w_length;\
4678 uint8_t *w_data;\
4679 torture_assert(tctx,\
4680 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4681 &w_type, &w_size, &w_length, &w_data),\
4682 "failed to query winreg");\
4683 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4684 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4685 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4686 value = IVAL(w_data, 0);\
4687 torture_assert_int_equal(tctx, value, iname,\
4688 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4689 } while(0);
4691 #define test_binary(wname, iname) \
4692 do {\
4693 enum winreg_Type w_type;\
4694 uint32_t w_size;\
4695 uint32_t w_length;\
4696 uint8_t *w_data;\
4697 torture_assert(tctx,\
4698 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4699 &w_type, &w_size, &w_length, &w_data),\
4700 "failed to query winreg");\
4701 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4702 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4703 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4704 "binary unequal");\
4705 } while(0);
4708 #define test_dm(wname, iname) \
4709 do {\
4710 DATA_BLOB blob;\
4711 struct spoolss_DeviceMode dm;\
4712 enum ndr_err_code ndr_err;\
4713 enum winreg_Type w_type;\
4714 uint32_t w_size;\
4715 uint32_t w_length;\
4716 uint8_t *w_data;\
4717 torture_assert(tctx,\
4718 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4719 &w_type, &w_size, &w_length, &w_data),\
4720 "failed to query winreg");\
4721 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4722 blob = data_blob(w_data, w_size);\
4723 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4724 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4725 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4726 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4727 "dm unequal");\
4728 } while(0);
4730 #define test_sd(wname, iname) \
4731 do {\
4732 DATA_BLOB blob;\
4733 struct security_descriptor sd;\
4734 enum ndr_err_code ndr_err;\
4735 enum winreg_Type w_type;\
4736 uint32_t w_size;\
4737 uint32_t w_length;\
4738 uint8_t *w_data;\
4739 torture_assert(tctx,\
4740 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4741 &w_type, &w_size, &w_length, &w_data),\
4742 "failed to query winreg");\
4743 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4744 blob = data_blob(w_data, w_size);\
4745 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4746 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4747 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4748 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4749 "sd unequal");\
4750 } while(0);
4752 #define test_multi_sz(wname, iname) \
4753 do {\
4754 DATA_BLOB blob;\
4755 const char **array;\
4756 enum winreg_Type w_type;\
4757 uint32_t w_size;\
4758 uint32_t w_length;\
4759 uint8_t *w_data;\
4760 int i;\
4761 torture_assert(tctx,\
4762 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4763 &w_type, &w_size, &w_length, &w_data),\
4764 "failed to query winreg");\
4765 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4766 blob = data_blob(w_data, w_size);\
4767 torture_assert(tctx, \
4768 pull_reg_multi_sz(tctx, &blob, &array),\
4769 "failed to pull multi sz");\
4770 for (i=0; array[i] != NULL; i++) {\
4771 torture_assert_str_equal(tctx, array[i], iname[i],\
4772 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4774 } while(0);
4776 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4777 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4778 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4780 torture_warning(tctx, "failed to check for winreg symlink");
4783 for (i=0; i < ARRAY_SIZE(keys); i++) {
4785 const char *printer_key;
4786 struct policy_handle key_handle;
4788 printer_key = talloc_asprintf(tctx, "%s\\%s",
4789 keys[i], printer_name);
4791 torture_assert(tctx,
4792 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4794 test_sz("Name", printername);
4795 test_sz("Share Name", sharename);
4796 test_sz("Port", info.info2.portname);
4797 test_sz("Printer Driver", info.info2.drivername);
4798 test_sz("Description", info.info2.comment);
4799 test_sz("Location", info.info2.location);
4800 test_sz("Separator File", info.info2.sepfile);
4801 test_sz("Print Processor", info.info2.printprocessor);
4802 test_sz("Datatype", info.info2.datatype);
4803 test_sz("Parameters", info.info2.parameters);
4804 /* winreg: 0, spoolss not */
4805 /* test_dword("Attributes", info.info2.attributes); */
4806 test_dword("Priority", info.info2.priority);
4807 test_dword("Default Priority", info.info2.defaultpriority);
4808 /* winreg: 60, spoolss: 0 */
4809 /* test_dword("StartTime", info.info2.starttime); */
4810 /* test_dword("UntilTime", info.info2.untiltime); */
4811 /* winreg != spoolss */
4812 /* test_dword("Status", info.info2.status); */
4813 test_dm("Default DevMode", info.info2.devmode);
4814 test_sd("Security", info.info2.secdesc);
4816 torture_assert(tctx,
4817 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4820 #undef test_dm
4821 #undef test_sd
4823 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4825 return true;
4828 static bool test_PrintProcessors(struct torture_context *tctx,
4829 struct dcerpc_binding_handle *b,
4830 const char *environment,
4831 struct dcerpc_binding_handle *winreg_handle,
4832 struct policy_handle *hive_handle)
4834 union spoolss_PrintProcessorInfo *info;
4835 uint32_t count;
4836 int i;
4838 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4840 torture_assert(tctx,
4841 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4842 "failed to enum print processors level 1");
4844 for (i=0; i < count; i++) {
4846 const char *processor_key;
4847 struct policy_handle key_handle;
4849 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4850 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4851 environment,
4852 info[i].info1.print_processor_name);
4854 torture_assert(tctx,
4855 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4857 /* nothing to check in there so far */
4859 torture_assert(tctx,
4860 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4863 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4865 return true;
4868 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4869 struct dcerpc_binding_handle *b,
4870 struct policy_handle *handle,
4871 const char *driver_name,
4872 const char *architecture,
4873 uint32_t level,
4874 uint32_t client_major_version,
4875 uint32_t client_minor_version,
4876 union spoolss_DriverInfo *info_p,
4877 WERROR *result);
4879 static const char *strip_path(const char *path)
4881 char *p;
4883 if (path == NULL) {
4884 return NULL;
4887 p = strrchr(path, '\\');
4888 if (p) {
4889 return p+1;
4892 return path;
4895 static const char **strip_paths(const char **path_array)
4897 int i;
4899 if (path_array == NULL) {
4900 return NULL;
4903 for (i=0; path_array[i] != NULL; i++) {
4904 path_array[i] = strip_path(path_array[i]);
4907 return path_array;
4910 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4912 time_t t;
4913 struct tm *tm;
4915 if (nt == 0) {
4916 return talloc_strdup(mem_ctx, "01/01/1601");
4919 t = nt_time_to_unix(nt);
4920 tm = localtime(&t);
4922 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4923 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4926 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4928 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4929 (unsigned)((v >> 48) & 0xFFFF),
4930 (unsigned)((v >> 32) & 0xFFFF),
4931 (unsigned)((v >> 16) & 0xFFFF),
4932 (unsigned)(v & 0xFFFF));
4935 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4936 struct dcerpc_binding_handle *b,
4937 struct policy_handle *handle,
4938 const char *printer_name,
4939 const char *driver_name,
4940 const char *environment,
4941 enum spoolss_DriverOSVersion version,
4942 struct dcerpc_binding_handle *winreg_handle,
4943 struct policy_handle *hive_handle,
4944 const char *server_name_slash)
4946 WERROR result;
4947 union spoolss_DriverInfo info;
4948 const char *driver_key;
4949 struct policy_handle key_handle;
4951 const char *driver_path;
4952 const char *data_file;
4953 const char *config_file;
4954 const char *help_file;
4955 const char **dependent_files;
4957 const char *driver_date;
4958 const char *inbox_driver_date;
4960 const char *driver_version;
4961 const char *inbox_driver_version;
4963 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4965 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4966 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4967 environment,
4968 version,
4969 driver_name);
4971 torture_assert(tctx,
4972 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4973 "failed to open driver key");
4975 if (torture_setting_bool(tctx, "samba3", false) ||
4976 torture_setting_bool(tctx, "w2k3", false)) {
4977 goto try_level6;
4980 if (handle) {
4981 torture_assert(tctx,
4982 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4983 "failed to get driver info level 8");
4984 } else {
4985 torture_assert(tctx,
4986 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4987 "failed to get driver info level 8");
4990 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4991 goto try_level6;
4994 driver_path = strip_path(info.info8.driver_path);
4995 data_file = strip_path(info.info8.data_file);
4996 config_file = strip_path(info.info8.config_file);
4997 help_file = strip_path(info.info8.help_file);
4998 dependent_files = strip_paths(info.info8.dependent_files);
5000 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5001 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5003 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5004 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5006 test_sz("Configuration File", config_file);
5007 test_sz("Data File", data_file);
5008 test_sz("Datatype", info.info8.default_datatype);
5009 test_sz("Driver", driver_path);
5010 test_sz("DriverDate", driver_date);
5011 test_sz("DriverVersion", driver_version);
5012 test_sz("HardwareID", info.info8.hardware_id);
5013 test_sz("Help File", help_file);
5014 test_sz("InfPath", info.info8.inf_path);
5015 test_sz("Manufacturer", info.info8.manufacturer_name);
5016 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5017 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5018 test_sz("Monitor", info.info8.monitor_name);
5019 test_sz("OEM URL", info.info8.manufacturer_url);
5020 test_sz("Print Processor", info.info8.print_processor);
5021 test_sz("Provider", info.info8.provider);
5022 test_sz("VendorSetup", info.info8.vendor_setup);
5023 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5024 test_multi_sz("Dependent Files", dependent_files);
5025 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5026 test_multi_sz("Previous Names", info.info8.previous_names);
5027 /* test_dword("Attributes", ?); */
5028 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5029 test_dword("Version", info.info8.version);
5030 /* test_dword("TempDir", ?); */
5032 try_level6:
5034 if (handle) {
5035 torture_assert(tctx,
5036 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5037 "failed to get driver info level 6");
5038 } else {
5039 torture_assert(tctx,
5040 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5041 "failed to get driver info level 6");
5044 driver_path = strip_path(info.info6.driver_path);
5045 data_file = strip_path(info.info6.data_file);
5046 config_file = strip_path(info.info6.config_file);
5047 help_file = strip_path(info.info6.help_file);
5048 dependent_files = strip_paths(info.info6.dependent_files);
5050 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5052 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5054 test_sz("Configuration File", config_file);
5055 test_sz("Data File", data_file);
5056 test_sz("Datatype", info.info6.default_datatype);
5057 test_sz("Driver", driver_path);
5058 if (torture_setting_bool(tctx, "w2k3", false)) {
5059 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5060 push_nttime(blob.data, 0, info.info6.driver_date);
5061 test_binary("DriverDate", blob);
5062 SBVAL(blob.data, 0, info.info6.driver_version);
5063 test_binary("DriverVersion", blob);
5064 } else {
5065 test_sz("DriverDate", driver_date);
5066 test_sz("DriverVersion", driver_version);
5068 test_sz("HardwareID", info.info6.hardware_id);
5069 test_sz("Help File", help_file);
5070 test_sz("Manufacturer", info.info6.manufacturer_name);
5071 test_sz("Monitor", info.info6.monitor_name);
5072 test_sz("OEM URL", info.info6.manufacturer_url);
5073 test_sz("Provider", info.info6.provider);
5074 test_multi_sz("Dependent Files", dependent_files);
5075 test_multi_sz("Previous Names", info.info6.previous_names);
5076 /* test_dword("Attributes", ?); */
5077 test_dword("Version", info.info6.version);
5078 /* test_dword("TempDir", ?); */
5080 if (handle) {
5081 torture_assert(tctx,
5082 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5083 "failed to get driver info level 3");
5084 } else {
5085 torture_assert(tctx,
5086 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5087 "failed to get driver info level 3");
5090 driver_path = strip_path(info.info3.driver_path);
5091 data_file = strip_path(info.info3.data_file);
5092 config_file = strip_path(info.info3.config_file);
5093 help_file = strip_path(info.info3.help_file);
5094 dependent_files = strip_paths(info.info3.dependent_files);
5096 test_sz("Configuration File", config_file);
5097 test_sz("Data File", data_file);
5098 test_sz("Datatype", info.info3.default_datatype);
5099 test_sz("Driver", driver_path);
5100 test_sz("Help File", help_file);
5101 test_sz("Monitor", info.info3.monitor_name);
5102 test_multi_sz("Dependent Files", dependent_files);
5103 /* test_dword("Attributes", ?); */
5104 test_dword("Version", info.info3.version);
5105 /* test_dword("TempDir", ?); */
5108 torture_assert(tctx,
5109 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5111 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5113 return true;
5116 #undef test_sz
5117 #undef test_dword
5119 static bool test_SetPrinterData(struct torture_context *tctx,
5120 struct dcerpc_binding_handle *b,
5121 struct policy_handle *handle,
5122 const char *value_name,
5123 enum winreg_Type type,
5124 uint8_t *data,
5125 uint32_t offered)
5127 struct spoolss_SetPrinterData r;
5129 r.in.handle = handle;
5130 r.in.value_name = value_name;
5131 r.in.type = type;
5132 r.in.data = data;
5133 r.in.offered = offered;
5135 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5136 r.in.value_name);
5138 torture_assert_ntstatus_ok(tctx,
5139 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5140 "SetPrinterData failed");
5141 torture_assert_werr_ok(tctx, r.out.result,
5142 "SetPrinterData failed");
5144 return true;
5147 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5148 struct dcerpc_binding_handle *b,
5149 struct policy_handle *handle,
5150 const char *printer_name,
5151 struct dcerpc_binding_handle *winreg_handle,
5152 struct policy_handle *hive_handle)
5154 const char *values[] = {
5155 "spootyfoot",
5156 "spooty\\foot",
5157 #if 0
5158 /* FIXME: not working with s3 atm. */
5159 "spooty,foot",
5160 "spooty,fo,ot",
5161 #endif
5162 "spooty foot",
5163 #if 0
5164 /* FIXME: not working with s3 atm. */
5165 "spooty\\fo,ot",
5166 "spooty,fo\\ot"
5167 #endif
5169 int i;
5171 for (i=0; i < ARRAY_SIZE(values); i++) {
5173 enum winreg_Type type, expected_type = REG_SZ;
5174 DATA_BLOB blob;
5175 uint8_t *data;
5176 uint32_t needed;
5178 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5179 type = REG_SZ;
5181 torture_assert(tctx,
5182 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5183 "SetPrinterData failed");
5185 torture_assert(tctx,
5186 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5187 "GetPrinterData failed");
5189 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5190 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5191 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5193 if (winreg_handle && hive_handle) {
5195 enum winreg_Type w_type;
5196 uint32_t w_size;
5197 uint32_t w_length;
5198 uint8_t *w_data;
5200 torture_assert(tctx,
5201 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5202 printer_name, "PrinterDriverData", values[i],
5203 &w_type, &w_size, &w_length, &w_data), "");
5205 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5206 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5207 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5208 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5211 torture_assert(tctx,
5212 test_DeletePrinterData(tctx, b, handle, values[i]),
5213 "DeletePrinterData failed");
5216 return true;
5220 static bool test_EnumPrinterKey(struct torture_context *tctx,
5221 struct dcerpc_binding_handle *b,
5222 struct policy_handle *handle,
5223 const char *key_name,
5224 const char ***array);
5226 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5227 struct dcerpc_binding_handle *b,
5228 struct policy_handle *handle,
5229 const char *key_name,
5230 const char *value_name,
5231 enum winreg_Type type,
5232 uint8_t *data,
5233 uint32_t offered)
5235 NTSTATUS status;
5236 struct spoolss_SetPrinterDataEx r;
5238 r.in.handle = handle;
5239 r.in.key_name = key_name;
5240 r.in.value_name = value_name;
5241 r.in.type = type;
5242 r.in.data = data;
5243 r.in.offered = offered;
5245 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5246 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5248 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5250 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5251 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5253 return true;
5256 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5257 struct dcerpc_pipe *p,
5258 struct policy_handle *handle)
5260 struct dcerpc_binding_handle *b = p->binding_handle;
5261 const char *value_name = "dog";
5262 const char *keys[] = {
5263 "torturedataex",
5264 "torture data ex",
5265 "torturedataex_with_subkey\\subkey",
5266 "torturedataex_with_subkey\\subkey:0",
5267 "torturedataex_with_subkey\\subkey:1",
5268 "torturedataex_with_subkey\\subkey\\subsubkey",
5269 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5270 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5271 "torture,data",
5272 "torture,data,ex",
5273 "torture,data\\ex",
5274 "torture\\data,ex",
5275 "torture/data",
5276 "torture/data ex",
5277 "torture/data ex/sub",
5278 "torture//data",
5279 "torture//data ex",
5280 "torture//data ex/sub",
5281 "torture//data ex//sub",
5283 int i;
5285 for (i=0; i < ARRAY_SIZE(keys); i++) {
5287 char *c;
5288 const char *key;
5289 enum winreg_Type type;
5290 DATA_BLOB blob_in, blob_out;
5291 const char **subkeys;
5292 uint32_t ecount;
5293 struct spoolss_PrinterEnumValues *einfo;
5294 uint32_t needed;
5296 blob_in = data_blob_talloc(tctx, NULL, 42);
5298 generate_random_buffer(blob_in.data, blob_in.length);
5300 torture_assert(tctx,
5301 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5302 "failed to call SetPrinterDataEx");
5304 torture_assert(tctx,
5305 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5306 "failed to call GetPrinterDataEx");
5308 blob_out.length = needed;
5309 torture_assert(tctx,
5310 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5311 "failed to call EnumPrinterDataEx");
5313 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5314 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5315 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5317 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5318 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5319 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5320 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5321 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5322 if (einfo[0].data_length > 0) {
5323 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5326 key = talloc_strdup(tctx, keys[i]);
5328 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5329 return false;
5332 c = strchr(key, '\\');
5333 if (c) {
5334 int k;
5336 /* we have subkeys */
5338 *c = 0;
5340 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5341 return false;
5344 for (k=0; subkeys && subkeys[k]; k++) {
5346 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5348 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5349 return false;
5353 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5354 return false;
5357 } else {
5358 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5359 return false;
5364 return true;
5367 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5368 struct dcerpc_pipe *p,
5369 struct policy_handle *handle)
5371 struct dcerpc_binding_handle *b = p->binding_handle;
5372 const char *key = "torturedataex";
5373 const char *values[] = {
5374 "torture_value",
5375 "torture value",
5376 "torture,value",
5377 "torture/value",
5378 "torture\\value",
5379 "torture\\\\value"
5381 int i;
5383 for (i=0; i < ARRAY_SIZE(values); i++) {
5385 enum winreg_Type type;
5386 DATA_BLOB blob_in, blob_out;
5387 uint32_t ecount;
5388 struct spoolss_PrinterEnumValues *einfo;
5389 uint32_t needed;
5391 if (torture_setting_bool(tctx, "samba3", false)) {
5392 char *q;
5393 q = strrchr(values[i], ',');
5394 if (q) {
5395 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5396 values[i]);
5397 continue;
5401 blob_in = data_blob_talloc(tctx, NULL, 42);
5403 generate_random_buffer(blob_in.data, blob_in.length);
5405 torture_assert(tctx,
5406 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5407 "failed to call SetPrinterDataEx");
5409 torture_assert(tctx,
5410 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5411 "failed to call GetPrinterDataEx");
5413 blob_out.length = needed;
5414 torture_assert(tctx,
5415 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5416 "failed to call EnumPrinterDataEx");
5418 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5419 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5420 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5422 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5423 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5424 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5425 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5426 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5427 if (einfo[0].data_length > 0) {
5428 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5431 torture_assert(tctx,
5432 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5433 "failed to call DeletePrinterDataEx");
5436 return true;
5440 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5441 struct dcerpc_pipe *p,
5442 struct policy_handle *handle,
5443 const char *printername,
5444 struct dcerpc_binding_handle *winreg_handle,
5445 struct policy_handle *hive_handle)
5447 struct dcerpc_binding_handle *b = p->binding_handle;
5448 const char *value_name = "dog";
5449 const char *key_name = "torturedataex";
5450 enum winreg_Type types[] = {
5451 REG_SZ,
5452 REG_MULTI_SZ,
5453 REG_DWORD,
5454 REG_BINARY
5456 const char *str = "abcdefghi";
5457 int t, s;
5459 for (t=0; t < ARRAY_SIZE(types); t++) {
5460 for (s=0; s < strlen(str); s++) {
5462 enum winreg_Type type;
5463 const char *string = talloc_strndup(tctx, str, s);
5464 const char *array[2];
5465 DATA_BLOB blob = data_blob_string_const(string);
5466 DATA_BLOB data;
5467 uint8_t *data_out;
5468 uint32_t needed, offered = 0;
5469 uint32_t ecount;
5470 struct spoolss_PrinterEnumValues *einfo;
5472 array[0] = talloc_strdup(tctx, string);
5473 array[1] = NULL;
5475 if (types[t] == REG_DWORD) {
5476 s = 0xffff;
5479 switch (types[t]) {
5480 case REG_BINARY:
5481 data = blob;
5482 offered = blob.length;
5483 break;
5484 case REG_DWORD:
5485 data = data_blob_talloc(tctx, NULL, 4);
5486 SIVAL(data.data, 0, 0x12345678);
5487 offered = 4;
5488 break;
5489 case REG_SZ:
5490 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5491 type = REG_SZ;
5492 offered = data.length;
5493 /*strlen_m_term(data.string)*2;*/
5494 break;
5495 case REG_MULTI_SZ:
5496 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5497 type = REG_MULTI_SZ;
5498 offered = data.length;
5499 break;
5500 default:
5501 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5504 torture_assert(tctx,
5505 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5506 "failed to call SetPrinterDataEx");
5508 torture_assert(tctx,
5509 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5510 "failed to call GetPrinterDataEx");
5512 torture_assert(tctx,
5513 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5514 "failed to call EnumPrinterDataEx");
5516 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5517 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5518 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5520 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5521 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5522 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5523 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5524 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5525 if (einfo[0].data_length > 0) {
5526 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5529 if (winreg_handle && hive_handle) {
5530 enum winreg_Type w_type;
5531 uint32_t w_size;
5532 uint32_t w_length;
5533 uint8_t *w_data;
5535 torture_assert(tctx,
5536 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5537 printername, key_name, value_name,
5538 &w_type, &w_size, &w_length, &w_data), "");
5540 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5541 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5542 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5543 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5546 torture_assert(tctx,
5547 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5548 "failed to call DeletePrinterDataEx");
5552 return true;
5555 static bool test_PrinterData_winreg(struct torture_context *tctx,
5556 struct dcerpc_pipe *p,
5557 struct policy_handle *handle,
5558 const char *printer_name)
5560 struct dcerpc_binding_handle *b = p->binding_handle;
5561 struct dcerpc_pipe *p2;
5562 bool ret = true;
5563 struct policy_handle hive_handle;
5564 struct dcerpc_binding_handle *b2;
5566 torture_assert_ntstatus_ok(tctx,
5567 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5568 "could not open winreg pipe");
5569 b2 = p2->binding_handle;
5571 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5573 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5574 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5576 test_winreg_CloseKey(tctx, b2, &hive_handle);
5578 talloc_free(p2);
5580 return ret;
5583 static bool test_Forms_winreg(struct torture_context *tctx,
5584 struct dcerpc_binding_handle *b,
5585 struct policy_handle *handle,
5586 bool print_server,
5587 const char *printer_name)
5589 struct dcerpc_pipe *p2;
5590 bool ret = true;
5591 struct policy_handle hive_handle;
5592 struct dcerpc_binding_handle *b2;
5594 torture_assert_ntstatus_ok(tctx,
5595 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5596 "could not open winreg pipe");
5597 b2 = p2->binding_handle;
5599 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5601 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5603 test_winreg_CloseKey(tctx, b2, &hive_handle);
5605 talloc_free(p2);
5607 return ret;
5610 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5611 struct dcerpc_pipe *p,
5612 struct policy_handle *handle,
5613 const char *printer_name)
5615 struct dcerpc_binding_handle *b = p->binding_handle;
5616 struct dcerpc_pipe *p2;
5617 bool ret = true;
5618 struct policy_handle hive_handle;
5619 struct dcerpc_binding_handle *b2;
5621 torture_assert_ntstatus_ok(tctx,
5622 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5623 "could not open winreg pipe");
5624 b2 = p2->binding_handle;
5626 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5628 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5630 test_winreg_CloseKey(tctx, b2, &hive_handle);
5632 talloc_free(p2);
5634 return ret;
5637 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5638 struct dcerpc_pipe *p,
5639 struct policy_handle *handle,
5640 const char *printer_name,
5641 const char *driver_name,
5642 const char *environment,
5643 enum spoolss_DriverOSVersion version)
5645 struct dcerpc_binding_handle *b = p->binding_handle;
5646 struct dcerpc_pipe *p2;
5647 bool ret = true;
5648 struct policy_handle hive_handle;
5649 struct dcerpc_binding_handle *b2;
5651 torture_assert_ntstatus_ok(tctx,
5652 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5653 "could not open winreg pipe");
5654 b2 = p2->binding_handle;
5656 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5658 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5660 test_winreg_CloseKey(tctx, b2, &hive_handle);
5662 talloc_free(p2);
5664 return ret;
5667 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5668 struct dcerpc_binding_handle *b,
5669 const char *environment)
5671 struct dcerpc_pipe *p2;
5672 bool ret = true;
5673 struct policy_handle hive_handle;
5674 struct dcerpc_binding_handle *b2;
5676 torture_assert_ntstatus_ok(tctx,
5677 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5678 "could not open winreg pipe");
5679 b2 = p2->binding_handle;
5681 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5683 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5685 test_winreg_CloseKey(tctx, b2, &hive_handle);
5687 talloc_free(p2);
5689 return ret;
5692 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5693 struct dcerpc_pipe *p,
5694 struct policy_handle *handle,
5695 const char *printer_name)
5697 struct spoolss_SetPrinterInfoCtr info_ctr;
5698 struct spoolss_DevmodeContainer devmode_ctr;
5699 struct sec_desc_buf secdesc_ctr;
5700 union spoolss_SetPrinterInfo sinfo;
5701 union spoolss_PrinterInfo info;
5702 struct dcerpc_binding_handle *b = p->binding_handle;
5703 const char *pname;
5705 ZERO_STRUCT(info_ctr);
5706 ZERO_STRUCT(devmode_ctr);
5707 ZERO_STRUCT(secdesc_ctr);
5709 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5711 torture_assert(tctx,
5712 test_GetPrinter_level(tctx, b, handle, 2, &info),
5713 "failed to query Printer level 2");
5715 torture_assert(tctx,
5716 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5717 "failed to convert");
5719 info_ctr.level = 2;
5720 info_ctr.info = sinfo;
5722 #define TEST_SZ(wname, iname) \
5723 do {\
5724 enum winreg_Type type;\
5725 uint8_t *data;\
5726 uint32_t needed;\
5727 DATA_BLOB blob;\
5728 const char *str;\
5729 torture_assert(tctx,\
5730 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5731 "failed to query");\
5732 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5733 blob = data_blob_const(data, needed);\
5734 torture_assert(tctx,\
5735 pull_reg_sz(tctx, &blob, &str),\
5736 "failed to pull REG_SZ");\
5737 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5738 } while(0);
5741 #define TEST_SET_SZ(wname, iname, val) \
5742 do {\
5743 enum winreg_Type type;\
5744 uint8_t *data;\
5745 uint32_t needed;\
5746 DATA_BLOB blob;\
5747 const char *str;\
5748 sinfo.info2->iname = val;\
5749 torture_assert(tctx,\
5750 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5751 "failed to call SetPrinter");\
5752 torture_assert(tctx,\
5753 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5754 "failed to query");\
5755 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5756 blob = data_blob_const(data, needed);\
5757 torture_assert(tctx,\
5758 pull_reg_sz(tctx, &blob, &str),\
5759 "failed to pull REG_SZ");\
5760 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5761 } while(0);
5763 #define TEST_SET_DWORD(wname, iname, val) \
5764 do {\
5765 enum winreg_Type type;\
5766 uint8_t *data;\
5767 uint32_t needed;\
5768 uint32_t value;\
5769 sinfo.info2->iname = val;\
5770 torture_assert(tctx,\
5771 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5772 "failed to call SetPrinter");\
5773 torture_assert(tctx,\
5774 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5775 "failed to query");\
5776 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5777 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5778 value = IVAL(data, 0); \
5779 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5780 } while(0);
5782 TEST_SET_SZ("description", comment, "newval");
5783 TEST_SET_SZ("location", location, "newval");
5784 TEST_SET_SZ("driverName", drivername, "newval");
5785 /* TEST_SET_DWORD("priority", priority, 25); */
5787 torture_assert(tctx,
5788 test_GetPrinter_level(tctx, b, handle, 2, &info),
5789 "failed to query Printer level 2");
5791 TEST_SZ("description", info.info2.comment);
5792 TEST_SZ("driverName", info.info2.drivername);
5793 TEST_SZ("location", info.info2.location);
5795 pname = strrchr(info.info2.printername, '\\');
5796 if (pname == NULL) {
5797 pname = info.info2.printername;
5798 } else {
5799 pname++;
5801 TEST_SZ("printerName", pname);
5802 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5803 /* TEST_SZ("printShareName", info.info2.sharename); */
5805 /* FIXME gd: complete the list */
5807 #undef TEST_SZ
5808 #undef TEST_SET_SZ
5809 #undef TEST_DWORD
5811 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5813 return true;
5816 static bool test_print_processors_winreg(struct torture_context *tctx,
5817 void *private_data)
5819 struct test_spoolss_context *ctx =
5820 talloc_get_type_abort(private_data, struct test_spoolss_context);
5821 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5822 struct dcerpc_binding_handle *b = p->binding_handle;
5824 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5827 static bool test_AddPrintProcessor(struct torture_context *tctx,
5828 struct dcerpc_binding_handle *b,
5829 const char *environment,
5830 const char *path_name,
5831 const char *print_processor_name,
5832 WERROR expected_error)
5834 struct spoolss_AddPrintProcessor r;
5836 r.in.server = NULL;
5837 r.in.architecture = environment;
5838 r.in.path_name = path_name;
5839 r.in.print_processor_name = print_processor_name;
5841 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5842 print_processor_name);
5844 torture_assert_ntstatus_ok(tctx,
5845 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5846 "spoolss_AddPrintProcessor failed");
5847 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5848 "spoolss_AddPrintProcessor failed");
5850 return true;
5853 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5854 struct dcerpc_binding_handle *b,
5855 const char *environment,
5856 const char *print_processor_name,
5857 WERROR expected_error)
5859 struct spoolss_DeletePrintProcessor r;
5861 r.in.server = NULL;
5862 r.in.architecture = environment;
5863 r.in.print_processor_name = print_processor_name;
5865 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5866 print_processor_name);
5868 torture_assert_ntstatus_ok(tctx,
5869 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5870 "spoolss_DeletePrintProcessor failed");
5871 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5872 "spoolss_DeletePrintProcessor failed");
5874 return true;
5877 static bool test_add_print_processor(struct torture_context *tctx,
5878 void *private_data)
5880 struct test_spoolss_context *ctx =
5881 talloc_get_type_abort(private_data, struct test_spoolss_context);
5882 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5883 struct dcerpc_binding_handle *b = p->binding_handle;
5884 int i;
5886 struct {
5887 const char *environment;
5888 const char *path_name;
5889 const char *print_processor_name;
5890 WERROR expected_add_result;
5891 WERROR expected_del_result;
5892 } tests[] = {
5894 .environment = ctx->environment,
5895 .path_name = "",
5896 .print_processor_name = "winprint",
5897 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
5898 .expected_del_result = WERR_CAN_NOT_COMPLETE
5900 .environment = ctx->environment,
5901 .path_name = "",
5902 .print_processor_name = "unknown",
5903 .expected_add_result = WERR_MOD_NOT_FOUND,
5904 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
5908 for (i=0; i < ARRAY_SIZE(tests); i++) {
5909 torture_assert(tctx,
5910 test_AddPrintProcessor(tctx, b,
5911 tests[i].environment,
5912 tests[i].path_name,
5913 tests[i].print_processor_name,
5914 tests[i].expected_add_result),
5915 "add print processor failed");
5916 torture_assert(tctx,
5917 test_DeletePrintProcessor(tctx, b,
5918 tests[i].environment,
5919 tests[i].print_processor_name,
5920 tests[i].expected_del_result),
5921 "delete print processor failed");
5924 return true;
5927 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5928 struct dcerpc_binding_handle *b,
5929 struct policy_handle *handle,
5930 uint32_t *change_id)
5932 enum winreg_Type type;
5933 uint8_t *data;
5934 uint32_t needed;
5936 torture_assert(tctx,
5937 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5938 "failed to call GetPrinterData");
5940 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5941 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5943 *change_id = IVAL(data, 0);
5945 return true;
5948 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5949 struct dcerpc_pipe *p,
5950 struct policy_handle *handle,
5951 uint32_t *change_id)
5953 enum winreg_Type type;
5954 uint8_t *data;
5955 uint32_t needed;
5957 torture_assert(tctx,
5958 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5959 "failed to call GetPrinterData");
5961 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5962 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5964 *change_id = IVAL(data, 0);
5966 return true;
5969 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5970 struct dcerpc_binding_handle *b,
5971 struct policy_handle *handle,
5972 uint32_t *change_id)
5974 union spoolss_PrinterInfo info;
5976 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5977 "failed to query Printer level 0");
5979 *change_id = info.info0.change_id;
5981 return true;
5984 static bool test_ChangeID(struct torture_context *tctx,
5985 struct dcerpc_pipe *p,
5986 struct policy_handle *handle)
5988 uint32_t change_id, change_id_ex, change_id_info;
5989 uint32_t change_id2, change_id_ex2, change_id_info2;
5990 union spoolss_PrinterInfo info;
5991 const char *comment;
5992 struct dcerpc_binding_handle *b = p->binding_handle;
5994 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5996 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5997 "failed to query for ChangeID");
5998 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5999 "failed to query for ChangeID");
6000 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6001 "failed to query for ChangeID");
6003 torture_assert_int_equal(tctx, change_id, change_id_ex,
6004 "change_ids should all be equal");
6005 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6006 "change_ids should all be equal");
6009 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6011 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6012 "failed to query for ChangeID");
6013 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6014 "failed to query Printer level 2");
6015 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6016 "failed to query for ChangeID");
6017 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6018 "failed to query for ChangeID");
6019 torture_assert_int_equal(tctx, change_id, change_id_ex,
6020 "change_id should not have changed");
6021 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6022 "change_id should not have changed");
6025 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6027 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6028 "failed to query for ChangeID");
6029 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6030 "failed to query for ChangeID");
6031 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6032 "failed to query for ChangeID");
6033 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6034 "failed to query Printer level 2");
6035 comment = talloc_strdup(tctx, info.info2.comment);
6038 struct spoolss_SetPrinterInfoCtr info_ctr;
6039 struct spoolss_DevmodeContainer devmode_ctr;
6040 struct sec_desc_buf secdesc_ctr;
6041 union spoolss_SetPrinterInfo sinfo;
6043 ZERO_STRUCT(info_ctr);
6044 ZERO_STRUCT(devmode_ctr);
6045 ZERO_STRUCT(secdesc_ctr);
6048 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6049 sinfo.info2->comment = "torture_comment";
6051 info_ctr.level = 2;
6052 info_ctr.info = sinfo;
6054 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6055 "failed to call SetPrinter");
6057 sinfo.info2->comment = comment;
6059 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6060 "failed to call SetPrinter");
6064 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6065 "failed to query for ChangeID");
6066 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6067 "failed to query for ChangeID");
6068 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6069 "failed to query for ChangeID");
6071 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6072 "change_ids should all be equal");
6073 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6074 "change_ids should all be equal");
6076 torture_assert(tctx, (change_id < change_id2),
6077 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6078 change_id2, change_id));
6079 torture_assert(tctx, (change_id_ex < change_id_ex2),
6080 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6081 change_id_ex2, change_id_ex));
6082 torture_assert(tctx, (change_id_info < change_id_info2),
6083 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6084 change_id_info2, change_id_info));
6086 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6088 return true;
6091 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6092 struct dcerpc_pipe *p,
6093 struct policy_handle *handle)
6095 NTSTATUS status;
6096 struct dcerpc_binding *b;
6097 struct dcerpc_pipe *p2;
6098 struct spoolss_ClosePrinter cp;
6100 /* only makes sense on SMB */
6101 if (p->conn->transport.transport != NCACN_NP) {
6102 return true;
6105 torture_comment(tctx, "Testing close on secondary pipe\n");
6107 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
6108 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
6110 status = dcerpc_secondary_connection(p, &p2, b);
6111 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6113 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6114 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6116 cp.in.handle = handle;
6117 cp.out.handle = handle;
6119 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6120 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6121 "ERROR: Allowed close on secondary connection");
6123 talloc_free(p2);
6125 return true;
6128 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6129 struct dcerpc_binding_handle *b, const char *name)
6131 NTSTATUS status;
6132 struct spoolss_OpenPrinter op;
6133 struct spoolss_OpenPrinterEx opEx;
6134 struct policy_handle handle;
6135 bool ret = true;
6137 op.in.printername = name;
6138 op.in.datatype = NULL;
6139 op.in.devmode_ctr.devmode= NULL;
6140 op.in.access_mask = 0;
6141 op.out.handle = &handle;
6143 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6145 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6146 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6147 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6148 "unexpected result");
6150 if (W_ERROR_IS_OK(op.out.result)) {
6151 ret &=test_ClosePrinter(tctx, b, &handle);
6154 opEx.in.printername = name;
6155 opEx.in.datatype = NULL;
6156 opEx.in.devmode_ctr.devmode = NULL;
6157 opEx.in.access_mask = 0;
6158 opEx.in.userlevel_ctr.level = 1;
6159 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6160 opEx.out.handle = &handle;
6162 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6164 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6165 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6166 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6167 "unexpected result");
6169 if (W_ERROR_IS_OK(opEx.out.result)) {
6170 ret &=test_ClosePrinter(tctx, b, &handle);
6173 return ret;
6176 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6177 void *private_data)
6179 struct test_spoolss_context *ctx =
6180 talloc_get_type_abort(private_data, struct test_spoolss_context);
6182 const char *badnames[] = {
6183 "__INVALID_PRINTER__",
6184 "\\\\__INVALID_HOST__",
6186 "\\\\\\",
6187 "\\\\\\__INVALID_PRINTER__"
6189 const char *badname;
6190 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6191 const char *server_name = dcerpc_server_name(p);
6192 struct dcerpc_binding_handle *b = p->binding_handle;
6193 int i;
6195 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6196 torture_assert(tctx,
6197 test_OpenPrinter_badname(tctx, b, badnames[i]),
6198 "");
6201 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6202 torture_assert(tctx,
6203 test_OpenPrinter_badname(tctx, b, badname),
6204 "");
6206 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6207 torture_assert(tctx,
6208 test_OpenPrinter_badname(tctx, b, badname),
6209 "");
6211 return true;
6214 static bool test_OpenPrinter(struct torture_context *tctx,
6215 struct dcerpc_pipe *p,
6216 const char *name,
6217 const char *environment,
6218 bool open_only)
6220 NTSTATUS status;
6221 struct spoolss_OpenPrinter r;
6222 struct policy_handle handle;
6223 bool ret = true;
6224 struct dcerpc_binding_handle *b = p->binding_handle;
6226 r.in.printername = name;
6227 r.in.datatype = NULL;
6228 r.in.devmode_ctr.devmode= NULL;
6229 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6230 r.out.handle = &handle;
6232 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6234 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6236 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6238 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6240 if (open_only) {
6241 goto close_printer;
6244 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6245 ret = false;
6248 if (!torture_setting_bool(tctx, "samba3", false)) {
6249 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6250 ret = false;
6254 close_printer:
6255 if (!test_ClosePrinter(tctx, b, &handle)) {
6256 ret = false;
6259 return ret;
6262 static bool test_OpenPrinterEx(struct torture_context *tctx,
6263 struct dcerpc_binding_handle *b,
6264 const char *printername,
6265 const char *datatype,
6266 struct spoolss_DeviceMode *devmode,
6267 uint32_t access_mask,
6268 struct spoolss_UserLevelCtr *userlevel_ctr,
6269 struct policy_handle *handle,
6270 WERROR expected_result)
6272 struct spoolss_OpenPrinterEx r;
6274 r.in.printername = printername;
6275 r.in.datatype = datatype;
6276 r.in.devmode_ctr.devmode= devmode;
6277 r.in.access_mask = access_mask;
6278 r.in.userlevel_ctr = *userlevel_ctr;
6279 r.out.handle = handle;
6281 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6283 torture_assert_ntstatus_ok(tctx,
6284 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6285 "OpenPrinterEx failed");
6287 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6288 "OpenPrinterEx failed");
6290 return true;
6293 static bool call_OpenPrinterEx(struct torture_context *tctx,
6294 struct dcerpc_pipe *p,
6295 const char *name,
6296 struct spoolss_DeviceMode *devmode,
6297 struct policy_handle *handle)
6299 struct spoolss_UserLevelCtr userlevel_ctr;
6300 struct spoolss_UserLevel1 userlevel1;
6301 struct dcerpc_binding_handle *b = p->binding_handle;
6303 userlevel1.size = 1234;
6304 userlevel1.client = "hello";
6305 userlevel1.user = "spottyfoot!";
6306 userlevel1.build = 1;
6307 userlevel1.major = 2;
6308 userlevel1.minor = 3;
6309 userlevel1.processor = 4;
6311 userlevel_ctr.level = 1;
6312 userlevel_ctr.user_info.level1 = &userlevel1;
6314 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6315 SEC_FLAG_MAXIMUM_ALLOWED,
6316 &userlevel_ctr,
6317 handle,
6318 WERR_OK);
6321 static bool test_printer_rename(struct torture_context *tctx,
6322 void *private_data)
6324 struct torture_printer_context *t =
6325 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6326 struct dcerpc_pipe *p = t->spoolss_pipe;
6328 bool ret = true;
6329 union spoolss_PrinterInfo info;
6330 union spoolss_SetPrinterInfo sinfo;
6331 struct spoolss_SetPrinterInfoCtr info_ctr;
6332 struct spoolss_DevmodeContainer devmode_ctr;
6333 struct sec_desc_buf secdesc_ctr;
6334 const char *printer_name;
6335 const char *printer_name_orig;
6336 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6337 struct policy_handle new_handle;
6338 const char *q;
6339 struct dcerpc_binding_handle *b = p->binding_handle;
6341 ZERO_STRUCT(devmode_ctr);
6342 ZERO_STRUCT(secdesc_ctr);
6344 torture_comment(tctx, "Testing Printer rename operations\n");
6346 torture_assert(tctx,
6347 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6348 "failed to call GetPrinter level 2");
6350 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6352 q = strrchr(info.info2.printername, '\\');
6353 if (q) {
6354 torture_warning(tctx,
6355 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6358 torture_assert(tctx,
6359 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6361 sinfo.info2->printername = printer_name_new;
6363 info_ctr.level = 2;
6364 info_ctr.info = sinfo;
6366 torture_assert(tctx,
6367 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6368 "failed to call SetPrinter level 2");
6370 torture_assert(tctx,
6371 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6372 "failed to call GetPrinter level 2");
6374 printer_name = talloc_strdup(tctx, info.info2.printername);
6376 q = strrchr(info.info2.printername, '\\');
6377 if (q) {
6378 torture_warning(tctx,
6379 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6380 q++;
6381 printer_name = q;
6384 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6385 "new printer name was not set");
6387 /* samba currently cannot fully rename printers */
6388 if (!torture_setting_bool(tctx, "samba3", false)) {
6389 torture_assert(tctx,
6390 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6391 "still can open printer with oldname after rename");
6392 } else {
6393 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6396 torture_assert(tctx,
6397 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6398 "failed to open printer with new name");
6400 torture_assert(tctx,
6401 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6402 "failed to call GetPrinter level 2");
6404 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6405 "new printer name was not set");
6407 torture_assert(tctx,
6408 test_ClosePrinter(tctx, b, &new_handle),
6409 "failed to close printer");
6411 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6413 return ret;
6416 static bool test_openprinter(struct torture_context *tctx,
6417 struct dcerpc_binding_handle *b,
6418 const char *real_printername)
6420 struct spoolss_UserLevelCtr userlevel_ctr;
6421 struct policy_handle handle;
6422 struct spoolss_UserLevel1 userlevel1;
6423 const char *printername = NULL;
6424 int i;
6426 struct {
6427 const char *suffix;
6428 WERROR expected_result;
6429 } tests[] = {
6431 .suffix = "rubbish",
6432 .expected_result = WERR_INVALID_PRINTER_NAME
6434 .suffix = ", LocalOnl",
6435 .expected_result = WERR_INVALID_PRINTER_NAME
6437 .suffix = ", localOnly",
6438 .expected_result = WERR_INVALID_PRINTER_NAME
6440 .suffix = ", localonl",
6441 .expected_result = WERR_INVALID_PRINTER_NAME
6443 .suffix = ",LocalOnl",
6444 .expected_result = WERR_INVALID_PRINTER_NAME
6446 .suffix = ",localOnl2",
6447 .expected_result = WERR_INVALID_PRINTER_NAME
6449 .suffix = ", DrvConver2t",
6450 .expected_result = WERR_INVALID_PRINTER_NAME
6452 .suffix = ", drvconvert",
6453 .expected_result = WERR_INVALID_PRINTER_NAME
6455 .suffix = ",drvconvert",
6456 .expected_result = WERR_INVALID_PRINTER_NAME
6458 .suffix = ", DrvConvert",
6459 .expected_result = WERR_OK
6461 .suffix = " , DrvConvert",
6462 .expected_result = WERR_INVALID_PRINTER_NAME
6464 .suffix = ",DrvConvert",
6465 .expected_result = WERR_OK
6467 .suffix = ", DrvConvertsadfasdf",
6468 .expected_result = WERR_OK
6470 .suffix = ",DrvConvertasdfasd",
6471 .expected_result = WERR_OK
6473 .suffix = ", LocalOnly",
6474 .expected_result = WERR_OK
6476 .suffix = " , LocalOnly",
6477 .expected_result = WERR_INVALID_PRINTER_NAME
6479 .suffix = ",LocalOnly",
6480 .expected_result = WERR_OK
6482 .suffix = ", LocalOnlysagi4gjfkd",
6483 .expected_result = WERR_OK
6485 .suffix = ",LocalOnlysagi4gjfkd",
6486 .expected_result = WERR_OK
6490 userlevel1.size = 1234;
6491 userlevel1.client = "hello";
6492 userlevel1.user = "spottyfoot!";
6493 userlevel1.build = 1;
6494 userlevel1.major = 2;
6495 userlevel1.minor = 3;
6496 userlevel1.processor = 4;
6498 userlevel_ctr.level = 1;
6499 userlevel_ctr.user_info.level1 = &userlevel1;
6501 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6503 torture_assert(tctx,
6504 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6505 &userlevel_ctr, &handle,
6506 WERR_OK),
6507 "OpenPrinterEx failed");
6508 test_ClosePrinter(tctx, b, &handle);
6510 for (i=0; i < ARRAY_SIZE(tests); i++) {
6512 printername = talloc_asprintf(tctx, "%s%s",
6513 real_printername,
6514 tests[i].suffix);
6516 torture_assert(tctx,
6517 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6518 &userlevel_ctr, &handle,
6519 tests[i].expected_result),
6520 "OpenPrinterEx failed");
6521 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6522 test_ClosePrinter(tctx, b, &handle);
6526 return true;
6530 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6531 struct dcerpc_pipe *p,
6532 const char *name,
6533 const char *environment)
6535 struct policy_handle handle;
6536 bool ret = true;
6537 struct dcerpc_binding_handle *b = p->binding_handle;
6539 if (!test_openprinter(tctx, b, name)) {
6540 return false;
6543 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6544 return false;
6547 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6548 ret = false;
6551 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6552 ret = false;
6555 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6556 ret = false;
6559 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6560 ret = false;
6563 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6564 ret = false;
6567 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6568 ret = false;
6571 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6572 ret = false;
6575 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6576 ret = false;
6579 if (!test_printer_all_keys(tctx, b, &handle)) {
6580 ret = false;
6583 if (!test_PausePrinter(tctx, b, &handle)) {
6584 ret = false;
6587 if (!test_DoPrintTest(tctx, b, &handle)) {
6588 ret = false;
6591 if (!test_ResumePrinter(tctx, b, &handle)) {
6592 ret = false;
6595 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6596 ret = false;
6599 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6600 ret = false;
6603 if (!torture_setting_bool(tctx, "samba3", false)) {
6604 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6605 ret = false;
6609 if (!test_ClosePrinter(tctx, b, &handle)) {
6610 ret = false;
6613 return ret;
6616 static bool test_EnumPrinters_old(struct torture_context *tctx,
6617 void *private_data)
6619 struct test_spoolss_context *ctx =
6620 talloc_get_type_abort(private_data, struct test_spoolss_context);
6621 struct spoolss_EnumPrinters r;
6622 NTSTATUS status;
6623 uint16_t levels[] = {1, 2, 4, 5};
6624 int i;
6625 bool ret = true;
6626 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6627 struct dcerpc_binding_handle *b = p->binding_handle;
6629 for (i=0;i<ARRAY_SIZE(levels);i++) {
6630 union spoolss_PrinterInfo *info;
6631 int j;
6632 uint32_t needed;
6633 uint32_t count;
6635 r.in.flags = PRINTER_ENUM_LOCAL;
6636 r.in.server = "";
6637 r.in.level = levels[i];
6638 r.in.buffer = NULL;
6639 r.in.offered = 0;
6640 r.out.needed = &needed;
6641 r.out.count = &count;
6642 r.out.info = &info;
6644 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6646 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6647 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6649 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6650 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6651 r.in.buffer = &blob;
6652 r.in.offered = needed;
6653 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6656 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6658 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6660 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6662 if (!info) {
6663 torture_comment(tctx, "No printers returned\n");
6664 return true;
6667 for (j=0;j<count;j++) {
6668 if (r.in.level == 1) {
6669 char *unc = talloc_strdup(tctx, info[j].info1.name);
6670 char *slash, *name, *full_name;
6671 name = unc;
6672 if (unc[0] == '\\' && unc[1] == '\\') {
6673 unc +=2;
6675 slash = strchr(unc, '\\');
6676 if (slash) {
6677 slash++;
6678 name = slash;
6680 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6681 dcerpc_server_name(p), name);
6682 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6683 ret = false;
6685 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6686 ret = false;
6688 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6689 ret = false;
6691 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6692 ret = false;
6698 return ret;
6701 static bool test_EnumPrinters_level(struct torture_context *tctx,
6702 struct dcerpc_binding_handle *b,
6703 uint32_t flags,
6704 const char *servername,
6705 uint32_t level,
6706 uint32_t *count_p,
6707 union spoolss_PrinterInfo **info_p)
6709 struct spoolss_EnumPrinters r;
6710 union spoolss_PrinterInfo *info;
6711 uint32_t needed;
6712 uint32_t count;
6714 r.in.flags = flags;
6715 r.in.server = servername;
6716 r.in.level = level;
6717 r.in.buffer = NULL;
6718 r.in.offered = 0;
6719 r.out.needed = &needed;
6720 r.out.count = &count;
6721 r.out.info = &info;
6723 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6724 r.in.server, r.in.level);
6726 torture_assert_ntstatus_ok(tctx,
6727 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6728 "EnumPrinters failed");
6729 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6730 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6731 r.in.buffer = &blob;
6732 r.in.offered = needed;
6733 torture_assert_ntstatus_ok(tctx,
6734 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6735 "EnumPrinters failed");
6738 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6740 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6742 if (count_p) {
6743 *count_p = count;
6745 if (info_p) {
6746 *info_p = info;
6749 return true;
6752 static const char *get_short_printername(struct torture_context *tctx,
6753 const char *name)
6755 const char *short_name;
6757 if (name[0] == '\\' && name[1] == '\\') {
6758 name += 2;
6759 short_name = strchr(name, '\\');
6760 if (short_name) {
6761 return talloc_strdup(tctx, short_name+1);
6765 return name;
6768 static const char *get_full_printername(struct torture_context *tctx,
6769 const char *name)
6771 const char *full_name = talloc_strdup(tctx, name);
6772 char *p;
6774 if (name && name[0] == '\\' && name[1] == '\\') {
6775 name += 2;
6776 p = strchr(name, '\\');
6777 if (p) {
6778 return full_name;
6782 return NULL;
6785 static bool test_OnePrinter_servername(struct torture_context *tctx,
6786 struct dcerpc_pipe *p,
6787 struct dcerpc_binding_handle *b,
6788 const char *servername,
6789 const char *printername)
6791 union spoolss_PrinterInfo info;
6792 const char *short_name = get_short_printername(tctx, printername);
6793 const char *full_name = get_full_printername(tctx, printername);
6795 if (short_name) {
6796 struct policy_handle handle;
6797 torture_assert(tctx,
6798 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6799 "failed to open printer");
6801 torture_assert(tctx,
6802 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6803 "failed to get printer info");
6805 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6806 "unexpected servername");
6807 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6808 "unexpected printername");
6810 if (info.info2.devmode) {
6811 const char *expected_devicename;
6812 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6813 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6814 "unexpected devicemode devicename");
6817 torture_assert(tctx,
6818 test_ClosePrinter(tctx, b, &handle),
6819 "failed to close printer");
6822 if (full_name) {
6823 struct policy_handle handle;
6825 torture_assert(tctx,
6826 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6827 "failed to open printer");
6829 torture_assert(tctx,
6830 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6831 "failed to get printer info");
6833 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6834 "unexpected servername");
6835 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6836 "unexpected printername");
6838 if (info.info2.devmode) {
6839 const char *expected_devicename;
6840 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6841 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6842 "unexpected devicemode devicename");
6845 torture_assert(tctx,
6846 test_ClosePrinter(tctx, b, &handle),
6847 "failed to close printer");
6850 return true;
6853 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6854 void *private_data)
6856 struct test_spoolss_context *ctx =
6857 talloc_get_type_abort(private_data, struct test_spoolss_context);
6858 int i;
6859 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6860 struct dcerpc_binding_handle *b = p->binding_handle;
6861 uint32_t count;
6862 union spoolss_PrinterInfo *info;
6863 const char *servername;
6864 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6866 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6868 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6870 torture_assert(tctx,
6871 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6872 "failed to enumerate printers");
6874 for (i=0; i < count; i++) {
6876 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6877 "unexpected servername");
6879 torture_assert(tctx,
6880 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6881 "failed to check printer");
6884 servername = "";
6886 torture_assert(tctx,
6887 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6888 "failed to enumerate printers");
6890 for (i=0; i < count; i++) {
6892 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6893 "unexpected servername");
6895 torture_assert(tctx,
6896 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6897 "failed to check printer");
6901 return true;
6905 static bool test_GetPrinterDriver(struct torture_context *tctx,
6906 struct dcerpc_binding_handle *b,
6907 struct policy_handle *handle,
6908 const char *driver_name)
6910 struct spoolss_GetPrinterDriver r;
6911 uint32_t needed;
6913 r.in.handle = handle;
6914 r.in.architecture = "W32X86";
6915 r.in.level = 1;
6916 r.in.buffer = NULL;
6917 r.in.offered = 0;
6918 r.out.needed = &needed;
6920 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6922 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6923 "failed to call GetPrinterDriver");
6924 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6925 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6926 r.in.buffer = &blob;
6927 r.in.offered = needed;
6928 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6929 "failed to call GetPrinterDriver");
6932 torture_assert_werr_ok(tctx, r.out.result,
6933 "failed to call GetPrinterDriver");
6935 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6937 return true;
6940 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6941 struct dcerpc_binding_handle *b,
6942 struct policy_handle *handle,
6943 const char *driver_name,
6944 const char *architecture,
6945 uint32_t level,
6946 uint32_t client_major_version,
6947 uint32_t client_minor_version,
6948 union spoolss_DriverInfo *info_p,
6949 WERROR *result_p)
6952 struct spoolss_GetPrinterDriver2 r;
6953 uint32_t needed;
6954 uint32_t server_major_version;
6955 uint32_t server_minor_version;
6957 r.in.handle = handle;
6958 r.in.architecture = architecture;
6959 r.in.client_major_version = client_major_version;
6960 r.in.client_minor_version = client_minor_version;
6961 r.in.buffer = NULL;
6962 r.in.offered = 0;
6963 r.in.level = level;
6964 r.out.needed = &needed;
6965 r.out.server_major_version = &server_major_version;
6966 r.out.server_minor_version = &server_minor_version;
6968 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6969 driver_name, r.in.level);
6971 torture_assert_ntstatus_ok(tctx,
6972 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6973 "failed to call GetPrinterDriver2");
6974 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6975 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6976 r.in.buffer = &blob;
6977 r.in.offered = needed;
6978 torture_assert_ntstatus_ok(tctx,
6979 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6980 "failed to call GetPrinterDriver2");
6983 if (result_p) {
6984 *result_p = r.out.result;
6987 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6988 switch (r.in.level) {
6989 case 101:
6990 case 8:
6991 torture_comment(tctx,
6992 "level %d not implemented, not considering as an error\n",
6993 r.in.level);
6994 return true;
6995 default:
6996 break;
7000 torture_assert_werr_ok(tctx, r.out.result,
7001 "failed to call GetPrinterDriver2");
7003 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7005 if (info_p) {
7006 *info_p = *r.out.info;
7009 return true;
7012 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7013 struct dcerpc_binding_handle *b,
7014 struct policy_handle *handle,
7015 const char *driver_name,
7016 const char *architecture)
7018 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7019 int i;
7022 for (i=0;i<ARRAY_SIZE(levels);i++) {
7024 torture_assert(tctx,
7025 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7026 "");
7029 return true;
7032 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7033 void *private_data)
7035 struct test_spoolss_context *ctx =
7036 talloc_get_type_abort(private_data, struct test_spoolss_context);
7037 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7038 int i;
7039 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7040 struct dcerpc_binding_handle *b = p->binding_handle;
7041 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7043 for (i=0;i<ARRAY_SIZE(levels);i++) {
7045 uint32_t count;
7046 union spoolss_DriverInfo *info;
7048 torture_assert(tctx,
7049 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7050 "failed to enumerate drivers");
7052 if (!info) {
7053 torture_comment(tctx, "No printer drivers returned\n");
7054 break;
7058 return true;
7061 static bool test_DeletePrinter(struct torture_context *tctx,
7062 struct dcerpc_binding_handle *b,
7063 struct policy_handle *handle)
7065 struct spoolss_DeletePrinter r;
7067 torture_comment(tctx, "Testing DeletePrinter\n");
7069 r.in.handle = handle;
7071 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7072 "failed to delete printer");
7073 torture_assert_werr_ok(tctx, r.out.result,
7074 "failed to delete printer");
7076 return true;
7079 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7080 struct dcerpc_binding_handle *b,
7081 uint32_t flags,
7082 uint32_t level,
7083 const char *name,
7084 bool *found)
7086 struct spoolss_EnumPrinters e;
7087 uint32_t count;
7088 union spoolss_PrinterInfo *info;
7089 uint32_t needed;
7090 int i;
7092 *found = false;
7094 e.in.flags = flags;
7095 e.in.server = NULL;
7096 e.in.level = level;
7097 e.in.buffer = NULL;
7098 e.in.offered = 0;
7099 e.out.count = &count;
7100 e.out.info = &info;
7101 e.out.needed = &needed;
7103 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7104 "failed to enum printers");
7106 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7107 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7108 e.in.buffer = &blob;
7109 e.in.offered = needed;
7111 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7112 "failed to enum printers");
7115 torture_assert_werr_ok(tctx, e.out.result,
7116 "failed to enum printers");
7118 for (i=0; i < count; i++) {
7120 const char *current = NULL;
7121 const char *q;
7123 switch (level) {
7124 case 1:
7125 current = info[i].info1.name;
7126 break;
7129 if (strequal(current, name)) {
7130 *found = true;
7131 break;
7134 q = strrchr(current, '\\');
7135 if (q) {
7136 if (!e.in.server) {
7137 torture_warning(tctx,
7138 "server returns printername %s incl. servername although we did not set servername", current);
7140 q++;
7141 if (strequal(q, name)) {
7142 *found = true;
7143 break;
7148 return true;
7151 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7152 struct dcerpc_pipe *p,
7153 const char *printername,
7154 bool ex)
7156 WERROR result;
7157 struct spoolss_AddPrinter r;
7158 struct spoolss_AddPrinterEx rex;
7159 struct spoolss_SetPrinterInfoCtr info_ctr;
7160 struct spoolss_SetPrinterInfo1 info1;
7161 struct spoolss_DevmodeContainer devmode_ctr;
7162 struct sec_desc_buf secdesc_ctr;
7163 struct spoolss_UserLevelCtr userlevel_ctr;
7164 struct policy_handle handle;
7165 bool found = false;
7166 struct dcerpc_binding_handle *b = p->binding_handle;
7168 ZERO_STRUCT(devmode_ctr);
7169 ZERO_STRUCT(secdesc_ctr);
7170 ZERO_STRUCT(userlevel_ctr);
7171 ZERO_STRUCT(info1);
7173 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7174 ex ? "Ex":"", printername);
7176 /* try to add printer to wellknown printer list (level 1) */
7178 userlevel_ctr.level = 1;
7180 info_ctr.info.info1 = &info1;
7181 info_ctr.level = 1;
7183 rex.in.server = NULL;
7184 rex.in.info_ctr = &info_ctr;
7185 rex.in.devmode_ctr = &devmode_ctr;
7186 rex.in.secdesc_ctr = &secdesc_ctr;
7187 rex.in.userlevel_ctr = &userlevel_ctr;
7188 rex.out.handle = &handle;
7190 r.in.server = NULL;
7191 r.in.info_ctr = &info_ctr;
7192 r.in.devmode_ctr = &devmode_ctr;
7193 r.in.secdesc_ctr = &secdesc_ctr;
7194 r.out.handle = &handle;
7196 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7197 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7198 "failed to add printer");
7199 result = ex ? rex.out.result : r.out.result;
7200 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7201 "unexpected result code");
7203 info1.name = printername;
7204 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7206 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7207 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7208 "failed to add printer");
7209 result = ex ? rex.out.result : r.out.result;
7210 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7211 "unexpected result code");
7213 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7214 better do a real check to see the printer is really there */
7216 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7217 PRINTER_ENUM_NETWORK, 1,
7218 printername,
7219 &found),
7220 "failed to enum printers");
7222 torture_assert(tctx, found, "failed to find newly added printer");
7224 info1.flags = 0;
7226 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7227 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7228 "failed to add printer");
7229 result = ex ? rex.out.result : r.out.result;
7230 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7231 "unexpected result code");
7233 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7234 better do a real check to see the printer has really been removed
7235 from the well known printer list */
7237 found = false;
7239 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7240 PRINTER_ENUM_NETWORK, 1,
7241 printername,
7242 &found),
7243 "failed to enum printers");
7244 #if 0
7245 torture_assert(tctx, !found, "printer still in well known printer list");
7246 #endif
7247 return true;
7250 static bool test_AddPrinter_normal(struct torture_context *tctx,
7251 struct dcerpc_pipe *p,
7252 struct policy_handle *handle_p,
7253 const char *printername,
7254 const char *drivername,
7255 const char *portname,
7256 struct spoolss_DeviceMode *devmode,
7257 bool ex)
7259 WERROR result;
7260 struct spoolss_AddPrinter r;
7261 struct spoolss_AddPrinterEx rex;
7262 struct spoolss_SetPrinterInfoCtr info_ctr;
7263 struct spoolss_SetPrinterInfo2 info2;
7264 struct spoolss_DevmodeContainer devmode_ctr;
7265 struct sec_desc_buf secdesc_ctr;
7266 struct spoolss_UserLevelCtr userlevel_ctr;
7267 struct policy_handle handle;
7268 bool found = false;
7269 bool existing_printer_deleted = false;
7270 struct dcerpc_binding_handle *b = p->binding_handle;
7272 ZERO_STRUCT(devmode_ctr);
7273 ZERO_STRUCT(secdesc_ctr);
7274 ZERO_STRUCT(userlevel_ctr);
7276 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7277 ex ? "Ex":"", printername);
7279 devmode_ctr.devmode = devmode;
7281 userlevel_ctr.level = 1;
7283 rex.in.server = NULL;
7284 rex.in.info_ctr = &info_ctr;
7285 rex.in.devmode_ctr = &devmode_ctr;
7286 rex.in.secdesc_ctr = &secdesc_ctr;
7287 rex.in.userlevel_ctr = &userlevel_ctr;
7288 rex.out.handle = &handle;
7290 r.in.server = NULL;
7291 r.in.info_ctr = &info_ctr;
7292 r.in.devmode_ctr = &devmode_ctr;
7293 r.in.secdesc_ctr = &secdesc_ctr;
7294 r.out.handle = &handle;
7296 again:
7298 /* try to add printer to printer list (level 2) */
7300 ZERO_STRUCT(info2);
7302 info_ctr.info.info2 = &info2;
7303 info_ctr.level = 2;
7305 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7306 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7307 "failed to add printer");
7308 result = ex ? rex.out.result : r.out.result;
7309 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7310 "unexpected result code");
7312 info2.printername = printername;
7314 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7315 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7316 "failed to add printer");
7317 result = ex ? rex.out.result : r.out.result;
7319 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7320 struct policy_handle printer_handle;
7322 if (existing_printer_deleted) {
7323 torture_fail(tctx, "already deleted printer still existing?");
7326 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7327 "failed to open printer handle");
7329 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7330 "failed to delete printer");
7332 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7333 "failed to close server handle");
7335 existing_printer_deleted = true;
7337 goto again;
7340 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7341 "unexpected result code");
7343 info2.portname = portname;
7345 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7346 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7347 "failed to add printer");
7348 result = ex ? rex.out.result : r.out.result;
7349 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7350 "unexpected result code");
7352 info2.drivername = drivername;
7354 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7355 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7356 "failed to add printer");
7357 result = ex ? rex.out.result : r.out.result;
7359 /* w2k8r2 allows to add printer w/o defining printprocessor */
7361 if (!W_ERROR_IS_OK(result)) {
7362 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7363 "unexpected result code");
7365 info2.printprocessor = "winprint";
7367 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7368 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7369 "failed to add printer");
7370 result = ex ? rex.out.result : r.out.result;
7371 torture_assert_werr_ok(tctx, result,
7372 "failed to add printer");
7375 *handle_p = handle;
7377 /* we are paranoid, really check if the printer is there now */
7379 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7380 PRINTER_ENUM_LOCAL, 1,
7381 printername,
7382 &found),
7383 "failed to enum printers");
7384 torture_assert(tctx, found, "failed to find newly added printer");
7386 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7387 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7388 "failed to add printer");
7389 result = ex ? rex.out.result : r.out.result;
7390 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7391 "unexpected result code");
7393 return true;
7396 static bool test_printer_info(struct torture_context *tctx,
7397 void *private_data)
7399 struct torture_printer_context *t =
7400 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7401 struct dcerpc_pipe *p = t->spoolss_pipe;
7402 struct dcerpc_binding_handle *b = p->binding_handle;
7404 bool ret = true;
7406 if (torture_setting_bool(tctx, "samba3", false)) {
7407 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7410 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7411 ret = false;
7414 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7415 ret = false;
7418 return ret;
7421 static bool test_EnumPrinterKey(struct torture_context *tctx,
7422 struct dcerpc_binding_handle *b,
7423 struct policy_handle *handle,
7424 const char *key_name,
7425 const char ***array)
7427 struct spoolss_EnumPrinterKey r;
7428 uint32_t needed = 0;
7429 union spoolss_KeyNames key_buffer;
7430 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7431 uint32_t _ndr_size;
7432 int i;
7434 r.in.handle = handle;
7435 r.in.key_name = key_name;
7436 r.out.key_buffer = &key_buffer;
7437 r.out.needed = &needed;
7438 r.out._ndr_size = &_ndr_size;
7440 for (i=0; i < ARRAY_SIZE(offered); i++) {
7442 if (offered[i] < 0 && needed) {
7443 if (needed <= 4) {
7444 continue;
7446 r.in.offered = needed + offered[i];
7447 } else {
7448 r.in.offered = offered[i];
7451 ZERO_STRUCT(key_buffer);
7453 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7455 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7456 "failed to call EnumPrinterKey");
7457 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7459 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7460 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7461 _ndr_size, r.in.offered/2));
7463 r.in.offered = needed;
7464 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7465 "failed to call EnumPrinterKey");
7468 if (offered[i] > 0) {
7469 torture_assert_werr_ok(tctx, r.out.result,
7470 "failed to call EnumPrinterKey");
7473 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7474 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7475 _ndr_size, r.in.offered/2));
7477 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7478 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7480 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7481 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7483 if (key_buffer.string_array) {
7484 uint32_t calc_needed = 0;
7485 int s;
7486 for (s=0; key_buffer.string_array[s]; s++) {
7487 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7489 if (!key_buffer.string_array[0]) {
7490 calc_needed += 2;
7492 calc_needed += 2;
7494 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7495 "EnumPrinterKey unexpected size");
7499 if (array) {
7500 *array = key_buffer.string_array;
7503 return true;
7506 bool test_printer_all_keys(struct torture_context *tctx,
7507 struct dcerpc_binding_handle *b,
7508 struct policy_handle *handle)
7510 const char **key_array = NULL;
7511 int i;
7513 torture_comment(tctx, "Testing Printer Keys\n");
7515 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7516 "failed to call test_EnumPrinterKey");
7518 for (i=0; key_array && key_array[i]; i++) {
7519 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7520 "failed to call test_EnumPrinterKey");
7522 for (i=0; key_array && key_array[i]; i++) {
7523 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7524 "failed to call test_EnumPrinterDataEx");
7527 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7529 return true;
7532 static bool test_openprinter_wrap(struct torture_context *tctx,
7533 void *private_data)
7535 struct torture_printer_context *t =
7536 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7537 struct dcerpc_pipe *p = t->spoolss_pipe;
7538 struct dcerpc_binding_handle *b = p->binding_handle;
7539 const char *printername = t->info2.printername;
7541 return test_openprinter(tctx, b, printername);
7544 static bool test_csetprinter(struct torture_context *tctx,
7545 void *private_data)
7547 struct torture_printer_context *t =
7548 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7549 struct dcerpc_pipe *p = t->spoolss_pipe;
7551 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7552 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7553 const char *portname = t->info2.portname;
7555 union spoolss_PrinterInfo info;
7556 struct policy_handle new_handle, new_handle2;
7557 struct dcerpc_binding_handle *b = p->binding_handle;
7559 torture_comment(tctx, "Testing c_setprinter\n");
7561 torture_assert(tctx,
7562 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7563 "failed to get level 0 printer info");
7564 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7565 info.info0.c_setprinter);
7567 /* check if c_setprinter on 1st handle increases after a printer has
7568 * been added */
7570 torture_assert(tctx,
7571 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7572 "failed to add new printer");
7573 torture_assert(tctx,
7574 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7575 "failed to get level 0 printer info");
7576 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7577 info.info0.c_setprinter);
7579 /* check if c_setprinter on new handle increases after a printer has
7580 * been added */
7582 torture_assert(tctx,
7583 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7584 "failed to get level 0 printer info");
7585 torture_comment(tctx, "csetprinter on created handle: %d\n",
7586 info.info0.c_setprinter);
7588 /* open the new printer and check if c_setprinter increases */
7590 torture_assert(tctx,
7591 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7592 "failed to open created printer");
7593 torture_assert(tctx,
7594 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7595 "failed to get level 0 printer info");
7596 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7597 info.info0.c_setprinter);
7599 /* cleanup */
7601 torture_assert(tctx,
7602 test_ClosePrinter(tctx, b, &new_handle2),
7603 "failed to close printer");
7604 torture_assert(tctx,
7605 test_DeletePrinter(tctx, b, &new_handle),
7606 "failed to delete new printer");
7608 return true;
7611 static bool compose_local_driver_directory(struct torture_context *tctx,
7612 const char *environment,
7613 const char *local_dir,
7614 const char **path)
7616 char *p;
7618 p = strrchr(local_dir, '/');
7619 if (!p) {
7620 return NULL;
7622 p++;
7624 if (strequal(environment, "Windows x64")) {
7625 if (!strequal(p, "x64")) {
7626 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7628 } else if (strequal(environment, "Windows NT x86")) {
7629 if (!strequal(p, "i386")) {
7630 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7632 } else {
7633 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7636 return true;
7639 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7640 const char *devicename)
7642 struct spoolss_DeviceMode *r;
7644 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7645 if (r == NULL) {
7646 return NULL;
7649 r->devicename = talloc_strdup(r, devicename);
7650 r->specversion = DMSPEC_NT4_AND_ABOVE;
7651 r->driverversion = 0x0600;
7652 r->size = 0x00dc;
7653 r->__driverextra_length = 0;
7654 r->fields = DEVMODE_FORMNAME |
7655 DEVMODE_TTOPTION |
7656 DEVMODE_PRINTQUALITY |
7657 DEVMODE_DEFAULTSOURCE |
7658 DEVMODE_COPIES |
7659 DEVMODE_SCALE |
7660 DEVMODE_PAPERSIZE |
7661 DEVMODE_ORIENTATION;
7662 r->orientation = DMORIENT_PORTRAIT;
7663 r->papersize = DMPAPER_LETTER;
7664 r->paperlength = 0;
7665 r->paperwidth = 0;
7666 r->scale = 100;
7667 r->copies = 55;
7668 r->defaultsource = DMBIN_FORMSOURCE;
7669 r->printquality = DMRES_HIGH;
7670 r->color = DMRES_MONOCHROME;
7671 r->duplex = DMDUP_SIMPLEX;
7672 r->yresolution = 0;
7673 r->ttoption = DMTT_SUBDEV;
7674 r->collate = DMCOLLATE_FALSE;
7675 r->formname = talloc_strdup(r, "Letter");
7677 return r;
7680 static bool test_architecture_buffer(struct torture_context *tctx,
7681 void *private_data)
7683 struct test_spoolss_context *ctx =
7684 talloc_get_type_abort(private_data, struct test_spoolss_context);
7686 struct spoolss_OpenPrinterEx r;
7687 struct spoolss_UserLevel1 u1;
7688 struct policy_handle handle;
7689 uint32_t architectures[] = {
7690 PROCESSOR_ARCHITECTURE_INTEL,
7691 PROCESSOR_ARCHITECTURE_IA64,
7692 PROCESSOR_ARCHITECTURE_AMD64
7694 uint32_t needed[3];
7695 int i;
7696 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7697 struct dcerpc_binding_handle *b = p->binding_handle;
7699 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7701 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7703 u1.size = 0;
7704 u1.client = NULL;
7705 u1.user = NULL;
7706 u1.build = 0;
7707 u1.major = 3;
7708 u1.minor = 0;
7709 u1.processor = architectures[i];
7711 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7712 r.in.datatype = NULL;
7713 r.in.devmode_ctr.devmode= NULL;
7714 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7715 r.in.userlevel_ctr.level = 1;
7716 r.in.userlevel_ctr.user_info.level1 = &u1;
7717 r.out.handle = &handle;
7719 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7720 torture_assert_werr_ok(tctx, r.out.result, "");
7723 struct spoolss_EnumPrinters e;
7724 uint32_t count;
7725 union spoolss_PrinterInfo *info;
7727 e.in.flags = PRINTER_ENUM_LOCAL;
7728 e.in.server = NULL;
7729 e.in.level = 2;
7730 e.in.buffer = NULL;
7731 e.in.offered = 0;
7732 e.out.count = &count;
7733 e.out.info = &info;
7734 e.out.needed = &needed[i];
7736 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7737 #if 0
7738 torture_comment(tctx, "needed was %d\n", needed[i]);
7739 #endif
7742 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7745 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7746 if (needed[i-1] != needed[i]) {
7747 torture_fail(tctx,
7748 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7749 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7753 return true;
7756 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7757 void *private_data)
7759 struct test_spoolss_context *ctx =
7760 talloc_get_type_abort(private_data, struct test_spoolss_context);
7761 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7762 struct dcerpc_binding_handle *b = p->binding_handle;
7764 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7767 static bool test_PrintServer_Forms(struct torture_context *tctx,
7768 void *private_data)
7770 struct test_spoolss_context *ctx =
7771 talloc_get_type_abort(private_data, struct test_spoolss_context);
7772 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7773 struct dcerpc_binding_handle *b = p->binding_handle;
7775 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7778 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7779 void *private_data)
7781 struct test_spoolss_context *ctx =
7782 talloc_get_type_abort(private_data, struct test_spoolss_context);
7783 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7784 struct dcerpc_binding_handle *b = p->binding_handle;
7786 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7789 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7791 NTSTATUS status;
7793 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7795 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7797 torture_assert(tctx,
7798 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7799 "failed to open printserver");
7800 torture_assert(tctx,
7801 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7802 "failed to get environment");
7804 return true;
7807 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7809 struct test_spoolss_context *t;
7811 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7813 return torture_rpc_spoolss_setup_common(tctx, t);
7816 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7818 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7820 return true;
7823 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7825 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7826 bool ret;
7828 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7829 talloc_free(t);
7831 return ret;
7834 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7836 struct dcerpc_pipe *p;
7837 struct dcerpc_binding_handle *b;
7838 const char *server_name_slash;
7839 const char *driver_name;
7840 const char *printer_name;
7841 const char *port_name;
7843 torture_assert_ntstatus_ok(tctx,
7844 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7845 "Error connecting to server");
7847 p = t->spoolss_pipe;
7848 b = p->binding_handle;
7849 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7851 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7852 t->driver.info8.driver_name = TORTURE_DRIVER;
7853 t->driver.info8.driver_path = "pscript5.dll";
7854 t->driver.info8.data_file = "cups6.ppd";
7855 t->driver.info8.config_file = "ps5ui.dll";
7856 t->driver.info8.help_file = "pscript.hlp";
7857 t->driver.info8.default_datatype = "RAW";
7858 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7859 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7860 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7861 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7862 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7863 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7864 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7865 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7866 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7867 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7869 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7871 t->info2.portname = "LPT1:";
7873 printer_name = t->info2.printername;
7874 port_name = t->info2.portname;
7876 torture_assert(tctx,
7877 fillup_printserver_info(tctx, p, &t->driver),
7878 "failed to fillup printserver info");
7880 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7882 torture_assert(tctx,
7883 compose_local_driver_directory(tctx, t->driver.remote.environment,
7884 t->driver.local.driver_directory,
7885 &t->driver.local.driver_directory),
7886 "failed to compose local driver directory");
7888 t->info2.drivername = "Microsoft XPS Document Writer";
7890 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7891 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7892 t->info2.drivername, t->driver.remote.environment);
7893 t->have_driver = true;
7894 goto try_add;
7897 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7898 t->info2.drivername, t->driver.remote.environment);
7900 t->info2.drivername = "Microsoft XPS Document Writer v4";
7902 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7903 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
7904 t->info2.drivername, t->driver.remote.environment);
7905 t->have_driver = true;
7906 goto try_add;
7909 torture_comment(tctx, "trying to upload own driver\n");
7911 if (!directory_exist(t->driver.local.driver_directory)) {
7912 torture_warning(tctx, "no local driver is available!");
7913 t->have_driver = false;
7914 goto try_add;
7917 torture_assert(tctx,
7918 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7919 "failed to upload printer driver");
7921 torture_assert(tctx,
7922 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7923 "failed to add driver");
7925 t->added_driver = true;
7926 t->have_driver = true;
7928 try_add:
7929 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7931 if (t->wellknown) {
7932 torture_assert(tctx,
7933 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7934 "failed to add wellknown printer");
7935 } else {
7936 torture_assert(tctx,
7937 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7938 "failed to add printer");
7941 return true;
7944 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7946 struct torture_printer_context *t;
7948 *data = t = talloc_zero(tctx, struct torture_printer_context);
7950 t->ex = false;
7951 t->wellknown = false;
7952 t->info2.printername = TORTURE_PRINTER;
7953 t->devmode = NULL;
7955 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7958 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7960 struct torture_printer_context *t;
7962 *data = t = talloc_zero(tctx, struct torture_printer_context);
7964 t->ex = true;
7965 t->wellknown = false;
7966 t->info2.printername = TORTURE_PRINTER_EX;
7967 t->devmode = NULL;
7969 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7972 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7974 struct torture_printer_context *t;
7976 *data = t = talloc_zero(tctx, struct torture_printer_context);
7978 t->ex = false;
7979 t->wellknown = true;
7980 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7981 t->devmode = NULL;
7983 /* FIXME */
7984 if (t->wellknown) {
7985 torture_skip(tctx, "skipping AddPrinter level 1");
7988 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7991 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7993 struct torture_printer_context *t;
7995 *data = t = talloc_zero(tctx, struct torture_printer_context);
7997 t->ex = true;
7998 t->wellknown = true;
7999 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8000 t->devmode = NULL;
8002 /* FIXME */
8003 if (t->wellknown) {
8004 torture_skip(tctx, "skipping AddPrinterEx level 1");
8007 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8010 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8012 struct torture_printer_context *t;
8014 *data = t = talloc_zero(tctx, struct torture_printer_context);
8016 t->ex = true;
8017 t->wellknown = false;
8018 t->info2.printername = TORTURE_PRINTER_EX;
8019 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8021 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8024 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8026 bool found = false;
8027 struct dcerpc_pipe *p = t->spoolss_pipe;
8028 struct dcerpc_binding_handle *b;
8029 const char *printer_name = t->info2.printername;
8031 if (t->added_driver) {
8032 torture_assert(tctx,
8033 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8034 "failed to remove printer driver");
8037 if (p && !t->wellknown) {
8038 b = p->binding_handle;
8040 torture_assert(tctx,
8041 test_DeletePrinter(tctx, b, &t->handle),
8042 "failed to delete printer");
8044 torture_assert(tctx,
8045 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8046 printer_name, &found),
8047 "failed to enumerate printers");
8049 torture_assert(tctx, !found, "deleted printer still there");
8052 return true;
8055 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8057 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8058 bool ret;
8060 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8061 talloc_free(t);
8063 return ret;
8066 static bool test_print_test(struct torture_context *tctx,
8067 void *private_data)
8069 struct torture_printer_context *t =
8070 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8071 struct dcerpc_pipe *p = t->spoolss_pipe;
8072 struct dcerpc_binding_handle *b = p->binding_handle;
8074 torture_assert(tctx,
8075 test_PausePrinter(tctx, b, &t->handle),
8076 "failed to pause printer");
8078 torture_assert(tctx,
8079 test_DoPrintTest(tctx, b, &t->handle),
8080 "failed to do print test");
8082 torture_assert(tctx,
8083 test_ResumePrinter(tctx, b, &t->handle),
8084 "failed to resume printer");
8086 return true;
8089 static bool test_print_test_extended(struct torture_context *tctx,
8090 void *private_data)
8092 struct torture_printer_context *t =
8093 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8094 struct dcerpc_pipe *p = t->spoolss_pipe;
8095 struct dcerpc_binding_handle *b = p->binding_handle;
8096 bool ret = true;
8098 torture_assert(tctx,
8099 test_PausePrinter(tctx, b, &t->handle),
8100 "failed to pause printer");
8102 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8103 if (ret == false) {
8104 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8105 if (torture_setting_bool(tctx, "samba3", false)) {
8106 torture_comment(tctx, "non-critical for samba3\n");
8107 ret = true;
8108 tctx->last_result = TORTURE_SKIP;
8112 torture_assert(tctx,
8113 test_ResumePrinter(tctx, b, &t->handle),
8114 "failed to resume printer");
8116 return ret;
8119 static bool test_print_test_properties(struct torture_context *tctx,
8120 void *private_data)
8122 struct torture_printer_context *t =
8123 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8124 struct dcerpc_pipe *p = t->spoolss_pipe;
8125 struct dcerpc_binding_handle *b = p->binding_handle;
8127 if (torture_setting_bool(tctx, "samba3", false)) {
8128 torture_skip(tctx, "skip printer job property tests against samba");
8131 torture_assert(tctx,
8132 test_PausePrinter(tctx, b, &t->handle),
8133 "failed to pause printer");
8135 torture_assert(tctx,
8136 test_DoPrintTest_properties(tctx, b, &t->handle),
8137 "failed to test print job properties");
8139 torture_assert(tctx,
8140 test_ResumePrinter(tctx, b, &t->handle),
8141 "failed to resume printer");
8143 return true;
8146 /* use smbd file IO to spool a print job */
8147 static bool test_print_test_smbd(struct torture_context *tctx,
8148 void *private_data)
8150 struct torture_printer_context *t =
8151 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8152 struct dcerpc_pipe *p = t->spoolss_pipe;
8153 struct dcerpc_binding_handle *b = p->binding_handle;
8154 NTSTATUS status;
8155 uint32_t count;
8156 union spoolss_JobInfo *info = NULL;
8157 int i;
8159 struct smb2_tree *tree;
8160 struct smb2_handle job_h;
8161 struct cli_credentials *credentials = cmdline_credentials;
8162 struct smbcli_options options;
8163 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8165 * Do not test against the dynamically added printers, printing via
8166 * smbd means that a different spoolss process may handle the
8167 * OpenPrinter request to the one that handled the AddPrinter request.
8168 * This currently leads to an ugly race condition where one process
8169 * sees the new printer and one doesn't.
8171 const char *share = TORTURE_PRINTER_STATIC1;
8173 torture_comment(tctx, "Testing smbd job spooling\n");
8174 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8176 status = smb2_connect_ext(mem_ctx,
8177 torture_setting_string(tctx, "host", NULL),
8178 lpcfg_smb_ports(tctx->lp_ctx),
8179 share,
8180 lpcfg_resolve_context(tctx->lp_ctx),
8181 credentials,
8183 &tree,
8184 tctx->ev,
8185 &options,
8186 lpcfg_socket_options(tctx->lp_ctx),
8187 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8188 if (!NT_STATUS_IS_OK(status)) {
8189 printf("Failed to connect to SMB2 printer %s - %s\n",
8190 share, nt_errstr(status));
8191 return false;
8194 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8195 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8197 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8198 sizeof("exciting print job data"));
8199 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8201 /* check back end spoolss job was created */
8202 torture_assert(tctx,
8203 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8204 "EnumJobs level 1 failed");
8206 for (i = 0; i < count; i++) {
8207 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8208 break;
8211 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8213 status = smb2_util_close(tree, job_h);
8214 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8216 /* disconnect from printer share */
8217 talloc_free(mem_ctx);
8219 return true;
8222 static bool test_printer_sd(struct torture_context *tctx,
8223 void *private_data)
8225 struct torture_printer_context *t =
8226 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8227 struct dcerpc_pipe *p = t->spoolss_pipe;
8228 struct dcerpc_binding_handle *b = p->binding_handle;
8230 torture_assert(tctx,
8231 test_PrinterInfo_SD(tctx, b, &t->handle),
8232 "failed to test security descriptors");
8234 return true;
8237 static bool test_printer_dm(struct torture_context *tctx,
8238 void *private_data)
8240 struct torture_printer_context *t =
8241 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8242 struct dcerpc_pipe *p = t->spoolss_pipe;
8244 torture_assert(tctx,
8245 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8246 "failed to test devicemodes");
8248 return true;
8251 static bool test_printer_info_winreg(struct torture_context *tctx,
8252 void *private_data)
8254 struct torture_printer_context *t =
8255 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8256 struct dcerpc_pipe *p = t->spoolss_pipe;
8258 torture_assert(tctx,
8259 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8260 "failed to test printer info winreg");
8262 return true;
8265 static bool test_printer_change_id(struct torture_context *tctx,
8266 void *private_data)
8268 struct torture_printer_context *t =
8269 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8270 struct dcerpc_pipe *p = t->spoolss_pipe;
8272 torture_assert(tctx,
8273 test_ChangeID(tctx, p, &t->handle),
8274 "failed to test change id");
8276 return true;
8279 static bool test_printer_keys(struct torture_context *tctx,
8280 void *private_data)
8282 struct torture_printer_context *t =
8283 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8284 struct dcerpc_pipe *p = t->spoolss_pipe;
8285 struct dcerpc_binding_handle *b = p->binding_handle;
8287 torture_assert(tctx,
8288 test_printer_all_keys(tctx, b, &t->handle),
8289 "failed to test printer keys");
8291 return true;
8294 static bool test_printer_data_consistency(struct torture_context *tctx,
8295 void *private_data)
8297 struct torture_printer_context *t =
8298 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8299 struct dcerpc_pipe *p = t->spoolss_pipe;
8301 torture_assert(tctx,
8302 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8303 "failed to test printer data consistency");
8305 return true;
8308 static bool test_printer_data_keys(struct torture_context *tctx,
8309 void *private_data)
8311 struct torture_printer_context *t =
8312 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8313 struct dcerpc_pipe *p = t->spoolss_pipe;
8315 torture_assert(tctx,
8316 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8317 "failed to test printer data keys");
8319 return true;
8322 static bool test_printer_data_values(struct torture_context *tctx,
8323 void *private_data)
8325 struct torture_printer_context *t =
8326 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8327 struct dcerpc_pipe *p = t->spoolss_pipe;
8329 torture_assert(tctx,
8330 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8331 "failed to test printer data values");
8333 return true;
8336 static bool test_printer_data_set(struct torture_context *tctx,
8337 void *private_data)
8339 struct torture_printer_context *t =
8340 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8341 struct dcerpc_pipe *p = t->spoolss_pipe;
8343 torture_assert(tctx,
8344 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8345 "failed to test printer data set");
8347 return true;
8350 static bool test_printer_data_winreg(struct torture_context *tctx,
8351 void *private_data)
8353 struct torture_printer_context *t =
8354 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8355 struct dcerpc_pipe *p = t->spoolss_pipe;
8357 torture_assert(tctx,
8358 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8359 "failed to test printer data winreg");
8361 return true;
8364 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8365 void *private_data)
8367 struct torture_printer_context *t =
8368 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8369 struct dcerpc_pipe *p = t->spoolss_pipe;
8371 torture_assert(tctx,
8372 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8373 "failed to test printer data winreg dsspooler");
8375 return true;
8378 static bool test_printer_ic(struct torture_context *tctx,
8379 void *private_data)
8381 struct torture_printer_context *t =
8382 talloc_get_type_abort(private_data,
8383 struct torture_printer_context);
8384 struct dcerpc_pipe *p = t->spoolss_pipe;
8385 struct dcerpc_binding_handle *b = p->binding_handle;
8386 struct policy_handle gdi_handle;
8388 if (torture_setting_bool(tctx, "samba3", false)) {
8389 torture_skip(tctx, "skip printer information context tests against samba");
8393 struct spoolss_CreatePrinterIC r;
8394 struct spoolss_DevmodeContainer devmode_ctr;
8396 ZERO_STRUCT(devmode_ctr);
8398 r.in.handle = &t->handle;
8399 r.in.devmode_ctr = &devmode_ctr;
8400 r.out.gdi_handle = &gdi_handle;
8402 torture_assert_ntstatus_ok(tctx,
8403 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8404 "CreatePrinterIC failed");
8405 torture_assert_werr_ok(tctx, r.out.result,
8406 "CreatePrinterIC failed");
8410 struct spoolss_PlayGDIScriptOnPrinterIC r;
8411 DATA_BLOB in,out;
8412 int i;
8413 uint32_t num_fonts = 0;
8415 in = data_blob_string_const("");
8417 r.in.gdi_handle = &gdi_handle;
8418 r.in.pIn = in.data;
8419 r.in.cIn = in.length;
8420 r.in.ul = 0;
8422 for (i = 0; i < 4; i++) {
8424 out = data_blob_talloc_zero(tctx, i);
8426 r.in.cOut = out.length;
8427 r.out.pOut = out.data;
8429 torture_assert_ntstatus_ok(tctx,
8430 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8431 "PlayGDIScriptOnPrinterIC failed");
8432 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8433 "PlayGDIScriptOnPrinterIC failed");
8436 out = data_blob_talloc_zero(tctx, 4);
8438 r.in.cOut = out.length;
8439 r.out.pOut = out.data;
8441 torture_assert_ntstatus_ok(tctx,
8442 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8443 "PlayGDIScriptOnPrinterIC failed");
8444 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8445 "PlayGDIScriptOnPrinterIC failed");
8447 /* now we should have the required length, so retry with a
8448 * buffer which is large enough to carry all font ids */
8450 num_fonts = IVAL(r.out.pOut, 0);
8452 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8454 out = data_blob_talloc_zero(tctx,
8455 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8457 r.in.cOut = out.length;
8458 r.out.pOut = out.data;
8460 torture_assert_ntstatus_ok(tctx,
8461 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8462 "PlayGDIScriptOnPrinterIC failed");
8463 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8464 "PlayGDIScriptOnPrinterIC failed");
8469 struct spoolss_DeletePrinterIC r;
8471 r.in.gdi_handle = &gdi_handle;
8472 r.out.gdi_handle = &gdi_handle;
8474 torture_assert_ntstatus_ok(tctx,
8475 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8476 "DeletePrinterIC failed");
8477 torture_assert_werr_ok(tctx, r.out.result,
8478 "DeletePrinterIC failed");
8482 return true;
8485 static bool test_printer_bidi(struct torture_context *tctx,
8486 void *private_data)
8488 struct torture_printer_context *t =
8489 talloc_get_type_abort(private_data,
8490 struct torture_printer_context);
8491 struct dcerpc_pipe *p = t->spoolss_pipe;
8492 struct dcerpc_binding_handle *b = p->binding_handle;
8493 struct spoolss_RpcSendRecvBidiData r;
8494 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8495 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8497 if (torture_setting_bool(tctx, "samba3", false)) {
8498 torture_skip(tctx, "skip printer bidirectional tests against samba");
8501 ZERO_STRUCT(bidi_req);
8503 r.in.hPrinter = t->handle;
8504 r.in.pAction = "foobar";
8505 r.in.pReqData = &bidi_req;
8506 r.out.ppRespData = &bidi_rep;
8508 torture_assert_ntstatus_ok(tctx,
8509 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8510 "RpcSendRecvBidiData failed");
8511 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8512 "RpcSendRecvBidiData failed");
8514 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8515 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8518 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8520 torture_assert_ntstatus_ok(tctx,
8521 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8522 "RpcSendRecvBidiData failed");
8523 torture_assert_werr_ok(tctx, r.out.result,
8524 "RpcSendRecvBidiData failed");
8526 return true;
8529 static bool test_printer_set_publish(struct torture_context *tctx,
8530 struct dcerpc_binding_handle *b,
8531 struct policy_handle *handle)
8533 union spoolss_PrinterInfo info;
8534 struct spoolss_SetPrinterInfo7 info7;
8535 struct spoolss_SetPrinterInfoCtr info_ctr;
8536 struct spoolss_DevmodeContainer devmode_ctr;
8537 struct sec_desc_buf secdesc_ctr;
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 if (info.info7.action & DSPRINT_PENDING) {
8562 torture_comment(tctx, "publish is pending\n");
8563 torture_assert_int_equal(tctx,
8564 info.info7.action,
8565 (DSPRINT_PENDING | DSPRINT_PUBLISH),
8566 "info7 publish flag not set");
8567 } else {
8568 struct GUID guid;
8569 torture_assert_int_equal(tctx,
8570 info.info7.action,
8571 DSPRINT_PUBLISH,
8572 "info7 publish flag not set");
8573 torture_assert_ntstatus_ok(tctx,
8574 GUID_from_string(info.info7.guid,
8575 &guid),
8576 "invalid published printer GUID");
8579 return true;
8582 static bool test_printer_set_unpublish(struct torture_context *tctx,
8583 struct dcerpc_binding_handle *b,
8584 struct policy_handle *handle)
8586 union spoolss_PrinterInfo info;
8587 struct spoolss_SetPrinterInfo7 info7;
8588 struct spoolss_SetPrinterInfoCtr info_ctr;
8589 struct spoolss_DevmodeContainer devmode_ctr;
8590 struct sec_desc_buf secdesc_ctr;
8592 info7.action = DSPRINT_UNPUBLISH;
8593 info7.guid = "";
8595 ZERO_STRUCT(info_ctr);
8596 ZERO_STRUCT(devmode_ctr);
8597 ZERO_STRUCT(secdesc_ctr);
8598 info_ctr.level = 7;
8599 info_ctr.info.info7 = &info7;
8601 torture_assert(tctx,
8602 test_SetPrinter(tctx, b, handle, &info_ctr,
8603 &devmode_ctr, &secdesc_ctr, 0), "");
8605 torture_assert(tctx,
8606 test_GetPrinter_level(tctx, b, handle, 2, &info),
8607 "");
8608 torture_assert(tctx,
8609 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8610 "info2 publish flag still set");
8611 torture_assert(tctx,
8612 test_GetPrinter_level(tctx, b, handle, 7, &info),
8613 "");
8615 if (info.info7.action & DSPRINT_PENDING) {
8616 struct GUID guid;
8617 torture_comment(tctx, "unpublish is pending\n");
8618 torture_assert_int_equal(tctx,
8619 info.info7.action,
8620 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
8621 "info7 unpublish flag not set");
8622 torture_assert_ntstatus_ok(tctx,
8623 GUID_from_string(info.info7.guid,
8624 &guid),
8625 "invalid printer GUID");
8626 } else {
8627 torture_assert_int_equal(tctx,
8628 info.info7.action, DSPRINT_UNPUBLISH,
8629 "info7 unpublish flag not set");
8632 return true;
8635 static bool test_printer_publish_toggle(struct torture_context *tctx,
8636 void *private_data)
8638 struct torture_printer_context *t =
8639 talloc_get_type_abort(private_data,
8640 struct torture_printer_context);
8641 struct dcerpc_pipe *p = t->spoolss_pipe;
8642 struct dcerpc_binding_handle *b = p->binding_handle;
8643 struct policy_handle *handle = &t->handle;
8644 union spoolss_PrinterInfo info7;
8645 union spoolss_PrinterInfo info2;
8647 /* check publish status via level 7 and level 2 */
8648 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
8649 "");
8650 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
8651 "");
8653 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
8654 torture_assert_int_equal(tctx,
8655 info7.info7.action, DSPRINT_PUBLISH,
8656 "info7 publish flag not set");
8657 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8658 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8659 } else {
8660 torture_assert_int_equal(tctx,
8661 info7.info7.action, DSPRINT_UNPUBLISH,
8662 "info7 unpublish flag not set");
8663 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8664 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8667 return true;
8670 static bool test_driver_info_winreg(struct torture_context *tctx,
8671 void *private_data)
8673 struct torture_printer_context *t =
8674 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8675 struct dcerpc_pipe *p = t->spoolss_pipe;
8676 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8678 if (!t->have_driver) {
8679 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8682 torture_assert(tctx,
8683 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8684 "failed to test driver info winreg");
8686 return true;
8689 void torture_tcase_printer(struct torture_tcase *tcase)
8691 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8692 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8693 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8694 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8695 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8696 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8697 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8698 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8699 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8700 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8701 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8702 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8703 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8704 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8705 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8706 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8707 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8708 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8709 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8710 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8711 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8712 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
8713 torture_tcase_add_simple_test(tcase, "publish_toggle",
8714 test_printer_publish_toggle);
8717 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8719 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8720 struct torture_tcase *tcase;
8722 tcase = torture_suite_add_tcase(suite, "addprinter");
8724 torture_tcase_set_fixture(tcase,
8725 torture_rpc_spoolss_printer_setup,
8726 torture_rpc_spoolss_printer_teardown);
8728 torture_tcase_printer(tcase);
8730 tcase = torture_suite_add_tcase(suite, "addprinterex");
8732 torture_tcase_set_fixture(tcase,
8733 torture_rpc_spoolss_printerex_setup,
8734 torture_rpc_spoolss_printer_teardown);
8736 torture_tcase_printer(tcase);
8738 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8740 torture_tcase_set_fixture(tcase,
8741 torture_rpc_spoolss_printerwkn_setup,
8742 torture_rpc_spoolss_printer_teardown);
8744 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8746 torture_tcase_set_fixture(tcase,
8747 torture_rpc_spoolss_printerexwkn_setup,
8748 torture_rpc_spoolss_printer_teardown);
8750 #if 0
8751 /* test is not correct */
8752 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8754 torture_tcase_set_fixture(tcase,
8755 torture_rpc_spoolss_printerdm_setup,
8756 torture_rpc_spoolss_printer_teardown);
8758 torture_tcase_printer(tcase);
8759 #endif
8760 return suite;
8763 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8765 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8766 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8768 torture_tcase_set_fixture(tcase,
8769 torture_rpc_spoolss_setup,
8770 torture_rpc_spoolss_teardown);
8772 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8773 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8774 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8775 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8776 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8777 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8778 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8779 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8780 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8781 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8782 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8783 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8784 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8785 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
8786 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8787 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8788 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8789 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8790 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8791 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8792 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8794 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8796 return suite;
8799 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8800 struct dcerpc_binding_handle *b,
8801 const char *server,
8802 const char *environment,
8803 const char **dir_p)
8805 struct spoolss_GetPrinterDriverDirectory r;
8806 uint32_t needed;
8808 r.in.server = server;
8809 r.in.environment = environment;
8810 r.in.level = 1;
8811 r.in.buffer = NULL;
8812 r.in.offered = 0;
8813 r.out.needed = &needed;
8815 torture_assert_ntstatus_ok(tctx,
8816 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8817 "failed to query driver directory");
8819 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8820 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8821 r.in.buffer = &blob;
8822 r.in.offered = needed;
8824 torture_assert_ntstatus_ok(tctx,
8825 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8826 "failed to query driver directory");
8829 torture_assert_werr_ok(tctx, r.out.result,
8830 "failed to query driver directory");
8832 if (dir_p) {
8833 *dir_p = r.out.info->info1.directory_name;
8836 return true;
8839 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8841 if (info_ctr == NULL) {
8842 return NULL;
8845 switch (info_ctr->level) {
8846 case 1:
8847 return info_ctr->info.info1->driver_name;
8848 case 2:
8849 return info_ctr->info.info2->driver_name;
8850 case 3:
8851 return info_ctr->info.info3->driver_name;
8852 case 4:
8853 return info_ctr->info.info4->driver_name;
8854 case 6:
8855 return info_ctr->info.info6->driver_name;
8856 case 8:
8857 return info_ctr->info.info8->driver_name;
8858 default:
8859 return NULL;
8863 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8865 if (info_ctr == NULL) {
8866 return NULL;
8869 switch (info_ctr->level) {
8870 case 2:
8871 return info_ctr->info.info2->architecture;
8872 case 3:
8873 return info_ctr->info.info3->architecture;
8874 case 4:
8875 return info_ctr->info.info4->architecture;
8876 case 6:
8877 return info_ctr->info.info6->architecture;
8878 case 8:
8879 return info_ctr->info.info8->architecture;
8880 default:
8881 return NULL;
8886 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8887 struct dcerpc_binding_handle *b,
8888 const char *servername,
8889 struct spoolss_AddDriverInfoCtr *info_ctr,
8890 WERROR expected_result)
8892 struct spoolss_AddPrinterDriver r;
8893 const char *drivername = get_driver_from_info(info_ctr);
8894 const char *environment = get_environment_from_info(info_ctr);
8896 r.in.servername = servername;
8897 r.in.info_ctr = info_ctr;
8899 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8900 drivername, info_ctr->level, environment);
8902 torture_assert_ntstatus_ok(tctx,
8903 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8904 "spoolss_AddPrinterDriver failed");
8905 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8906 "spoolss_AddPrinterDriver failed with unexpected result");
8908 return true;
8912 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8913 struct dcerpc_binding_handle *b,
8914 const char *servername,
8915 struct spoolss_AddDriverInfoCtr *info_ctr,
8916 uint32_t flags,
8917 WERROR expected_result)
8919 struct spoolss_AddPrinterDriverEx r;
8920 const char *drivername = get_driver_from_info(info_ctr);
8921 const char *environment = get_environment_from_info(info_ctr);
8923 r.in.servername = servername;
8924 r.in.info_ctr = info_ctr;
8925 r.in.flags = flags;
8927 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8928 drivername, info_ctr->level, environment);
8930 torture_assert_ntstatus_ok(tctx,
8931 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8932 "AddPrinterDriverEx failed");
8933 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8934 "AddPrinterDriverEx failed with unexpected result");
8936 return true;
8939 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8940 if (path && strlen(path)) {\
8941 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8944 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8945 struct dcerpc_binding_handle *b,
8946 const char *server_name,
8947 struct spoolss_AddDriverInfo8 *r,
8948 uint32_t flags,
8949 bool ex,
8950 const char *remote_driver_dir)
8952 struct spoolss_AddDriverInfoCtr info_ctr;
8953 struct spoolss_AddDriverInfo1 info1;
8955 ZERO_STRUCT(info1);
8957 info_ctr.level = 1;
8958 info_ctr.info.info1 = &info1;
8960 if (ex) {
8961 torture_assert(tctx,
8962 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8963 "failed to test AddPrinterDriverEx level 1");
8964 } else {
8965 torture_assert(tctx,
8966 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8967 "failed to test AddPrinterDriver level 1");
8970 info1.driver_name = r->driver_name;
8972 if (ex) {
8973 torture_assert(tctx,
8974 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8975 "failed to test AddPrinterDriverEx level 1");
8976 } else {
8977 torture_assert(tctx,
8978 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8979 "failed to test AddPrinterDriver level 1");
8982 return true;
8985 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8986 struct dcerpc_binding_handle *b,
8987 const char *server_name,
8988 struct spoolss_AddDriverInfo8 *r,
8989 uint32_t flags,
8990 bool ex,
8991 const char *remote_driver_dir)
8993 struct spoolss_AddDriverInfoCtr info_ctr;
8994 struct spoolss_AddDriverInfo2 info2;
8995 union spoolss_DriverInfo info;
8997 ZERO_STRUCT(info2);
8999 info_ctr.level = 2;
9000 info_ctr.info.info2 = &info2;
9002 if (ex) {
9003 torture_assert(tctx,
9004 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9005 "failed to test AddPrinterDriverEx level 2");
9006 } else {
9007 torture_assert(tctx,
9008 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9009 "failed to test AddPrinterDriver level 2");
9012 info2.driver_name = r->driver_name;
9014 if (ex) {
9015 torture_assert(tctx,
9016 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9017 "failed to test AddPrinterDriverEx level 2");
9018 } else {
9019 torture_assert(tctx,
9020 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9021 "failed to test AddPrinterDriver level 2");
9024 info2.version = r->version;
9026 if (ex) {
9027 torture_assert(tctx,
9028 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9029 "failed to test AddPrinterDriverEx level 2");
9030 } else {
9031 torture_assert(tctx,
9032 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9033 "failed to test AddPrinterDriver level 2");
9036 info2.architecture = r->architecture;
9038 if (ex) {
9039 torture_assert(tctx,
9040 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9041 "failed to test AddPrinterDriverEx level 2");
9042 } else {
9043 torture_assert(tctx,
9044 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9045 "failed to test AddPrinterDriver level 2");
9048 info2.driver_path = r->driver_path;
9050 if (ex) {
9051 torture_assert(tctx,
9052 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9053 "failed to test AddPrinterDriverEx level 2");
9054 } else {
9055 torture_assert(tctx,
9056 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9057 "failed to test AddPrinterDriver level 2");
9060 info2.data_file = r->data_file;
9062 if (ex) {
9063 torture_assert(tctx,
9064 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9065 "failed to test AddPrinterDriverEx level 2");
9066 } else {
9067 torture_assert(tctx,
9068 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9069 "failed to test AddPrinterDriver level 2");
9072 info2.config_file = r->config_file;
9074 if (ex) {
9075 torture_assert(tctx,
9076 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
9077 "failed to test AddPrinterDriverEx");
9080 if (ex) {
9081 torture_assert(tctx,
9082 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9083 "failed to test AddPrinterDriverEx level 2");
9084 } else {
9085 torture_assert(tctx,
9086 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9087 "failed to test AddPrinterDriver level 2");
9090 torture_assert(tctx,
9091 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9092 "failed to find added printer driver");
9094 if (remote_driver_dir) {
9095 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9096 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9097 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9100 return true;
9103 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9104 struct dcerpc_binding_handle *b,
9105 const char *server_name,
9106 struct spoolss_AddDriverInfo8 *r,
9107 uint32_t flags,
9108 bool ex,
9109 const char *remote_driver_dir)
9111 struct spoolss_AddDriverInfoCtr info_ctr;
9112 struct spoolss_AddDriverInfo3 info3;
9113 union spoolss_DriverInfo info;
9115 info3.driver_name = r->driver_name;
9116 info3.version = r->version;
9117 info3.architecture = r->architecture;
9118 info3.driver_path = r->driver_path;
9119 info3.data_file = r->data_file;
9120 info3.config_file = r->config_file;
9121 info3.help_file = r->help_file;
9122 info3.monitor_name = r->monitor_name;
9123 info3.default_datatype = r->default_datatype;
9124 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9125 info3.dependent_files = r->dependent_files;
9127 info_ctr.level = 3;
9128 info_ctr.info.info3 = &info3;
9130 if (ex) {
9131 torture_assert(tctx,
9132 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9133 "failed to test AddPrinterDriverEx level 3");
9134 } else {
9135 torture_assert(tctx,
9136 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9137 "failed to test AddPrinterDriver level 3");
9140 torture_assert(tctx,
9141 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
9142 "failed to find added printer driver");
9144 if (remote_driver_dir) {
9145 int i;
9146 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9147 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9148 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9149 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9150 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9151 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9155 return true;
9158 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9159 struct dcerpc_binding_handle *b,
9160 const char *server_name,
9161 struct spoolss_AddDriverInfo8 *r,
9162 uint32_t flags,
9163 bool ex,
9164 const char *remote_driver_dir)
9166 struct spoolss_AddDriverInfoCtr info_ctr;
9167 struct spoolss_AddDriverInfo4 info4;
9168 union spoolss_DriverInfo info;
9170 info4.version = r->version;
9171 info4.driver_name = r->driver_name;
9172 info4.architecture = r->architecture;
9173 info4.driver_path = r->driver_path;
9174 info4.data_file = r->data_file;
9175 info4.config_file = r->config_file;
9176 info4.help_file = r->help_file;
9177 info4.monitor_name = r->monitor_name;
9178 info4.default_datatype = r->default_datatype;
9179 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9180 info4.dependent_files = r->dependent_files;
9181 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9182 info4.previous_names = r->previous_names;
9184 info_ctr.level = 4;
9185 info_ctr.info.info4 = &info4;
9187 if (ex) {
9188 torture_assert(tctx,
9189 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9190 "failed to test AddPrinterDriverEx level 4");
9191 } else {
9192 torture_assert(tctx,
9193 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9194 "failed to test AddPrinterDriver level 4");
9197 torture_assert(tctx,
9198 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9199 "failed to find added printer driver");
9201 if (remote_driver_dir) {
9202 int i;
9203 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9204 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9205 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9206 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9207 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9208 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9212 return true;
9215 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9216 struct dcerpc_binding_handle *b,
9217 const char *server_name,
9218 struct spoolss_AddDriverInfo8 *r,
9219 uint32_t flags,
9220 bool ex,
9221 const char *remote_driver_dir)
9223 struct spoolss_AddDriverInfoCtr info_ctr;
9224 struct spoolss_AddDriverInfo6 info6;
9225 union spoolss_DriverInfo info;
9227 info6.version = r->version;
9228 info6.driver_name = r->driver_name;
9229 info6.architecture = r->architecture;
9230 info6.driver_path = r->driver_path;
9231 info6.data_file = r->data_file;
9232 info6.config_file = r->config_file;
9233 info6.help_file = r->help_file;
9234 info6.monitor_name = r->monitor_name;
9235 info6.default_datatype = r->default_datatype;
9236 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9237 info6.dependent_files = r->dependent_files;
9238 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9239 info6.previous_names = r->previous_names;
9240 info6.driver_date = r->driver_date;
9241 info6.driver_version = r->driver_version;
9242 info6.manufacturer_name = r->manufacturer_name;
9243 info6.manufacturer_url = r->manufacturer_url;
9244 info6.hardware_id = r->hardware_id;
9245 info6.provider = r->provider;
9247 info_ctr.level = 6;
9248 info_ctr.info.info6 = &info6;
9250 if (ex) {
9251 torture_assert(tctx,
9252 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9253 "failed to test AddPrinterDriverEx level 6");
9254 } else {
9255 torture_assert(tctx,
9256 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9257 "failed to test AddPrinterDriver level 6");
9260 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9262 if (!ex) {
9263 return true;
9266 torture_assert(tctx,
9267 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9268 "failed to find added printer driver");
9270 if (remote_driver_dir) {
9271 int i;
9272 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9273 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9274 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9275 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9276 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9277 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9281 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9282 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9284 return true;
9287 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9288 struct dcerpc_binding_handle *b,
9289 const char *server_name,
9290 struct spoolss_AddDriverInfo8 *r,
9291 uint32_t flags,
9292 bool ex,
9293 const char *remote_driver_dir)
9295 struct spoolss_AddDriverInfoCtr info_ctr;
9296 union spoolss_DriverInfo info;
9298 info_ctr.level = 8;
9299 info_ctr.info.info8 = r;
9301 if (ex) {
9302 torture_assert(tctx,
9303 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9304 "failed to test AddPrinterDriverEx level 8");
9305 } else {
9306 torture_assert(tctx,
9307 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9308 "failed to test AddPrinterDriver level 8");
9311 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9313 if (!ex) {
9314 return true;
9317 torture_assert(tctx,
9318 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9319 "failed to find added printer driver");
9321 if (remote_driver_dir) {
9322 int i;
9323 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9324 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9325 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9326 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9327 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9328 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9332 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9333 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9335 return true;
9338 #undef ASSERT_DRIVER_PATH
9340 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9341 struct dcerpc_binding_handle *b,
9342 const char *server,
9343 const char *driver,
9344 const char *environment,
9345 WERROR expected_result)
9347 struct spoolss_DeletePrinterDriver r;
9349 r.in.server = server;
9350 r.in.architecture = environment;
9351 r.in.driver = driver;
9353 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9355 torture_assert_ntstatus_ok(tctx,
9356 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9357 "DeletePrinterDriver failed");
9358 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9359 "DeletePrinterDriver failed with unexpected result");
9361 return true;
9364 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9365 struct dcerpc_binding_handle *b,
9366 const char *server,
9367 const char *driver,
9368 const char *environment,
9369 uint32_t delete_flags,
9370 uint32_t version,
9371 WERROR expected_result)
9373 struct spoolss_DeletePrinterDriverEx r;
9375 r.in.server = server;
9376 r.in.architecture = environment;
9377 r.in.driver = driver;
9378 r.in.delete_flags = delete_flags;
9379 r.in.version = version;
9381 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9383 torture_assert_ntstatus_ok(tctx,
9384 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9385 "DeletePrinterDriverEx failed");
9386 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9387 "DeletePrinterDriverEx failed with unexpected result");
9389 return true;
9392 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9393 struct dcerpc_binding_handle *b,
9394 const char *server_name,
9395 const char *driver,
9396 const char *environment)
9398 torture_assert(tctx,
9399 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9400 "failed to delete driver");
9402 torture_assert(tctx,
9403 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9404 "failed to delete driver");
9406 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9407 torture_fail(tctx, "deleted driver still enumerated");
9410 torture_assert(tctx,
9411 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9412 "2nd delete failed");
9414 return true;
9417 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9418 struct dcerpc_binding_handle *b,
9419 const char *server_name,
9420 const char *driver,
9421 const char *environment,
9422 uint32_t delete_flags,
9423 uint32_t version)
9425 torture_assert(tctx,
9426 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9427 "failed to delete driver");
9429 torture_assert(tctx,
9430 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9431 "failed to delete driver");
9433 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9434 torture_fail(tctx, "deleted driver still enumerated");
9437 torture_assert(tctx,
9438 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9439 "2nd delete failed");
9441 return true;
9444 static bool test_PrinterDriver_args(struct torture_context *tctx,
9445 struct dcerpc_binding_handle *b,
9446 const char *server_name,
9447 uint32_t level,
9448 struct spoolss_AddDriverInfo8 *r,
9449 uint32_t add_flags,
9450 uint32_t delete_flags,
9451 uint32_t delete_version,
9452 bool ex,
9453 const char *remote_driver_dir)
9455 bool ret = true;
9457 switch (level) {
9458 case 1:
9459 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9460 break;
9461 case 2:
9462 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9463 break;
9464 case 3:
9465 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9466 break;
9467 case 4:
9468 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9469 break;
9470 case 6:
9471 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9472 break;
9473 case 8:
9474 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9475 break;
9476 default:
9477 return false;
9480 if (ret == false) {
9481 return ret;
9484 if (level == 1) {
9485 return ret;
9488 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9490 if (!ex && (level == 6 || level == 8)) {
9491 return ret;
9495 struct dcerpc_pipe *p2;
9496 struct policy_handle hive_handle;
9497 struct dcerpc_binding_handle *b2;
9499 torture_assert_ntstatus_ok(tctx,
9500 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9501 "could not open winreg pipe");
9502 b2 = p2->binding_handle;
9504 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9506 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9508 test_winreg_CloseKey(tctx, b2, &hive_handle);
9510 talloc_free(p2);
9513 if (ex) {
9514 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9515 } else {
9516 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9520 static bool fillup_printserver_info(struct torture_context *tctx,
9521 struct dcerpc_pipe *p,
9522 struct torture_driver_context *d)
9524 struct policy_handle server_handle;
9525 struct dcerpc_binding_handle *b = p->binding_handle;
9526 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9528 torture_assert(tctx,
9529 test_OpenPrinter_server(tctx, p, &server_handle),
9530 "failed to open printserver");
9531 torture_assert(tctx,
9532 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9533 "failed to get environment");
9534 torture_assert(tctx,
9535 test_ClosePrinter(tctx, b, &server_handle),
9536 "failed to close printserver");
9538 torture_assert(tctx,
9539 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9540 d->local.environment ? d->local.environment : d->remote.environment,
9541 &d->remote.driver_directory),
9542 "failed to get driver directory");
9544 return true;
9547 static const char *driver_directory_dir(const char *driver_directory)
9549 char *p;
9551 p = strrchr(driver_directory, '\\');
9552 if (p) {
9553 return p+1;
9556 return NULL;
9559 static const char *driver_directory_share(struct torture_context *tctx,
9560 const char *driver_directory)
9562 const char *p;
9563 char *tok;
9565 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9566 driver_directory += 2;
9569 p = talloc_strdup(tctx, driver_directory);
9571 torture_assert(tctx,
9572 next_token_talloc(tctx, &p, &tok, "\\"),
9573 "cannot explode uri");
9574 torture_assert(tctx,
9575 next_token_talloc(tctx, &p, &tok, "\\"),
9576 "cannot explode uri");
9578 return tok;
9581 static bool upload_printer_driver_file(struct torture_context *tctx,
9582 struct smbcli_state *cli,
9583 struct torture_driver_context *d,
9584 const char *file_name)
9586 XFILE *f;
9587 int fnum;
9588 uint8_t *buf;
9589 int maxwrite = 64512;
9590 off_t nread = 0;
9591 size_t start = 0;
9592 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9593 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9594 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9596 if (!file_name || strlen(file_name) == 0) {
9597 return true;
9600 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9602 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9603 if (fnum == -1) {
9604 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9607 f = x_fopen(local_name, O_RDONLY, 0);
9608 if (f == NULL) {
9609 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9612 buf = talloc_array(tctx, uint8_t, maxwrite);
9613 if (!buf) {
9614 x_fclose(f);
9615 return false;
9618 while (!x_feof(f)) {
9619 int n = maxwrite;
9620 int ret;
9622 if ((n = x_fread(buf, 1, n, f)) < 1) {
9623 if((n == 0) && x_feof(f))
9624 break; /* Empty local file. */
9626 torture_warning(tctx,
9627 "failed to read file: %s\n", strerror(errno));
9628 break;
9631 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9633 if (n != ret) {
9634 torture_warning(tctx,
9635 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9636 break;
9639 nread += n;
9642 x_fclose(f);
9644 torture_assert_ntstatus_ok(tctx,
9645 smbcli_close(cli->tree, fnum),
9646 "failed to close file");
9648 return true;
9651 static bool connect_printer_driver_share(struct torture_context *tctx,
9652 const char *server_name,
9653 const char *share_name,
9654 struct smbcli_state **cli)
9656 struct smbcli_options smb_options;
9657 struct smbcli_session_options smb_session_options;
9659 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9660 share_name, server_name);
9662 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9663 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9665 torture_assert_ntstatus_ok(tctx,
9666 smbcli_full_connection(tctx, cli, server_name,
9667 lpcfg_smb_ports(tctx->lp_ctx),
9668 share_name, NULL,
9669 lpcfg_socket_options(tctx->lp_ctx),
9670 cmdline_credentials,
9671 lpcfg_resolve_context(tctx->lp_ctx),
9672 tctx->ev,
9673 &smb_options,
9674 &smb_session_options,
9675 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9676 "failed to open driver share");
9678 return true;
9681 static bool upload_printer_driver(struct torture_context *tctx,
9682 const char *server_name,
9683 struct torture_driver_context *d)
9685 struct smbcli_state *cli;
9686 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9687 int i;
9689 torture_assert(tctx,
9690 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9691 "failed to connect to driver share");
9693 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9694 server_name, share_name);
9696 torture_assert(tctx,
9697 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9698 "failed to upload driver_path");
9699 torture_assert(tctx,
9700 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9701 "failed to upload data_file");
9702 torture_assert(tctx,
9703 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9704 "failed to upload config_file");
9705 torture_assert(tctx,
9706 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9707 "failed to upload help_file");
9708 if (d->info8.dependent_files) {
9709 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9710 torture_assert(tctx,
9711 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9712 "failed to upload dependent_files");
9716 talloc_free(cli);
9718 return true;
9721 static bool check_printer_driver_file(struct torture_context *tctx,
9722 struct smbcli_state *cli,
9723 struct torture_driver_context *d,
9724 const char *file_name)
9726 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9727 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9728 remote_arch_dir,
9729 d->info8.version,
9730 file_name);
9731 int fnum;
9733 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9735 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9737 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9738 if (fnum == -1) {
9739 return false;
9742 torture_assert_ntstatus_ok(tctx,
9743 smbcli_close(cli->tree, fnum),
9744 "failed to close driver file");
9746 return true;
9749 static bool check_printer_driver_files(struct torture_context *tctx,
9750 const char *server_name,
9751 struct torture_driver_context *d,
9752 bool expect_exist)
9754 struct smbcli_state *cli;
9755 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9756 int i;
9758 torture_assert(tctx,
9759 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9760 "failed to connect to driver share");
9762 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9763 (expect_exist ? "": "non-"),
9764 server_name, share_name);
9766 if (d->info8.driver_path && d->info8.driver_path[0]) {
9767 torture_assert(tctx,
9768 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9769 "failed driver_path check");
9771 if (d->info8.data_file && d->info8.data_file[0]) {
9772 torture_assert(tctx,
9773 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9774 "failed data_file check");
9776 if (d->info8.config_file && d->info8.config_file[0]) {
9777 torture_assert(tctx,
9778 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9779 "failed config_file check");
9781 if (d->info8.help_file && d->info8.help_file[0]) {
9782 torture_assert(tctx,
9783 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9784 "failed help_file check");
9786 if (d->info8.dependent_files) {
9787 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9788 torture_assert(tctx,
9789 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9790 "failed dependent_files check");
9794 talloc_free(cli);
9796 return true;
9799 static bool remove_printer_driver_file(struct torture_context *tctx,
9800 struct smbcli_state *cli,
9801 struct torture_driver_context *d,
9802 const char *file_name)
9804 const char *remote_name;
9805 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9807 if (!file_name || strlen(file_name) == 0) {
9808 return true;
9811 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9813 torture_comment(tctx, "Removing %s\n", remote_name);
9815 torture_assert_ntstatus_ok(tctx,
9816 smbcli_unlink(cli->tree, remote_name),
9817 "failed to unlink");
9819 return true;
9822 static bool remove_printer_driver(struct torture_context *tctx,
9823 const char *server_name,
9824 struct torture_driver_context *d)
9826 struct smbcli_state *cli;
9827 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9828 int i;
9830 torture_assert(tctx,
9831 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9832 "failed to connect to driver share");
9834 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9835 server_name, share_name);
9837 torture_assert(tctx,
9838 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9839 "failed to remove driver_path");
9840 torture_assert(tctx,
9841 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9842 "failed to remove data_file");
9843 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9844 torture_assert(tctx,
9845 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9846 "failed to remove config_file");
9848 torture_assert(tctx,
9849 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9850 "failed to remove help_file");
9851 if (d->info8.dependent_files) {
9852 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9853 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9854 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9855 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9856 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9857 continue;
9859 torture_assert(tctx,
9860 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9861 "failed to remove dependent_files");
9865 talloc_free(cli);
9867 return true;
9871 static bool test_add_driver_arg(struct torture_context *tctx,
9872 struct dcerpc_pipe *p,
9873 struct torture_driver_context *d)
9875 bool ret = true;
9876 struct dcerpc_binding_handle *b = p->binding_handle;
9877 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9878 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9879 int i;
9880 struct spoolss_AddDriverInfo8 info8;
9881 uint32_t add_flags = APD_COPY_NEW_FILES;
9882 uint32_t delete_flags = 0;
9884 ZERO_STRUCT(info8);
9886 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9887 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9889 torture_assert(tctx,
9890 fillup_printserver_info(tctx, p, d),
9891 "failed to fillup printserver info");
9893 if (!directory_exist(d->local.driver_directory)) {
9894 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9897 torture_assert(tctx,
9898 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9899 "failed to upload printer driver");
9901 info8 = d->info8;
9902 if (d->info8.dependent_files) {
9903 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9904 if (d->info8.dependent_files->string) {
9905 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9907 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9908 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9909 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9913 info8.architecture = d->local.environment;
9915 for (i=0; i < ARRAY_SIZE(levels); i++) {
9917 if (torture_setting_bool(tctx, "samba3", false)) {
9918 switch (levels[i]) {
9919 case 2:
9920 case 4:
9921 case 8:
9922 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9923 continue;
9924 default:
9925 break;
9928 if (torture_setting_bool(tctx, "w2k3", false)) {
9929 switch (levels[i]) {
9930 case 8:
9931 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9932 continue;
9933 default:
9934 break;
9938 torture_comment(tctx,
9939 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9940 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9942 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);
9945 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9946 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9947 if (d->info8.config_file) {
9948 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9950 if (d->info8.help_file) {
9951 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9953 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9954 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9955 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9959 for (i=0; i < ARRAY_SIZE(levels); i++) {
9961 if (torture_setting_bool(tctx, "samba3", false)) {
9962 switch (levels[i]) {
9963 case 2:
9964 case 4:
9965 case 8:
9966 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9967 continue;
9968 default:
9969 break;
9972 if (torture_setting_bool(tctx, "w2k3", false)) {
9973 switch (levels[i]) {
9974 case 8:
9975 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9976 continue;
9977 default:
9978 break;
9982 torture_comment(tctx,
9983 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9984 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9986 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);
9989 torture_assert(tctx,
9990 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9991 "failed to remove printer driver");
9993 torture_comment(tctx, "\n");
9995 return ret;
9998 static bool test_add_driver_ex_64(struct torture_context *tctx,
9999 struct dcerpc_pipe *p)
10001 struct torture_driver_context *d;
10003 d = talloc_zero(tctx, struct torture_driver_context);
10005 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10006 d->info8.driver_name = TORTURE_DRIVER_EX;
10007 d->info8.architecture = NULL;
10008 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10009 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10010 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10011 d->local.environment = talloc_strdup(d, "Windows x64");
10012 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10013 d->ex = true;
10015 return test_add_driver_arg(tctx, p, d);
10018 static bool test_add_driver_ex_32(struct torture_context *tctx,
10019 struct dcerpc_pipe *p)
10021 struct torture_driver_context *d;
10023 d = talloc_zero(tctx, struct torture_driver_context);
10025 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10026 d->info8.driver_name = TORTURE_DRIVER_EX;
10027 d->info8.architecture = NULL;
10028 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10029 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10030 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10031 d->local.environment = talloc_strdup(d, "Windows NT x86");
10032 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10033 d->ex = true;
10035 return test_add_driver_arg(tctx, p, d);
10038 static bool test_add_driver_64(struct torture_context *tctx,
10039 struct dcerpc_pipe *p)
10041 struct torture_driver_context *d;
10043 d = talloc_zero(tctx, struct torture_driver_context);
10045 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10046 d->info8.driver_name = TORTURE_DRIVER;
10047 d->info8.architecture = NULL;
10048 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10049 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10050 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10051 d->local.environment = talloc_strdup(d, "Windows x64");
10052 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10053 d->ex = false;
10055 return test_add_driver_arg(tctx, p, d);
10058 static bool test_add_driver_32(struct torture_context *tctx,
10059 struct dcerpc_pipe *p)
10061 struct torture_driver_context *d;
10063 d = talloc_zero(tctx, struct torture_driver_context);
10065 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10066 d->info8.driver_name = TORTURE_DRIVER;
10067 d->info8.architecture = NULL;
10068 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10069 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10070 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10071 d->local.environment = talloc_strdup(d, "Windows NT x86");
10072 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10073 d->ex = false;
10075 return test_add_driver_arg(tctx, p, d);
10078 static bool test_add_driver_adobe(struct torture_context *tctx,
10079 struct dcerpc_pipe *p)
10081 struct torture_driver_context *d;
10083 if (!torture_setting_bool(tctx, "samba3", false)) {
10084 torture_skip(tctx, "skipping adobe test which only works against samba3");
10087 d = talloc_zero(tctx, struct torture_driver_context);
10089 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10090 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
10091 d->info8.architecture = NULL;
10092 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10093 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10094 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
10095 #if 0
10096 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10097 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10098 #endif
10099 d->local.environment = talloc_strdup(d, "Windows 4.0");
10100 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10101 d->ex = false;
10103 return test_add_driver_arg(tctx, p, d);
10106 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
10107 struct dcerpc_pipe *p)
10109 struct torture_driver_context *d;
10110 struct spoolss_StringArray *a;
10112 if (!torture_setting_bool(tctx, "samba3", false)) {
10113 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
10116 d = talloc_zero(tctx, struct torture_driver_context);
10118 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10119 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
10120 d->info8.architecture = NULL;
10121 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10122 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10123 d->info8.config_file = NULL;
10124 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10125 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10126 d->info8.default_datatype = talloc_strdup(d, "RAW");
10128 a = talloc_zero(d, struct spoolss_StringArray);
10129 a->string = talloc_zero_array(a, const char *, 7);
10130 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
10131 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
10132 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
10133 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
10134 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
10135 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
10137 d->info8.dependent_files = a;
10138 d->local.environment = talloc_strdup(d, "Windows 4.0");
10139 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10140 d->ex = false;
10142 return test_add_driver_arg(tctx, p, d);
10145 static bool test_add_driver_timestamps(struct torture_context *tctx,
10146 struct dcerpc_pipe *p)
10148 struct torture_driver_context *d;
10149 struct timeval t = timeval_current();
10151 d = talloc_zero(tctx, struct torture_driver_context);
10153 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10154 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
10155 d->info8.architecture = NULL;
10156 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10157 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10158 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10159 d->info8.driver_date = timeval_to_nttime(&t);
10160 d->local.environment = talloc_strdup(d, "Windows NT x86");
10161 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10162 d->ex = true;
10164 torture_assert(tctx,
10165 test_add_driver_arg(tctx, p, d),
10166 "");
10168 unix_to_nt_time(&d->info8.driver_date, 1);
10170 torture_assert(tctx,
10171 test_add_driver_arg(tctx, p, d),
10172 "");
10174 return true;
10177 static bool test_multiple_drivers(struct torture_context *tctx,
10178 struct dcerpc_pipe *p)
10180 struct torture_driver_context *d;
10181 struct dcerpc_binding_handle *b = p->binding_handle;
10182 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10183 int i;
10184 struct spoolss_AddDriverInfo8 info8;
10185 uint32_t add_flags = APD_COPY_NEW_FILES;
10186 uint32_t delete_flags = 0;
10188 d = talloc_zero(tctx, struct torture_driver_context);
10190 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10191 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10192 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10193 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10194 d->local.environment = talloc_strdup(d, "Windows NT x86");
10195 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10196 d->ex = true;
10198 torture_assert(tctx,
10199 fillup_printserver_info(tctx, p, d),
10200 "failed to fillup printserver info");
10202 if (!directory_exist(d->local.driver_directory)) {
10203 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10206 torture_assert(tctx,
10207 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10208 "failed to upload printer driver");
10210 info8 = d->info8;
10211 info8.architecture = d->local.environment;
10213 for (i=0; i < 3; i++) {
10214 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
10216 torture_assert(tctx,
10217 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10218 "failed to add driver");
10221 torture_assert(tctx,
10222 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10223 "failed to delete driver");
10225 torture_assert(tctx,
10226 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10227 "torture_test_driver_1 no longer on the server");
10229 torture_assert(tctx,
10230 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10231 "torture_test_driver_2 no longer on the server");
10233 torture_assert(tctx,
10234 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10235 "failed to delete driver");
10237 torture_assert(tctx,
10238 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10239 "torture_test_driver_2 no longer on the server");
10241 torture_assert(tctx,
10242 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10243 "failed to delete driver");
10245 torture_assert(tctx,
10246 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10247 "failed to remove printer driver");
10249 return true;
10252 static bool test_del_driver_all_files(struct torture_context *tctx,
10253 struct dcerpc_pipe *p)
10255 struct torture_driver_context *d;
10256 struct spoolss_StringArray *a;
10257 uint32_t add_flags = APD_COPY_NEW_FILES;
10258 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10259 struct dcerpc_binding_handle *b = p->binding_handle;
10260 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10262 d = talloc_zero(tctx, struct torture_driver_context);
10264 d->ex = true;
10265 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10266 d->info8.driver_name = TORTURE_DRIVER_DELETER;
10267 d->info8.architecture = NULL;
10268 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10269 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10270 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10271 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
10272 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10273 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10275 a = talloc_zero(d, struct spoolss_StringArray);
10276 a->string = talloc_zero_array(a, const char *, 3);
10277 a->string[0] = talloc_strdup(a->string, "cups6.inf");
10278 a->string[1] = talloc_strdup(a->string, "cups6.ini");
10280 d->info8.dependent_files = a;
10281 d->info8.architecture = d->local.environment;
10283 torture_assert(tctx,
10284 fillup_printserver_info(tctx, p, d),
10285 "failed to fillup printserver info");
10287 if (!directory_exist(d->local.driver_directory)) {
10288 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10291 torture_assert(tctx,
10292 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10293 "failed to upload printer driver");
10295 torture_assert(tctx,
10296 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10297 "failed to add driver");
10299 torture_assert(tctx,
10300 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10301 d->info8.driver_name,
10302 d->local.environment,
10303 delete_flags,
10304 d->info8.version),
10305 "failed to delete driver");
10307 torture_assert(tctx,
10308 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10309 "printer driver file check failed");
10311 talloc_free(d);
10312 return true;
10315 static bool test_del_driver_unused_files(struct torture_context *tctx,
10316 struct dcerpc_pipe *p)
10318 struct torture_driver_context *d1;
10319 struct torture_driver_context *d2;
10320 uint32_t add_flags = APD_COPY_NEW_FILES;
10321 struct dcerpc_binding_handle *b = p->binding_handle;
10322 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10324 d1 = talloc_zero(tctx, struct torture_driver_context);
10325 d1->ex = true;
10326 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10327 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10328 d1->info8.architecture = NULL;
10329 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10330 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10331 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10332 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10333 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10334 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10335 d1->info8.architecture = d1->local.environment;
10337 d2 = talloc_zero(tctx, struct torture_driver_context);
10338 d2->ex = true;
10339 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10340 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10341 d2->info8.architecture = NULL;
10342 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10343 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10344 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10345 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10346 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10347 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10348 d2->info8.architecture = d2->local.environment;
10350 torture_assert(tctx,
10351 fillup_printserver_info(tctx, p, d1),
10352 "failed to fillup printserver info");
10353 torture_assert(tctx,
10354 fillup_printserver_info(tctx, p, d2),
10355 "failed to fillup printserver info");
10357 if (!directory_exist(d1->local.driver_directory)) {
10358 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10361 torture_assert(tctx,
10362 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10363 "failed to upload printer driver");
10364 torture_assert(tctx,
10365 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10366 "failed to add driver");
10368 torture_assert(tctx,
10369 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10370 "failed to upload printer driver");
10371 torture_assert(tctx,
10372 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10373 "failed to add driver");
10375 /* some files are in use by a separate driver, should fail */
10376 torture_assert(tctx,
10377 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10378 d1->info8.driver_name,
10379 d1->local.environment,
10380 DPD_DELETE_ALL_FILES,
10381 d1->info8.version,
10382 WERR_PRINTER_DRIVER_IN_USE),
10383 "invalid delete driver response");
10385 /* should only delete files not in use by other driver */
10386 torture_assert(tctx,
10387 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10388 d1->info8.driver_name,
10389 d1->local.environment,
10390 DPD_DELETE_UNUSED_FILES,
10391 d1->info8.version,
10392 WERR_OK),
10393 "failed to delete driver (unused files)");
10395 /* check non-overlapping were deleted */
10396 d1->info8.driver_path = NULL;
10397 d1->info8.help_file = NULL;
10398 torture_assert(tctx,
10399 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10400 "printer driver file check failed");
10401 /* d2 files should be uneffected */
10402 torture_assert(tctx,
10403 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10404 "printer driver file check failed");
10406 torture_assert(tctx,
10407 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10408 d2->info8.driver_name,
10409 d2->local.environment,
10410 DPD_DELETE_ALL_FILES,
10411 d2->info8.version,
10412 WERR_OK),
10413 "failed to delete driver");
10415 torture_assert(tctx,
10416 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10417 "printer driver file check failed");
10419 talloc_free(d1);
10420 talloc_free(d2);
10421 return true;
10424 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10426 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10428 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10429 "driver", &ndr_table_spoolss);
10430 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10431 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10433 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10434 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10436 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10438 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10440 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10442 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10444 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10446 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10448 return suite;