s3-torture: Use static printer for smbd spooler test
[Samba/id10ts.git] / source4 / torture / rpc / spoolss.c
blob6e0d9edcf888273b5114115e1fbeb3937c4bc981
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
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 = 0;
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 = 0;
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];j++) {
683 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
684 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
686 switch (level) {
687 case 1:
688 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
689 break;
690 case 2:
691 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
692 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
693 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
694 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
695 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
696 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
697 break;
698 case 3:
699 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
704 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
705 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
706 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
707 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
708 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
709 break;
710 case 4:
711 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
716 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
717 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
718 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
719 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
720 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
721 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
722 break;
723 case 5:
724 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
725 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
726 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
727 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
728 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
729 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
730 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
731 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
732 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
733 break;
734 case 6:
735 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
740 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
741 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
742 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
745 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
746 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
747 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
748 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
749 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
750 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
751 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
752 break;
753 case 8:
754 /* level 8 is our reference, and it makes no sense to compare it to itself */
755 break;
761 return true;
764 static bool test_EnumMonitors(struct torture_context *tctx,
765 void *private_data)
767 struct test_spoolss_context *ctx =
768 talloc_get_type_abort(private_data, struct test_spoolss_context);
769 struct dcerpc_pipe *p = ctx->spoolss_pipe;
770 struct dcerpc_binding_handle *b = p->binding_handle;
771 NTSTATUS status;
772 struct spoolss_EnumMonitors r;
773 uint16_t levels[] = { 1, 2 };
774 int i, j;
776 for (i=0;i<ARRAY_SIZE(levels);i++) {
777 int level = levels[i];
778 DATA_BLOB blob;
779 uint32_t needed;
780 uint32_t count;
781 union spoolss_MonitorInfo *info;
783 r.in.servername = "";
784 r.in.level = level;
785 r.in.buffer = NULL;
786 r.in.offered = 0;
787 r.out.needed = &needed;
788 r.out.count = &count;
789 r.out.info = &info;
791 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
793 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
794 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
795 if (W_ERROR_IS_OK(r.out.result)) {
796 /* TODO: do some more checks here */
797 continue;
799 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
800 "EnumMonitors failed");
802 blob = data_blob_talloc_zero(ctx, needed);
803 r.in.buffer = &blob;
804 r.in.offered = needed;
806 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
807 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
809 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
811 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
813 ctx->monitor_count[level] = count;
814 ctx->monitors[level] = info;
817 for (i=1;i<ARRAY_SIZE(levels);i++) {
818 int level = levels[i];
819 int old_level = levels[i-1];
820 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
821 "EnumMonitors invalid value");
824 for (i=0;i<ARRAY_SIZE(levels);i++) {
825 int level = levels[i];
826 for (j=0;j<ctx->monitor_count[level];j++) {
827 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
828 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
829 switch (level) {
830 case 1:
831 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
832 break;
833 case 2:
834 /* level 2 is our reference, and it makes no sense to compare it to itself */
835 break;
840 return true;
843 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
844 struct dcerpc_binding_handle *b,
845 const char *environment,
846 uint32_t level,
847 uint32_t *count_p,
848 union spoolss_PrintProcessorInfo **info_p,
849 WERROR expected_result)
851 struct spoolss_EnumPrintProcessors r;
852 DATA_BLOB blob;
853 uint32_t needed;
854 uint32_t count;
855 union spoolss_PrintProcessorInfo *info;
857 r.in.servername = "";
858 r.in.environment = environment;
859 r.in.level = level;
860 r.in.buffer = NULL;
861 r.in.offered = 0;
862 r.out.needed = &needed;
863 r.out.count = &count;
864 r.out.info = &info;
866 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
867 r.in.environment, r.in.level);
869 torture_assert_ntstatus_ok(tctx,
870 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
871 "EnumPrintProcessors failed");
872 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
873 blob = data_blob_talloc_zero(tctx, needed);
874 r.in.buffer = &blob;
875 r.in.offered = needed;
876 torture_assert_ntstatus_ok(tctx,
877 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
878 "EnumPrintProcessors failed");
880 torture_assert_werr_equal(tctx, r.out.result, expected_result,
881 "EnumPrintProcessors failed");
883 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
885 if (count_p) {
886 *count_p = count;
888 if (info_p) {
889 *info_p = info;
892 return true;
895 static bool test_EnumPrintProcessors(struct torture_context *tctx,
896 void *private_data)
898 struct test_spoolss_context *ctx =
899 talloc_get_type_abort(private_data, struct test_spoolss_context);
901 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
902 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
903 int i;
904 struct dcerpc_pipe *p = ctx->spoolss_pipe;
905 struct dcerpc_binding_handle *b = p->binding_handle;
907 torture_assert(tctx,
908 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
909 "test_EnumPrintProcessors_level failed");
911 for (i=0;i<ARRAY_SIZE(levels);i++) {
912 union spoolss_PrintProcessorInfo *info;
913 uint32_t count;
914 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
916 torture_assert(tctx,
917 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
918 "test_EnumPrintProcessors_level failed");
921 return true;
924 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
925 struct dcerpc_binding_handle *b,
926 const char *print_processor_name,
927 uint32_t level,
928 uint32_t *count_p,
929 union spoolss_PrintProcDataTypesInfo **info_p,
930 WERROR expected_result)
932 struct spoolss_EnumPrintProcDataTypes r;
933 DATA_BLOB blob;
934 uint32_t needed;
935 uint32_t count;
936 union spoolss_PrintProcDataTypesInfo *info;
938 r.in.servername = "";
939 r.in.print_processor_name = print_processor_name;
940 r.in.level = level;
941 r.in.buffer = NULL;
942 r.in.offered = 0;
943 r.out.needed = &needed;
944 r.out.count = &count;
945 r.out.info = &info;
947 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
948 r.in.print_processor_name, r.in.level);
950 torture_assert_ntstatus_ok(tctx,
951 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
952 "EnumPrintProcDataTypes failed");
953 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
954 blob = data_blob_talloc_zero(tctx, needed);
955 r.in.buffer = &blob;
956 r.in.offered = needed;
957 torture_assert_ntstatus_ok(tctx,
958 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
959 "EnumPrintProcDataTypes failed");
961 torture_assert_werr_equal(tctx, r.out.result, expected_result,
962 "EnumPrintProcDataTypes failed");
964 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
966 if (count_p) {
967 *count_p = count;
969 if (info_p) {
970 *info_p = info;
973 return true;
976 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
977 void *private_data)
979 struct test_spoolss_context *ctx =
980 talloc_get_type_abort(private_data, struct test_spoolss_context);
982 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
983 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
984 int i;
985 struct dcerpc_pipe *p = ctx->spoolss_pipe;
986 struct dcerpc_binding_handle *b = p->binding_handle;
988 torture_assert(tctx,
989 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
990 "test_EnumPrintProcDataTypes_level failed");
992 torture_assert(tctx,
993 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
994 "test_EnumPrintProcDataTypes_level failed");
996 for (i=0;i<ARRAY_SIZE(levels);i++) {
997 int level = levels[i];
998 uint32_t count;
999 union spoolss_PrintProcDataTypesInfo *info;
1000 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1002 torture_assert(tctx,
1003 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1004 "test_EnumPrintProcDataTypes_level failed");
1008 union spoolss_PrintProcessorInfo *info;
1009 uint32_t count;
1011 torture_assert(tctx,
1012 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1013 "test_EnumPrintProcessors_level failed");
1015 for (i=0; i < count; i++) {
1016 torture_assert(tctx,
1017 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1018 "test_EnumPrintProcDataTypes_level failed");
1023 return true;
1026 static bool test_EnumPrinters(struct torture_context *tctx,
1027 void *private_data)
1029 struct test_spoolss_context *ctx =
1030 talloc_get_type_abort(private_data, struct test_spoolss_context);
1031 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1032 struct dcerpc_binding_handle *b = p->binding_handle;
1033 struct spoolss_EnumPrinters r;
1034 NTSTATUS status;
1035 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1036 int i, j;
1038 for (i=0;i<ARRAY_SIZE(levels);i++) {
1039 int level = levels[i];
1040 DATA_BLOB blob;
1041 uint32_t needed;
1042 uint32_t count;
1043 union spoolss_PrinterInfo *info;
1045 r.in.flags = PRINTER_ENUM_LOCAL;
1046 r.in.server = "";
1047 r.in.level = level;
1048 r.in.buffer = NULL;
1049 r.in.offered = 0;
1050 r.out.needed = &needed;
1051 r.out.count = &count;
1052 r.out.info = &info;
1054 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1056 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1057 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1058 if (W_ERROR_IS_OK(r.out.result)) {
1059 /* TODO: do some more checks here */
1060 continue;
1062 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1063 "EnumPrinters unexpected return code");
1065 blob = data_blob_talloc_zero(ctx, needed);
1066 r.in.buffer = &blob;
1067 r.in.offered = needed;
1069 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1070 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1072 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1074 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1076 ctx->printer_count[level] = count;
1077 ctx->printers[level] = info;
1080 for (i=1;i<ARRAY_SIZE(levels);i++) {
1081 int level = levels[i];
1082 int old_level = levels[i-1];
1083 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1084 "EnumPrinters invalid value");
1087 for (i=0;i<ARRAY_SIZE(levels);i++) {
1088 int level = levels[i];
1089 for (j=0;j<ctx->printer_count[level];j++) {
1090 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1091 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1092 switch (level) {
1093 case 0:
1094 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1095 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1097 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1099 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1112 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1113 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1116 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1117 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1118 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1119 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1120 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1121 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1122 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1123 break;
1124 case 1:
1125 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1126 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1127 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1128 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1129 break;
1130 case 2:
1131 /* level 2 is our reference, and it makes no sense to compare it to itself */
1132 break;
1133 case 4:
1134 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1135 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1136 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1137 break;
1138 case 5:
1139 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1140 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1141 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1142 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1143 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1144 break;
1149 /* TODO:
1150 * - verify that the port of a printer was in the list returned by EnumPorts
1153 return true;
1156 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1157 struct dcerpc_binding_handle *b,
1158 struct policy_handle *handle,
1159 const char *driver_name,
1160 const char *environment);
1162 bool test_GetPrinter_level(struct torture_context *tctx,
1163 struct dcerpc_binding_handle *b,
1164 struct policy_handle *handle,
1165 uint32_t level,
1166 union spoolss_PrinterInfo *info)
1168 struct spoolss_GetPrinter r;
1169 uint32_t needed;
1171 r.in.handle = handle;
1172 r.in.level = level;
1173 r.in.buffer = NULL;
1174 r.in.offered = 0;
1175 r.out.needed = &needed;
1177 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1179 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1180 "GetPrinter failed");
1182 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1183 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1184 r.in.buffer = &blob;
1185 r.in.offered = needed;
1187 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1188 "GetPrinter failed");
1191 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1193 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1195 if (info && r.out.info) {
1196 *info = *r.out.info;
1199 return true;
1203 static bool test_GetPrinter(struct torture_context *tctx,
1204 struct dcerpc_binding_handle *b,
1205 struct policy_handle *handle,
1206 const char *environment)
1208 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1209 int i;
1211 for (i=0;i<ARRAY_SIZE(levels);i++) {
1213 union spoolss_PrinterInfo info;
1215 ZERO_STRUCT(info);
1217 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1218 "failed to call GetPrinter");
1220 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1221 torture_assert(tctx,
1222 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1223 "failed to call test_GetPrinterDriver2");
1227 return true;
1230 static bool test_SetPrinter(struct torture_context *tctx,
1231 struct dcerpc_binding_handle *b,
1232 struct policy_handle *handle,
1233 struct spoolss_SetPrinterInfoCtr *info_ctr,
1234 struct spoolss_DevmodeContainer *devmode_ctr,
1235 struct sec_desc_buf *secdesc_ctr,
1236 enum spoolss_PrinterControl command)
1238 struct spoolss_SetPrinter r;
1240 r.in.handle = handle;
1241 r.in.info_ctr = info_ctr;
1242 r.in.devmode_ctr = devmode_ctr;
1243 r.in.secdesc_ctr = secdesc_ctr;
1244 r.in.command = command;
1246 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1248 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1249 "failed to call SetPrinter");
1250 torture_assert_werr_ok(tctx, r.out.result,
1251 "failed to call SetPrinter");
1253 return true;
1256 static bool test_SetPrinter_errors(struct torture_context *tctx,
1257 struct dcerpc_binding_handle *b,
1258 struct policy_handle *handle)
1260 struct spoolss_SetPrinter r;
1261 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1262 int i;
1264 struct spoolss_SetPrinterInfoCtr info_ctr;
1265 struct spoolss_DevmodeContainer devmode_ctr;
1266 struct sec_desc_buf secdesc_ctr;
1268 info_ctr.level = 0;
1269 info_ctr.info.info0 = NULL;
1271 ZERO_STRUCT(devmode_ctr);
1272 ZERO_STRUCT(secdesc_ctr);
1274 r.in.handle = handle;
1275 r.in.info_ctr = &info_ctr;
1276 r.in.devmode_ctr = &devmode_ctr;
1277 r.in.secdesc_ctr = &secdesc_ctr;
1278 r.in.command = 0;
1280 torture_comment(tctx, "Testing SetPrinter all zero\n");
1282 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1283 "failed to call SetPrinter");
1284 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1285 "failed to call SetPrinter");
1287 again:
1288 for (i=0; i < ARRAY_SIZE(levels); i++) {
1290 struct spoolss_SetPrinterInfo0 info0;
1291 struct spoolss_SetPrinterInfo1 info1;
1292 struct spoolss_SetPrinterInfo2 info2;
1293 struct spoolss_SetPrinterInfo3 info3;
1294 struct spoolss_SetPrinterInfo4 info4;
1295 struct spoolss_SetPrinterInfo5 info5;
1296 struct spoolss_SetPrinterInfo6 info6;
1297 struct spoolss_SetPrinterInfo7 info7;
1298 struct spoolss_SetPrinterInfo8 info8;
1299 struct spoolss_SetPrinterInfo9 info9;
1302 info_ctr.level = levels[i];
1303 switch (levels[i]) {
1304 case 0:
1305 ZERO_STRUCT(info0);
1306 info_ctr.info.info0 = &info0;
1307 break;
1308 case 1:
1309 ZERO_STRUCT(info1);
1310 info_ctr.info.info1 = &info1;
1311 break;
1312 case 2:
1313 ZERO_STRUCT(info2);
1314 info_ctr.info.info2 = &info2;
1315 break;
1316 case 3:
1317 ZERO_STRUCT(info3);
1318 info_ctr.info.info3 = &info3;
1319 break;
1320 case 4:
1321 ZERO_STRUCT(info4);
1322 info_ctr.info.info4 = &info4;
1323 break;
1324 case 5:
1325 ZERO_STRUCT(info5);
1326 info_ctr.info.info5 = &info5;
1327 break;
1328 case 6:
1329 ZERO_STRUCT(info6);
1330 info_ctr.info.info6 = &info6;
1331 break;
1332 case 7:
1333 ZERO_STRUCT(info7);
1334 info_ctr.info.info7 = &info7;
1335 break;
1336 case 8:
1337 ZERO_STRUCT(info8);
1338 info_ctr.info.info8 = &info8;
1339 break;
1340 case 9:
1341 ZERO_STRUCT(info9);
1342 info_ctr.info.info9 = &info9;
1343 break;
1346 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1347 info_ctr.level, r.in.command);
1349 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1350 "failed to call SetPrinter");
1352 switch (r.in.command) {
1353 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1354 /* is ignored for all levels other then 0 */
1355 if (info_ctr.level > 0) {
1356 /* ignored then */
1357 break;
1359 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1360 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1361 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1362 if (info_ctr.level > 0) {
1363 /* is invalid for all levels other then 0 */
1364 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1365 "unexpected error code returned");
1366 continue;
1367 } else {
1368 torture_assert_werr_ok(tctx, r.out.result,
1369 "failed to call SetPrinter with non 0 command");
1370 continue;
1372 break;
1374 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1375 /* FIXME: gd needs further investigation */
1376 default:
1377 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1378 "unexpected error code returned");
1379 continue;
1382 switch (info_ctr.level) {
1383 case 1:
1384 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1385 "unexpected error code returned");
1386 break;
1387 case 2:
1388 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1389 "unexpected error code returned");
1390 break;
1391 case 3:
1392 case 4:
1393 case 5:
1394 case 7:
1395 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1396 "unexpected error code returned");
1397 break;
1398 case 9:
1399 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1400 "unexpected error code returned");
1401 break;
1402 default:
1403 torture_assert_werr_ok(tctx, r.out.result,
1404 "failed to call SetPrinter");
1405 break;
1409 if (r.in.command < 5) {
1410 r.in.command++;
1411 goto again;
1414 return true;
1417 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1419 if ((r->level == 2) && (r->info.info2)) {
1420 r->info.info2->secdesc_ptr = 0;
1421 r->info.info2->devmode_ptr = 0;
1425 static bool test_PrinterInfo(struct torture_context *tctx,
1426 struct dcerpc_binding_handle *b,
1427 struct policy_handle *handle)
1429 NTSTATUS status;
1430 struct spoolss_SetPrinter s;
1431 struct spoolss_GetPrinter q;
1432 struct spoolss_GetPrinter q0;
1433 struct spoolss_SetPrinterInfoCtr info_ctr;
1434 union spoolss_PrinterInfo info;
1435 struct spoolss_DevmodeContainer devmode_ctr;
1436 struct sec_desc_buf secdesc_ctr;
1437 uint32_t needed;
1438 bool ret = true;
1439 int i;
1441 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1443 uint32_t status_list[] = {
1444 /* these do not stick
1445 PRINTER_STATUS_PAUSED,
1446 PRINTER_STATUS_ERROR,
1447 PRINTER_STATUS_PENDING_DELETION, */
1448 PRINTER_STATUS_PAPER_JAM,
1449 PRINTER_STATUS_PAPER_OUT,
1450 PRINTER_STATUS_MANUAL_FEED,
1451 PRINTER_STATUS_PAPER_PROBLEM,
1452 PRINTER_STATUS_OFFLINE,
1453 PRINTER_STATUS_IO_ACTIVE,
1454 PRINTER_STATUS_BUSY,
1455 PRINTER_STATUS_PRINTING,
1456 PRINTER_STATUS_OUTPUT_BIN_FULL,
1457 PRINTER_STATUS_NOT_AVAILABLE,
1458 PRINTER_STATUS_WAITING,
1459 PRINTER_STATUS_PROCESSING,
1460 PRINTER_STATUS_INITIALIZING,
1461 PRINTER_STATUS_WARMING_UP,
1462 PRINTER_STATUS_TONER_LOW,
1463 PRINTER_STATUS_NO_TONER,
1464 PRINTER_STATUS_PAGE_PUNT,
1465 PRINTER_STATUS_USER_INTERVENTION,
1466 PRINTER_STATUS_OUT_OF_MEMORY,
1467 PRINTER_STATUS_DOOR_OPEN,
1468 PRINTER_STATUS_SERVER_UNKNOWN,
1469 PRINTER_STATUS_POWER_SAVE,
1470 /* these do not stick
1471 0x02000000,
1472 0x04000000,
1473 0x08000000,
1474 0x10000000,
1475 0x20000000,
1476 0x40000000,
1477 0x80000000 */
1479 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1480 uint32_t attribute_list[] = {
1481 PRINTER_ATTRIBUTE_QUEUED,
1482 /* fails with WERR_INVALID_DATATYPE:
1483 PRINTER_ATTRIBUTE_DIRECT, */
1484 /* does not stick
1485 PRINTER_ATTRIBUTE_DEFAULT, */
1486 PRINTER_ATTRIBUTE_SHARED,
1487 /* does not stick
1488 PRINTER_ATTRIBUTE_NETWORK, */
1489 PRINTER_ATTRIBUTE_HIDDEN,
1490 PRINTER_ATTRIBUTE_LOCAL,
1491 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1492 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1493 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1494 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1495 /* does not stick
1496 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1497 /* fails with WERR_INVALID_DATATYPE:
1498 PRINTER_ATTRIBUTE_RAW_ONLY, */
1499 /* these do not stick
1500 PRINTER_ATTRIBUTE_PUBLISHED,
1501 PRINTER_ATTRIBUTE_FAX,
1502 PRINTER_ATTRIBUTE_TS,
1503 0x00010000,
1504 0x00020000,
1505 0x00040000,
1506 0x00080000,
1507 0x00100000,
1508 0x00200000,
1509 0x00400000,
1510 0x00800000,
1511 0x01000000,
1512 0x02000000,
1513 0x04000000,
1514 0x08000000,
1515 0x10000000,
1516 0x20000000,
1517 0x40000000,
1518 0x80000000 */
1521 ZERO_STRUCT(devmode_ctr);
1522 ZERO_STRUCT(secdesc_ctr);
1524 s.in.handle = handle;
1525 s.in.command = 0;
1526 s.in.info_ctr = &info_ctr;
1527 s.in.devmode_ctr = &devmode_ctr;
1528 s.in.secdesc_ctr = &secdesc_ctr;
1530 q.in.handle = handle;
1531 q.out.info = &info;
1532 q0 = q;
1534 #define TESTGETCALL(call, r) \
1535 r.in.buffer = NULL; \
1536 r.in.offered = 0;\
1537 r.out.needed = &needed; \
1538 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1539 if (!NT_STATUS_IS_OK(status)) { \
1540 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1541 r.in.level, nt_errstr(status), __location__); \
1542 ret = false; \
1543 break; \
1545 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1546 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1547 r.in.buffer = &blob; \
1548 r.in.offered = needed; \
1550 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1551 if (!NT_STATUS_IS_OK(status)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, nt_errstr(status), __location__); \
1554 ret = false; \
1555 break; \
1557 if (!W_ERROR_IS_OK(r.out.result)) { \
1558 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1559 r.in.level, win_errstr(r.out.result), __location__); \
1560 ret = false; \
1561 break; \
1565 #define TESTSETCALL_EXP(call, r, err) \
1566 clear_info2(&info_ctr);\
1567 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1568 if (!NT_STATUS_IS_OK(status)) { \
1569 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1570 r.in.info_ctr->level, nt_errstr(status), __location__); \
1571 ret = false; \
1572 break; \
1574 if (!W_ERROR_IS_OK(err)) { \
1575 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1576 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1577 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1578 ret = false; \
1580 break; \
1582 if (!W_ERROR_IS_OK(r.out.result)) { \
1583 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1584 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1585 ret = false; \
1586 break; \
1589 #define TESTSETCALL(call, r) \
1590 TESTSETCALL_EXP(call, r, WERR_OK)
1592 #define STRING_EQUAL(s1, s2, field) \
1593 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1594 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1595 #field, s2, __location__); \
1596 ret = false; \
1597 break; \
1600 #define MEM_EQUAL(s1, s2, length, field) \
1601 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1602 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1603 #field, (const char *)s2, __location__); \
1604 ret = false; \
1605 break; \
1608 #define INT_EQUAL(i1, i2, field) \
1609 if (i1 != i2) { \
1610 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1611 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1612 ret = false; \
1613 break; \
1616 #define SD_EQUAL(sd1, sd2, field) \
1617 if (!security_descriptor_equal(sd1, sd2)) { \
1618 torture_comment(tctx, "Failed to set %s (%s)\n", \
1619 #field, __location__); \
1620 ret = false; \
1621 break; \
1624 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1625 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626 q.in.level = lvl1; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.level = lvl1; \
1629 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630 info_ctr.info.info ## lvl1->field1 = value;\
1631 TESTSETCALL_EXP(SetPrinter, s, err) \
1632 info_ctr.info.info ## lvl1->field1 = ""; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl1->field1 = value; \
1635 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1636 q.in.level = lvl2; \
1637 TESTGETCALL(GetPrinter, q) \
1638 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1640 } while (0)
1642 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1643 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1644 } while (0);
1646 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1647 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1648 q.in.level = lvl1; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.level = lvl1; \
1651 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1652 info_ctr.info.info ## lvl1->field1 = value; \
1653 TESTSETCALL(SetPrinter, s) \
1654 info_ctr.info.info ## lvl1->field1 = 0; \
1655 TESTGETCALL(GetPrinter, q) \
1656 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1657 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1658 q.in.level = lvl2; \
1659 TESTGETCALL(GetPrinter, q) \
1660 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1661 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1662 } while (0)
1664 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1665 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1666 } while (0)
1668 q0.in.level = 0;
1669 do { TESTGETCALL(GetPrinter, q0) } while (0);
1671 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1672 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1674 /* level 0 printername does not stick */
1675 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1676 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1677 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1680 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1681 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1682 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1685 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1686 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1687 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1691 /* servername can be set but does not stick
1692 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1693 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1697 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1698 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1703 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1704 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1705 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1706 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1707 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1708 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1709 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1710 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1711 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1712 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1714 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1715 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1716 attribute_list[i],
1717 (attribute_list[i] | default_attribute)
1718 ); */
1719 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1720 attribute_list[i],
1721 (attribute_list[i] | default_attribute)
1723 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1724 attribute_list[i],
1725 (attribute_list[i] | default_attribute)
1727 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1728 attribute_list[i],
1729 (attribute_list[i] | default_attribute)
1731 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1732 attribute_list[i],
1733 (attribute_list[i] | default_attribute)
1734 ); */
1735 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1736 attribute_list[i],
1737 (attribute_list[i] | default_attribute)
1739 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1740 attribute_list[i],
1741 (attribute_list[i] | default_attribute)
1743 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1744 attribute_list[i],
1745 (attribute_list[i] | default_attribute)
1747 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1748 attribute_list[i],
1749 (attribute_list[i] | default_attribute)
1750 ); */
1751 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1752 attribute_list[i],
1753 (attribute_list[i] | default_attribute)
1755 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1756 attribute_list[i],
1757 (attribute_list[i] | default_attribute)
1759 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1760 attribute_list[i],
1761 (attribute_list[i] | default_attribute)
1765 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1766 /* level 2 sets do not stick
1767 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1770 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1775 /* priorities need to be between 0 and 99
1776 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1777 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1780 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1781 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1784 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1786 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1787 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1789 /* does not stick
1790 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1791 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1793 /* does not stick
1794 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1795 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1797 /* FIXME: gd also test devmode and secdesc behavior */
1800 /* verify composition of level 1 description field */
1801 const char *description;
1802 const char *tmp;
1804 q0.in.level = 1;
1805 do { TESTGETCALL(GetPrinter, q0) } while (0);
1807 description = talloc_strdup(tctx, q0.out.info->info1.description);
1809 q0.in.level = 2;
1810 do { TESTGETCALL(GetPrinter, q0) } while (0);
1812 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1813 q0.out.info->info2.printername,
1814 q0.out.info->info2.drivername,
1815 q0.out.info->info2.location);
1817 do { STRING_EQUAL(description, tmp, "description")} while (0);
1820 return ret;
1823 static bool test_security_descriptor_equal(struct torture_context *tctx,
1824 const struct security_descriptor *sd1,
1825 const struct security_descriptor *sd2)
1827 if (sd1 == sd2) {
1828 return true;
1831 if (!sd1 || !sd2) {
1832 torture_comment(tctx, "%s\n", __location__);
1833 return false;
1836 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1837 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1839 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1840 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1842 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1843 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1846 return false;
1848 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1849 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1850 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1851 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1852 return false;
1855 return true;
1858 static bool test_sd_set_level(struct torture_context *tctx,
1859 struct dcerpc_binding_handle *b,
1860 struct policy_handle *handle,
1861 uint32_t level,
1862 struct security_descriptor *sd)
1864 struct spoolss_SetPrinterInfoCtr info_ctr;
1865 struct spoolss_DevmodeContainer devmode_ctr;
1866 struct sec_desc_buf secdesc_ctr;
1867 union spoolss_SetPrinterInfo sinfo;
1869 ZERO_STRUCT(devmode_ctr);
1870 ZERO_STRUCT(secdesc_ctr);
1872 switch (level) {
1873 case 2: {
1874 union spoolss_PrinterInfo info;
1875 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1876 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1878 info_ctr.level = 2;
1879 info_ctr.info = sinfo;
1881 break;
1883 case 3: {
1884 struct spoolss_SetPrinterInfo3 info3;
1886 info3.sec_desc_ptr = 0;
1888 info_ctr.level = 3;
1889 info_ctr.info.info3 = &info3;
1891 break;
1893 default:
1894 return false;
1897 secdesc_ctr.sd = sd;
1899 torture_assert(tctx,
1900 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1902 return true;
1905 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1906 struct dcerpc_binding_handle *b,
1907 struct policy_handle *handle)
1909 union spoolss_PrinterInfo info;
1910 struct security_descriptor *sd1, *sd2;
1911 int i;
1913 /* just compare level 2 and level 3 */
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1917 sd1 = info.info2.secdesc;
1919 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1921 sd2 = info.info3.secdesc;
1923 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1924 "SD level 2 != SD level 3");
1927 /* query level 2, set level 2, query level 2 */
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd1 = info.info2.secdesc;
1933 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1935 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1937 sd2 = info.info2.secdesc;
1938 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1939 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1940 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1943 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1944 "SD level 2 != SD level 2 after SD has been set via level 2");
1947 /* query level 2, set level 3, query level 2 */
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd1 = info.info2.secdesc;
1953 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1955 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1957 sd2 = info.info2.secdesc;
1959 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1960 "SD level 2 != SD level 2 after SD has been set via level 3");
1962 /* set modified sd level 3, query level 2 */
1964 for (i=0; i < 93; i++) {
1965 struct security_ace a;
1966 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1967 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1968 a.flags = 0;
1969 a.size = 0; /* autogenerated */
1970 a.access_mask = 0;
1971 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1972 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1975 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1977 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1978 sd2 = info.info2.secdesc;
1980 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1981 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1982 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1985 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1986 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1989 return true;
1993 * wrapper call that saves original sd, runs tests, and restores sd
1996 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1997 struct dcerpc_binding_handle *b,
1998 struct policy_handle *handle)
2000 union spoolss_PrinterInfo info;
2001 struct security_descriptor *sd;
2002 bool ret = true;
2004 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2006 /* save original sd */
2008 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2009 "failed to get initial security descriptor");
2011 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2013 /* run tests */
2015 ret = test_PrinterInfo_SDs(tctx, b, handle);
2017 /* restore original sd */
2019 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2020 "failed to restore initial security descriptor");
2022 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2023 ret ? "succeeded" : "failed");
2026 return ret;
2029 static bool test_devmode_set_level(struct torture_context *tctx,
2030 struct dcerpc_binding_handle *b,
2031 struct policy_handle *handle,
2032 uint32_t level,
2033 struct spoolss_DeviceMode *devmode)
2035 struct spoolss_SetPrinterInfoCtr info_ctr;
2036 struct spoolss_DevmodeContainer devmode_ctr;
2037 struct sec_desc_buf secdesc_ctr;
2038 union spoolss_SetPrinterInfo sinfo;
2040 ZERO_STRUCT(devmode_ctr);
2041 ZERO_STRUCT(secdesc_ctr);
2043 switch (level) {
2044 case 2: {
2045 union spoolss_PrinterInfo info;
2046 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2047 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2049 info_ctr.level = 2;
2050 info_ctr.info = sinfo;
2052 break;
2054 case 8: {
2055 struct spoolss_SetPrinterInfo8 info8;
2057 info8.devmode_ptr = 0;
2059 info_ctr.level = 8;
2060 info_ctr.info.info8 = &info8;
2062 break;
2064 default:
2065 return false;
2068 devmode_ctr.devmode = devmode;
2070 torture_assert(tctx,
2071 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2073 return true;
2077 static bool test_devicemode_equal(struct torture_context *tctx,
2078 const struct spoolss_DeviceMode *d1,
2079 const struct spoolss_DeviceMode *d2)
2081 if (d1 == d2) {
2082 return true;
2085 if (!d1 || !d2) {
2086 torture_comment(tctx, "%s\n", __location__);
2087 return false;
2089 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2090 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2091 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2092 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2093 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2094 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2095 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2096 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2097 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2098 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2099 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2100 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2101 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2102 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2103 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2104 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2105 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2106 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2107 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2108 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2109 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2110 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2111 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2112 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2113 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2114 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2115 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2116 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2117 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2118 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2119 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2121 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2122 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2123 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2125 return true;
2128 static bool test_devicemode_full(struct torture_context *tctx,
2129 struct dcerpc_binding_handle *b,
2130 struct policy_handle *handle)
2132 struct spoolss_SetPrinter s;
2133 struct spoolss_GetPrinter q;
2134 struct spoolss_GetPrinter q0;
2135 struct spoolss_SetPrinterInfoCtr info_ctr;
2136 struct spoolss_SetPrinterInfo8 info8;
2137 union spoolss_PrinterInfo info;
2138 struct spoolss_DevmodeContainer devmode_ctr;
2139 struct sec_desc_buf secdesc_ctr;
2140 uint32_t needed;
2141 bool ret = true;
2142 NTSTATUS status;
2144 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2145 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2146 q.in.level = lvl1; \
2147 TESTGETCALL(GetPrinter, q) \
2148 info_ctr.level = lvl1; \
2149 if (lvl1 == 2) {\
2150 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2151 } else if (lvl1 == 8) {\
2152 info_ctr.info.info ## lvl1 = &info8; \
2154 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2155 devmode_ctr.devmode->field1 = value; \
2156 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2157 if (W_ERROR_IS_OK(expected_result)) { \
2158 TESTGETCALL(GetPrinter, q) \
2159 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2160 q.in.level = lvl2; \
2161 TESTGETCALL(GetPrinter, q) \
2162 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2164 } while (0)
2166 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2167 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2168 } while (0)
2170 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2171 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2172 } while (0)
2174 ZERO_STRUCT(devmode_ctr);
2175 ZERO_STRUCT(secdesc_ctr);
2176 ZERO_STRUCT(info8);
2178 s.in.handle = handle;
2179 s.in.command = 0;
2180 s.in.info_ctr = &info_ctr;
2181 s.in.devmode_ctr = &devmode_ctr;
2182 s.in.secdesc_ctr = &secdesc_ctr;
2184 q.in.handle = handle;
2185 q.out.info = &info;
2186 q0 = q;
2188 #if 0
2189 const char *devicename;/* [charset(UTF16)] */
2190 enum spoolss_DeviceModeSpecVersion specversion;
2191 uint16_t driverversion;
2192 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2193 uint32_t fields;
2194 #endif
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2199 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2201 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2202 torture_assert(tctx,
2203 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2204 "failed to set devmode");
2206 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2207 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2209 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2210 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2211 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2212 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2213 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2214 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2215 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2216 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2217 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2218 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2219 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2220 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2221 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2222 #if 0
2223 const char *formname;/* [charset(UTF16)] */
2224 #endif
2225 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2226 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2227 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2228 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2229 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2230 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2231 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2232 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2233 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2234 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2237 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2238 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2240 return ret;
2243 static bool call_OpenPrinterEx(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 const char *name,
2246 struct spoolss_DeviceMode *devmode,
2247 struct policy_handle *handle);
2249 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2250 struct dcerpc_pipe *p,
2251 struct policy_handle *handle,
2252 const char *name)
2254 union spoolss_PrinterInfo info;
2255 struct spoolss_DeviceMode *devmode;
2256 struct spoolss_DeviceMode *devmode2;
2257 struct policy_handle handle_devmode;
2258 struct dcerpc_binding_handle *b = p->binding_handle;
2260 /* simply compare level8 and level2 devmode */
2262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264 devmode = info.info8.devmode;
2266 if (devmode && devmode->size == 0) {
2267 torture_fail(tctx,
2268 "devmode of zero size!");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2273 devmode2 = info.info2.devmode;
2275 if (devmode2 && devmode2->size == 0) {
2276 torture_fail(tctx,
2277 "devmode of zero size!");
2280 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2281 "DM level 8 != DM level 2");
2284 /* set devicemode level 8 and see if it persists */
2286 devmode->copies = 93;
2287 devmode->formname = talloc_strdup(tctx, "Legal");
2289 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2291 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2293 devmode2 = info.info8.devmode;
2295 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2296 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2298 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2300 devmode2 = info.info2.devmode;
2302 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2303 "modified DM level 8 != DM level 2");
2306 /* set devicemode level 2 and see if it persists */
2308 devmode->copies = 39;
2309 devmode->formname = talloc_strdup(tctx, "Executive");
2311 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2313 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2315 devmode2 = info.info8.devmode;
2317 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2318 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2320 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2322 devmode2 = info.info2.devmode;
2324 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2325 "modified DM level 8 != DM level 2");
2328 /* check every single bit in public part of devicemode */
2330 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2331 "failed to set every single devicemode component");
2334 /* change formname upon open and see if it persists in getprinter calls */
2336 devmode->formname = talloc_strdup(tctx, "A4");
2337 devmode->copies = 42;
2339 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2340 "failed to open printer handle");
2342 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2344 devmode2 = info.info8.devmode;
2346 if (strequal(devmode->devicename, devmode2->devicename)) {
2347 torture_warning(tctx, "devicenames are the same\n");
2348 } else {
2349 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2350 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2353 if (strequal(devmode->formname, devmode2->formname)) {
2354 torture_warning(tctx, "formname are the same\n");
2355 } else {
2356 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2357 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2360 if (devmode->copies == devmode2->copies) {
2361 torture_warning(tctx, "copies are the same\n");
2362 } else {
2363 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2364 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2367 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2369 devmode2 = info.info2.devmode;
2371 if (strequal(devmode->devicename, devmode2->devicename)) {
2372 torture_warning(tctx, "devicenames are the same\n");
2373 } else {
2374 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2375 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2378 if (strequal(devmode->formname, devmode2->formname)) {
2379 torture_warning(tctx, "formname is the same\n");
2380 } else {
2381 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2382 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2385 if (devmode->copies == devmode2->copies) {
2386 torture_warning(tctx, "copies are the same\n");
2387 } else {
2388 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2389 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2392 test_ClosePrinter(tctx, b, &handle_devmode);
2394 return true;
2398 * wrapper call that saves original devmode, runs tests, and restores devmode
2401 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2402 struct dcerpc_pipe *p,
2403 struct policy_handle *handle,
2404 const char *name,
2405 struct spoolss_DeviceMode *addprinter_devmode)
2407 union spoolss_PrinterInfo info;
2408 struct spoolss_DeviceMode *devmode;
2409 bool ret = true;
2410 struct dcerpc_binding_handle *b = p->binding_handle;
2412 torture_comment(tctx, "Testing Printer Devicemodes\n");
2414 /* save original devmode */
2416 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2417 "failed to get initial global devicemode");
2419 devmode = info.info8.devmode;
2421 if (devmode && devmode->size == 0) {
2422 torture_fail(tctx,
2423 "devmode of zero size!");
2426 if (addprinter_devmode) {
2427 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2428 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2432 /* run tests */
2434 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2436 /* restore original devmode */
2438 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2439 "failed to restore initial global device mode");
2441 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2442 ret ? "succeeded" : "failed");
2445 return ret;
2448 bool test_ClosePrinter(struct torture_context *tctx,
2449 struct dcerpc_binding_handle *b,
2450 struct policy_handle *handle)
2452 NTSTATUS status;
2453 struct spoolss_ClosePrinter r;
2455 r.in.handle = handle;
2456 r.out.handle = handle;
2458 torture_comment(tctx, "Testing ClosePrinter\n");
2460 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2464 return true;
2467 static bool test_GetForm_args(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 const char *form_name,
2471 uint32_t level,
2472 union spoolss_FormInfo *info_p)
2474 NTSTATUS status;
2475 struct spoolss_GetForm r;
2476 uint32_t needed;
2478 r.in.handle = handle;
2479 r.in.form_name = form_name;
2480 r.in.level = level;
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2485 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2487 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2488 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2492 r.in.buffer = &blob;
2493 r.in.offered = needed;
2494 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 torture_assert(tctx, r.out.info, "No form info returned");
2502 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2504 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2506 if (info_p) {
2507 *info_p = *r.out.info;
2510 return true;
2513 static bool test_GetForm(struct torture_context *tctx,
2514 struct dcerpc_binding_handle *b,
2515 struct policy_handle *handle,
2516 const char *form_name,
2517 uint32_t level)
2519 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2522 static bool test_EnumForms(struct torture_context *tctx,
2523 struct dcerpc_binding_handle *b,
2524 struct policy_handle *handle,
2525 bool print_server,
2526 uint32_t level,
2527 uint32_t *count_p,
2528 union spoolss_FormInfo **info_p)
2530 struct spoolss_EnumForms r;
2531 uint32_t needed;
2532 uint32_t count;
2533 union spoolss_FormInfo *info;
2535 r.in.handle = handle;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2540 r.out.count = &count;
2541 r.out.info = &info;
2543 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2545 torture_assert_ntstatus_ok(tctx,
2546 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2547 "EnumForms failed");
2549 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2550 torture_skip(tctx, "EnumForms level 2 not supported");
2553 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2554 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2557 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2558 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2559 r.in.buffer = &blob;
2560 r.in.offered = needed;
2562 torture_assert_ntstatus_ok(tctx,
2563 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2564 "EnumForms failed");
2566 torture_assert(tctx, info, "No forms returned");
2569 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2571 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2573 if (info_p) {
2574 *info_p = info;
2576 if (count_p) {
2577 *count_p = count;
2580 return true;
2583 static bool test_EnumForms_all(struct torture_context *tctx,
2584 struct dcerpc_binding_handle *b,
2585 struct policy_handle *handle,
2586 bool print_server)
2588 uint32_t levels[] = { 1, 2 };
2589 int i, j;
2591 for (i=0; i<ARRAY_SIZE(levels); i++) {
2593 uint32_t count = 0;
2594 union spoolss_FormInfo *info = NULL;
2596 torture_assert(tctx,
2597 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2598 "failed to enum forms");
2600 for (j = 0; j < count; j++) {
2601 if (!print_server) {
2602 torture_assert(tctx,
2603 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2604 "failed to get form");
2609 return true;
2612 static bool test_EnumForms_find_one(struct torture_context *tctx,
2613 struct dcerpc_binding_handle *b,
2614 struct policy_handle *handle,
2615 bool print_server,
2616 const char *form_name)
2618 union spoolss_FormInfo *info;
2619 uint32_t count;
2620 bool found = false;
2621 int i;
2623 torture_assert(tctx,
2624 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2625 "failed to enumerate forms");
2627 for (i=0; i<count; i++) {
2628 if (strequal(form_name, info[i].info1.form_name)) {
2629 found = true;
2630 break;
2634 return found;
2637 static bool test_DeleteForm(struct torture_context *tctx,
2638 struct dcerpc_binding_handle *b,
2639 struct policy_handle *handle,
2640 const char *form_name,
2641 WERROR expected_result)
2643 struct spoolss_DeleteForm r;
2645 r.in.handle = handle;
2646 r.in.form_name = form_name;
2648 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2650 torture_assert_ntstatus_ok(tctx,
2651 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2652 "DeleteForm failed");
2653 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2654 "DeleteForm gave unexpected result");
2655 if (W_ERROR_IS_OK(r.out.result)) {
2656 torture_assert_ntstatus_ok(tctx,
2657 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2658 "2nd DeleteForm failed");
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2660 "2nd DeleteForm failed");
2663 return true;
2666 static bool test_AddForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 uint32_t level,
2670 union spoolss_AddFormInfo *info,
2671 WERROR expected_result)
2673 struct spoolss_AddForm r;
2675 if (level != 1) {
2676 torture_skip(tctx, "only level 1 supported");
2679 r.in.handle = handle;
2680 r.in.level = level;
2681 r.in.info = *info;
2683 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2684 r.in.info.info1->form_name, r.in.level,
2685 r.in.info.info1->flags);
2687 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2688 "AddForm failed");
2689 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2690 "AddForm gave unexpected result");
2692 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2693 "2nd AddForm failed");
2694 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2695 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2696 "2nd AddForm gave unexpected result");
2697 } else {
2698 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2699 "2nd AddForm gave unexpected result");
2702 return true;
2705 static bool test_SetForm(struct torture_context *tctx,
2706 struct dcerpc_binding_handle *b,
2707 struct policy_handle *handle,
2708 const char *form_name,
2709 uint32_t level,
2710 union spoolss_AddFormInfo *info)
2712 struct spoolss_SetForm r;
2714 r.in.handle = handle;
2715 r.in.form_name = form_name;
2716 r.in.level = level;
2717 r.in.info = *info;
2719 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2720 form_name, r.in.level);
2722 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2723 "SetForm failed");
2725 torture_assert_werr_ok(tctx, r.out.result,
2726 "SetForm failed");
2728 return true;
2731 static bool test_GetForm_winreg(struct torture_context *tctx,
2732 struct dcerpc_binding_handle *b,
2733 struct policy_handle *handle,
2734 const char *key_name,
2735 const char *form_name,
2736 enum winreg_Type *w_type,
2737 uint32_t *w_size,
2738 uint32_t *w_length,
2739 uint8_t **w_data);
2741 static bool test_Forms_args(struct torture_context *tctx,
2742 struct dcerpc_binding_handle *b,
2743 struct policy_handle *handle,
2744 bool print_server,
2745 const char *printer_name,
2746 struct dcerpc_binding_handle *winreg_handle,
2747 struct policy_handle *hive_handle,
2748 const char *form_name,
2749 struct spoolss_AddFormInfo1 *info1,
2750 WERROR expected_add_result,
2751 WERROR expected_delete_result)
2753 union spoolss_FormInfo info;
2754 union spoolss_AddFormInfo add_info;
2756 enum winreg_Type w_type;
2757 uint32_t w_size;
2758 uint32_t w_length;
2759 uint8_t *w_data;
2761 add_info.info1 = info1;
2763 torture_assert(tctx,
2764 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2765 "failed to add form");
2767 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2769 struct spoolss_FormInfo1 i1;
2771 torture_assert(tctx,
2772 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2773 "failed to get form via winreg");
2775 i1.size.width = IVAL(w_data, 0);
2776 i1.size.height = IVAL(w_data, 4);
2777 i1.area.left = IVAL(w_data, 8);
2778 i1.area.top = IVAL(w_data, 12);
2779 i1.area.right = IVAL(w_data, 16);
2780 i1.area.bottom = IVAL(w_data, 20);
2781 /* skip index here */
2782 i1.flags = IVAL(w_data, 28);
2784 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2785 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2786 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2787 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2788 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2789 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2790 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2791 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2792 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2793 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2796 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2797 torture_assert(tctx,
2798 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2799 "failed to get added form");
2801 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2802 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2803 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2804 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2805 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2806 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2807 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2809 if (winreg_handle && hive_handle) {
2811 struct spoolss_FormInfo1 i1;
2813 i1.size.width = IVAL(w_data, 0);
2814 i1.size.height = IVAL(w_data, 4);
2815 i1.area.left = IVAL(w_data, 8);
2816 i1.area.top = IVAL(w_data, 12);
2817 i1.area.right = IVAL(w_data, 16);
2818 i1.area.bottom = IVAL(w_data, 20);
2819 /* skip index here */
2820 i1.flags = IVAL(w_data, 28);
2822 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2823 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2824 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2825 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2826 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2827 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2828 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2831 add_info.info1->size.width = 1234;
2833 torture_assert(tctx,
2834 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2835 "failed to set form");
2836 torture_assert(tctx,
2837 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2838 "failed to get setted form");
2840 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2843 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2844 torture_assert(tctx,
2845 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2846 "Newly added form not found in enum call");
2849 torture_assert(tctx,
2850 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2851 "failed to delete form");
2853 return true;
2856 static bool test_Forms(struct torture_context *tctx,
2857 struct dcerpc_binding_handle *b,
2858 struct policy_handle *handle,
2859 bool print_server,
2860 const char *printer_name,
2861 struct dcerpc_binding_handle *winreg_handle,
2862 struct policy_handle *hive_handle)
2864 const struct spoolss_FormSize size = {
2865 .width = 50,
2866 .height = 25
2868 const struct spoolss_FormArea area = {
2869 .left = 5,
2870 .top = 10,
2871 .right = 45,
2872 .bottom = 15
2874 int i;
2876 struct {
2877 struct spoolss_AddFormInfo1 info1;
2878 WERROR expected_add_result;
2879 WERROR expected_delete_result;
2880 } forms[] = {
2882 .info1 = {
2883 .flags = SPOOLSS_FORM_USER,
2884 .form_name = "testform_user",
2885 .size = size,
2886 .area = area,
2888 .expected_add_result = WERR_OK,
2889 .expected_delete_result = WERR_OK
2892 weird, we can add a builtin form but we can never remove it
2893 again - gd
2896 .info1 = {
2897 .flags = SPOOLSS_FORM_BUILTIN,
2898 .form_name = "testform_builtin",
2899 .size = size,
2900 .area = area,
2902 .expected_add_result = WERR_OK,
2903 .expected_delete_result = WERR_INVALID_PARAM,
2907 .info1 = {
2908 .flags = SPOOLSS_FORM_PRINTER,
2909 .form_name = "testform_printer",
2910 .size = size,
2911 .area = area,
2913 .expected_add_result = WERR_OK,
2914 .expected_delete_result = WERR_OK
2917 .info1 = {
2918 .flags = SPOOLSS_FORM_USER,
2919 .form_name = "Letter",
2920 .size = size,
2921 .area = area,
2923 .expected_add_result = WERR_FILE_EXISTS,
2924 .expected_delete_result = WERR_INVALID_PARAM
2927 .info1 = {
2928 .flags = SPOOLSS_FORM_BUILTIN,
2929 .form_name = "Letter",
2930 .size = size,
2931 .area = area,
2933 .expected_add_result = WERR_FILE_EXISTS,
2934 .expected_delete_result = WERR_INVALID_PARAM
2937 .info1 = {
2938 .flags = SPOOLSS_FORM_PRINTER,
2939 .form_name = "Letter",
2940 .size = size,
2941 .area = area,
2943 .expected_add_result = WERR_FILE_EXISTS,
2944 .expected_delete_result = WERR_INVALID_PARAM
2947 .info1 = {
2948 .flags = 12345,
2949 .form_name = "invalid_flags",
2950 .size = size,
2951 .area = area,
2953 .expected_add_result = WERR_INVALID_PARAM,
2954 .expected_delete_result = WERR_INVALID_FORM_NAME
2959 for (i=0; i < ARRAY_SIZE(forms); i++) {
2960 torture_assert(tctx,
2961 test_Forms_args(tctx, b, handle, print_server, printer_name,
2962 winreg_handle, hive_handle,
2963 forms[i].info1.form_name,
2964 &forms[i].info1,
2965 forms[i].expected_add_result,
2966 forms[i].expected_delete_result),
2967 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2970 return true;
2973 static bool test_EnumPorts_old(struct torture_context *tctx,
2974 void *private_data)
2976 struct test_spoolss_context *ctx =
2977 talloc_get_type_abort(private_data, struct test_spoolss_context);
2979 NTSTATUS status;
2980 struct spoolss_EnumPorts r;
2981 uint32_t needed;
2982 uint32_t count;
2983 union spoolss_PortInfo *info;
2984 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2985 struct dcerpc_binding_handle *b = p->binding_handle;
2987 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2988 dcerpc_server_name(p));
2989 r.in.level = 2;
2990 r.in.buffer = NULL;
2991 r.in.offered = 0;
2992 r.out.needed = &needed;
2993 r.out.count = &count;
2994 r.out.info = &info;
2996 torture_comment(tctx, "Testing EnumPorts\n");
2998 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3000 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3002 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3003 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3004 r.in.buffer = &blob;
3005 r.in.offered = needed;
3007 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3008 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3009 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3011 torture_assert(tctx, info, "No ports returned");
3014 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3016 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3018 return true;
3021 static bool test_AddPort(struct torture_context *tctx,
3022 void *private_data)
3024 struct test_spoolss_context *ctx =
3025 talloc_get_type_abort(private_data, struct test_spoolss_context);
3027 NTSTATUS status;
3028 struct spoolss_AddPort r;
3029 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3030 struct dcerpc_binding_handle *b = p->binding_handle;
3032 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3033 dcerpc_server_name(p));
3034 r.in.unknown = 0;
3035 r.in.monitor_name = "foo";
3037 torture_comment(tctx, "Testing AddPort\n");
3039 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3041 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3043 /* win2k3 returns WERR_NOT_SUPPORTED */
3045 #if 0
3047 if (!W_ERROR_IS_OK(r.out.result)) {
3048 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3049 return false;
3052 #endif
3054 return true;
3057 static bool test_GetJob_args(struct torture_context *tctx,
3058 struct dcerpc_binding_handle *b,
3059 struct policy_handle *handle,
3060 uint32_t job_id,
3061 uint32_t level,
3062 union spoolss_JobInfo *info_p)
3064 NTSTATUS status;
3065 struct spoolss_GetJob r;
3066 union spoolss_JobInfo info;
3067 uint32_t needed;
3069 r.in.handle = handle;
3070 r.in.job_id = job_id;
3071 r.in.level = level;
3072 r.in.buffer = NULL;
3073 r.in.offered = 0;
3074 r.out.needed = &needed;
3075 r.out.info = &info;
3077 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3079 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3080 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3081 if (level == 0) {
3082 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3085 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3086 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3087 r.in.buffer = &blob;
3088 r.in.offered = needed;
3090 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3091 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3094 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3095 torture_assert(tctx, r.out.info, "No job info returned");
3097 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3099 if (info_p) {
3100 *info_p = *r.out.info;
3103 return true;
3106 static bool test_GetJob(struct torture_context *tctx,
3107 struct dcerpc_binding_handle *b,
3108 struct policy_handle *handle,
3109 uint32_t job_id)
3111 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3112 uint32_t i;
3114 for (i=0; i < ARRAY_SIZE(levels); i++) {
3115 torture_assert(tctx,
3116 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3117 "GetJob failed");
3120 return true;
3123 static bool test_SetJob(struct torture_context *tctx,
3124 struct dcerpc_binding_handle *b,
3125 struct policy_handle *handle,
3126 uint32_t job_id,
3127 struct spoolss_JobInfoContainer *ctr,
3128 enum spoolss_JobControl command)
3130 NTSTATUS status;
3131 struct spoolss_SetJob r;
3133 r.in.handle = handle;
3134 r.in.job_id = job_id;
3135 r.in.ctr = ctr;
3136 r.in.command = command;
3138 switch (command) {
3139 case SPOOLSS_JOB_CONTROL_PAUSE:
3140 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3141 break;
3142 case SPOOLSS_JOB_CONTROL_RESUME:
3143 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3144 break;
3145 case SPOOLSS_JOB_CONTROL_CANCEL:
3146 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3147 break;
3148 case SPOOLSS_JOB_CONTROL_RESTART:
3149 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3150 break;
3151 case SPOOLSS_JOB_CONTROL_DELETE:
3152 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3153 break;
3154 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3155 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3156 break;
3157 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3158 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3159 break;
3160 case SPOOLSS_JOB_CONTROL_RETAIN:
3161 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3162 break;
3163 case SPOOLSS_JOB_CONTROL_RELEASE:
3164 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3165 break;
3166 default:
3167 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3168 break;
3171 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3172 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3173 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3175 return true;
3178 static bool test_AddJob(struct torture_context *tctx,
3179 struct dcerpc_binding_handle *b,
3180 struct policy_handle *handle)
3182 NTSTATUS status;
3183 struct spoolss_AddJob r;
3184 uint32_t needed;
3186 r.in.level = 0;
3187 r.in.handle = handle;
3188 r.in.offered = 0;
3189 r.out.needed = &needed;
3190 r.in.buffer = r.out.buffer = NULL;
3192 torture_comment(tctx, "Testing AddJob\n");
3194 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3195 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3197 r.in.level = 1;
3199 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3200 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3202 return true;
3206 static bool test_EnumJobs_args(struct torture_context *tctx,
3207 struct dcerpc_binding_handle *b,
3208 struct policy_handle *handle,
3209 uint32_t level,
3210 uint32_t *count_p,
3211 union spoolss_JobInfo **info_p)
3213 NTSTATUS status;
3214 struct spoolss_EnumJobs r;
3215 uint32_t needed;
3216 uint32_t count;
3217 union spoolss_JobInfo *info;
3219 r.in.handle = handle;
3220 r.in.firstjob = 0;
3221 r.in.numjobs = 0xffffffff;
3222 r.in.level = level;
3223 r.in.buffer = NULL;
3224 r.in.offered = 0;
3225 r.out.needed = &needed;
3226 r.out.count = &count;
3227 r.out.info = &info;
3229 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3231 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3233 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3235 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3236 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3237 r.in.buffer = &blob;
3238 r.in.offered = needed;
3240 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3242 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3243 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3244 torture_assert(tctx, info, "No jobs returned");
3246 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3248 } else {
3249 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3252 if (count_p) {
3253 *count_p = count;
3255 if (info_p) {
3256 *info_p = info;
3259 return true;
3262 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3263 struct dcerpc_binding_handle *b,
3264 struct policy_handle *handle,
3265 const char *document_name,
3266 uint32_t *job_id)
3268 NTSTATUS status;
3269 struct spoolss_StartDocPrinter s;
3270 struct spoolss_DocumentInfo1 info1;
3271 struct spoolss_StartPagePrinter sp;
3272 struct spoolss_WritePrinter w;
3273 struct spoolss_EndPagePrinter ep;
3274 struct spoolss_EndDocPrinter e;
3275 int i;
3276 uint32_t num_written;
3278 torture_comment(tctx, "Testing StartDocPrinter\n");
3280 s.in.handle = handle;
3281 s.in.level = 1;
3282 s.in.info.info1 = &info1;
3283 s.out.job_id = job_id;
3284 info1.document_name = document_name;
3285 info1.output_file = NULL;
3286 info1.datatype = "RAW";
3288 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3289 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3290 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3292 for (i=1; i < 4; i++) {
3293 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3295 sp.in.handle = handle;
3297 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3298 torture_assert_ntstatus_ok(tctx, status,
3299 "dcerpc_spoolss_StartPagePrinter failed");
3300 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3302 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3304 w.in.handle = handle;
3305 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3306 w.out.num_written = &num_written;
3308 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3309 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3310 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3312 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3314 ep.in.handle = handle;
3316 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3317 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3318 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3321 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3323 e.in.handle = handle;
3325 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3326 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3327 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3329 return true;
3332 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3333 struct dcerpc_binding_handle *b,
3334 struct policy_handle *handle,
3335 uint32_t num_jobs,
3336 uint32_t *job_ids)
3338 uint32_t count;
3339 union spoolss_JobInfo *info = NULL;
3340 int i;
3342 torture_assert(tctx,
3343 test_AddJob(tctx, b, handle),
3344 "AddJob failed");
3346 torture_assert(tctx,
3347 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3348 "EnumJobs level 1 failed");
3350 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3352 for (i=0; i < num_jobs; i++) {
3353 union spoolss_JobInfo ginfo;
3354 const char *document_name;
3355 const char *new_document_name = "any_other_docname";
3356 struct spoolss_JobInfoContainer ctr;
3357 struct spoolss_SetJobInfo1 info1;
3359 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3361 torture_assert(tctx,
3362 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3363 "failed to call test_GetJob");
3365 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3367 document_name = ginfo.info1.document_name;
3369 info1.job_id = ginfo.info1.job_id;
3370 info1.printer_name = ginfo.info1.printer_name;
3371 info1.server_name = ginfo.info1.server_name;
3372 info1.user_name = ginfo.info1.user_name;
3373 info1.document_name = new_document_name;
3374 info1.data_type = ginfo.info1.data_type;
3375 info1.text_status = ginfo.info1.text_status;
3376 info1.status = ginfo.info1.status;
3377 info1.priority = ginfo.info1.priority;
3378 info1.position = ginfo.info1.position;
3379 info1.total_pages = ginfo.info1.total_pages;
3380 info1.pages_printed = ginfo.info1.pages_printed;
3381 info1.submitted = ginfo.info1.submitted;
3383 ctr.level = 1;
3384 ctr.info.info1 = &info1;
3386 torture_assert(tctx,
3387 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3388 "failed to call test_SetJob level 1");
3390 torture_assert(tctx,
3391 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3392 "failed to call test_GetJob");
3394 if (strequal(ginfo.info1.document_name, document_name)) {
3395 torture_warning(tctx,
3396 "document_name did *NOT* change from '%s' to '%s'\n",
3397 document_name, new_document_name);
3401 for (i=0; i < num_jobs; i++) {
3402 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3403 torture_warning(tctx, "failed to pause printjob\n");
3405 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3406 torture_warning(tctx, "failed to resume printjob\n");
3410 return true;
3413 static bool test_DoPrintTest(struct torture_context *tctx,
3414 struct dcerpc_binding_handle *b,
3415 struct policy_handle *handle)
3417 bool ret = true;
3418 uint32_t num_jobs = 8;
3419 uint32_t *job_ids;
3420 int i;
3422 torture_comment(tctx, "Testing real print operations\n");
3424 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3426 for (i=0; i < num_jobs; i++) {
3427 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3430 for (i=0; i < num_jobs; i++) {
3431 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3434 if (ret == true) {
3435 torture_comment(tctx, "real print operations test succeeded\n\n");
3438 return ret;
3441 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3442 struct dcerpc_binding_handle *b,
3443 struct policy_handle *handle)
3445 bool ret = true;
3446 uint32_t num_jobs = 8;
3447 uint32_t *job_ids;
3448 int i;
3449 torture_comment(tctx, "Testing real print operations (extended)\n");
3451 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3453 for (i=0; i < num_jobs; i++) {
3454 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3457 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3459 for (i=0; i < num_jobs; i++) {
3460 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3463 if (ret == true) {
3464 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3467 return ret;
3470 static bool test_PausePrinter(struct torture_context *tctx,
3471 struct dcerpc_binding_handle *b,
3472 struct policy_handle *handle)
3474 NTSTATUS status;
3475 struct spoolss_SetPrinter r;
3476 struct spoolss_SetPrinterInfoCtr info_ctr;
3477 struct spoolss_DevmodeContainer devmode_ctr;
3478 struct sec_desc_buf secdesc_ctr;
3480 info_ctr.level = 0;
3481 info_ctr.info.info0 = NULL;
3483 ZERO_STRUCT(devmode_ctr);
3484 ZERO_STRUCT(secdesc_ctr);
3486 r.in.handle = handle;
3487 r.in.info_ctr = &info_ctr;
3488 r.in.devmode_ctr = &devmode_ctr;
3489 r.in.secdesc_ctr = &secdesc_ctr;
3490 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3492 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3494 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3496 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3498 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3500 return true;
3503 static bool test_ResumePrinter(struct torture_context *tctx,
3504 struct dcerpc_binding_handle *b,
3505 struct policy_handle *handle)
3507 NTSTATUS status;
3508 struct spoolss_SetPrinter r;
3509 struct spoolss_SetPrinterInfoCtr info_ctr;
3510 struct spoolss_DevmodeContainer devmode_ctr;
3511 struct sec_desc_buf secdesc_ctr;
3513 info_ctr.level = 0;
3514 info_ctr.info.info0 = NULL;
3516 ZERO_STRUCT(devmode_ctr);
3517 ZERO_STRUCT(secdesc_ctr);
3519 r.in.handle = handle;
3520 r.in.info_ctr = &info_ctr;
3521 r.in.devmode_ctr = &devmode_ctr;
3522 r.in.secdesc_ctr = &secdesc_ctr;
3523 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3525 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3527 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3529 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3531 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3533 return true;
3536 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3537 struct dcerpc_binding_handle *b,
3538 struct policy_handle *handle,
3539 const char *value_name,
3540 enum winreg_Type *expected_type,
3541 enum winreg_Type *type_p,
3542 uint8_t **data_p,
3543 uint32_t *needed_p)
3545 NTSTATUS status;
3546 struct spoolss_GetPrinterData r;
3547 uint32_t needed;
3548 enum winreg_Type type;
3549 union spoolss_PrinterData data;
3551 r.in.handle = handle;
3552 r.in.value_name = value_name;
3553 r.in.offered = 0;
3554 r.out.needed = &needed;
3555 r.out.type = &type;
3556 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3558 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3560 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3561 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3563 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3564 if (expected_type) {
3565 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3567 r.in.offered = needed;
3568 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3569 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3570 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3573 torture_assert_werr_ok(tctx, r.out.result,
3574 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3576 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3578 if (type_p) {
3579 *type_p = type;
3582 if (data_p) {
3583 *data_p = r.out.data;
3586 if (needed_p) {
3587 *needed_p = needed;
3590 return true;
3593 static bool test_GetPrinterData(struct torture_context *tctx,
3594 struct dcerpc_binding_handle *b,
3595 struct policy_handle *handle,
3596 const char *value_name,
3597 enum winreg_Type *type_p,
3598 uint8_t **data_p,
3599 uint32_t *needed_p)
3601 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3602 NULL, type_p, data_p, needed_p);
3605 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3606 struct dcerpc_pipe *p,
3607 struct policy_handle *handle,
3608 const char *key_name,
3609 const char *value_name,
3610 enum winreg_Type *expected_type,
3611 enum winreg_Type *type_p,
3612 uint8_t **data_p,
3613 uint32_t *needed_p)
3615 NTSTATUS status;
3616 struct spoolss_GetPrinterDataEx r;
3617 enum winreg_Type type;
3618 uint32_t needed;
3619 union spoolss_PrinterData data;
3620 struct dcerpc_binding_handle *b = p->binding_handle;
3622 r.in.handle = handle;
3623 r.in.key_name = key_name;
3624 r.in.value_name = value_name;
3625 r.in.offered = 0;
3626 r.out.type = &type;
3627 r.out.needed = &needed;
3628 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3630 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3631 r.in.key_name, r.in.value_name);
3633 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3634 if (!NT_STATUS_IS_OK(status)) {
3635 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3636 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3638 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3641 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3642 if (expected_type) {
3643 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3645 r.in.offered = needed;
3646 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3647 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3648 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3651 torture_assert_werr_ok(tctx, r.out.result,
3652 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3654 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3656 if (type_p) {
3657 *type_p = type;
3660 if (data_p) {
3661 *data_p = r.out.data;
3664 if (needed_p) {
3665 *needed_p = needed;
3668 return true;
3671 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3672 struct dcerpc_pipe *p,
3673 struct policy_handle *handle,
3674 const char *key_name,
3675 const char *value_name,
3676 enum winreg_Type *type_p,
3677 uint8_t **data_p,
3678 uint32_t *needed_p)
3680 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3681 NULL, type_p, data_p, needed_p);
3684 static bool test_get_environment(struct torture_context *tctx,
3685 struct dcerpc_binding_handle *b,
3686 struct policy_handle *handle,
3687 const char **architecture)
3689 DATA_BLOB blob;
3690 enum winreg_Type type;
3691 uint8_t *data;
3692 uint32_t needed;
3694 torture_assert(tctx,
3695 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3696 "failed to get Architecture");
3698 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3700 blob = data_blob_const(data, needed);
3701 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3703 return true;
3706 static bool test_GetPrinterData_list(struct torture_context *tctx,
3707 void *private_data)
3709 struct test_spoolss_context *ctx =
3710 talloc_get_type_abort(private_data, struct test_spoolss_context);
3711 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3712 struct dcerpc_binding_handle *b = p->binding_handle;
3713 const char *list[] = {
3714 "W3SvcInstalled",
3715 "BeepEnabled",
3716 "EventLog",
3717 /* "NetPopup", not on w2k8 */
3718 /* "NetPopupToComputer", not on w2k8 */
3719 "MajorVersion",
3720 "MinorVersion",
3721 "DefaultSpoolDirectory",
3722 "Architecture",
3723 "DsPresent",
3724 "OSVersion",
3725 /* "OSVersionEx", not on s3 */
3726 "DNSMachineName"
3728 int i;
3730 for (i=0; i < ARRAY_SIZE(list); i++) {
3731 enum winreg_Type type, type_ex;
3732 uint8_t *data, *data_ex;
3733 uint32_t needed, needed_ex;
3735 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3736 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3737 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3738 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3739 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3740 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3741 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3744 return true;
3747 static bool test_EnumPrinterData(struct torture_context *tctx,
3748 struct dcerpc_pipe *p,
3749 struct policy_handle *handle,
3750 uint32_t enum_index,
3751 uint32_t value_offered,
3752 uint32_t data_offered,
3753 enum winreg_Type *type_p,
3754 uint32_t *value_needed_p,
3755 uint32_t *data_needed_p,
3756 const char **value_name_p,
3757 uint8_t **data_p,
3758 WERROR *result_p)
3760 struct spoolss_EnumPrinterData r;
3761 uint32_t data_needed;
3762 uint32_t value_needed;
3763 enum winreg_Type type;
3764 struct dcerpc_binding_handle *b = p->binding_handle;
3766 r.in.handle = handle;
3767 r.in.enum_index = enum_index;
3768 r.in.value_offered = value_offered;
3769 r.in.data_offered = data_offered;
3770 r.out.data_needed = &data_needed;
3771 r.out.value_needed = &value_needed;
3772 r.out.type = &type;
3773 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3774 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3776 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3778 torture_assert_ntstatus_ok(tctx,
3779 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3780 "EnumPrinterData failed");
3782 if (type_p) {
3783 *type_p = type;
3785 if (value_needed_p) {
3786 *value_needed_p = value_needed;
3788 if (data_needed_p) {
3789 *data_needed_p = data_needed;
3791 if (value_name_p) {
3792 *value_name_p = r.out.value_name;
3794 if (data_p) {
3795 *data_p = r.out.data;
3797 if (result_p) {
3798 *result_p = r.out.result;
3801 return true;
3805 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3806 struct dcerpc_pipe *p,
3807 struct policy_handle *handle)
3809 uint32_t enum_index = 0;
3810 enum winreg_Type type;
3811 uint32_t value_needed;
3812 uint32_t data_needed;
3813 uint8_t *data;
3814 const char *value_name;
3815 WERROR result;
3817 torture_comment(tctx, "Testing EnumPrinterData\n");
3819 do {
3820 torture_assert(tctx,
3821 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3822 &type, &value_needed, &data_needed,
3823 &value_name, &data, &result),
3824 "EnumPrinterData failed");
3826 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3827 break;
3830 torture_assert(tctx,
3831 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3832 &type, &value_needed, &data_needed,
3833 &value_name, &data, &result),
3834 "EnumPrinterData failed");
3836 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3837 break;
3840 enum_index++;
3842 } while (W_ERROR_IS_OK(result));
3844 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3846 return true;
3849 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3850 struct dcerpc_binding_handle *b,
3851 struct policy_handle *handle,
3852 const char *key_name,
3853 uint32_t *count_p,
3854 struct spoolss_PrinterEnumValues **info_p)
3856 struct spoolss_EnumPrinterDataEx r;
3857 struct spoolss_PrinterEnumValues *info;
3858 uint32_t needed;
3859 uint32_t count;
3861 r.in.handle = handle;
3862 r.in.key_name = key_name;
3863 r.in.offered = 0;
3864 r.out.needed = &needed;
3865 r.out.count = &count;
3866 r.out.info = &info;
3868 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3870 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3871 "EnumPrinterDataEx failed");
3872 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3873 r.in.offered = needed;
3874 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3875 "EnumPrinterDataEx failed");
3878 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3880 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3882 if (count_p) {
3883 *count_p = count;
3885 if (info_p) {
3886 *info_p = info;
3889 return true;
3892 static bool test_SetPrinterData(struct torture_context *tctx,
3893 struct dcerpc_binding_handle *b,
3894 struct policy_handle *handle,
3895 const char *value_name,
3896 enum winreg_Type type,
3897 uint8_t *data,
3898 uint32_t offered);
3899 static bool test_DeletePrinterData(struct torture_context *tctx,
3900 struct dcerpc_binding_handle *b,
3901 struct policy_handle *handle,
3902 const char *value_name);
3904 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3905 struct dcerpc_pipe *p,
3906 struct policy_handle *handle)
3908 uint32_t count;
3909 struct spoolss_PrinterEnumValues *info;
3910 int i;
3911 uint32_t value_needed, data_needed;
3912 uint32_t value_offered, data_offered;
3913 WERROR result;
3914 struct dcerpc_binding_handle *b = p->binding_handle;
3916 enum winreg_Type type;
3917 DATA_BLOB blob;
3919 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3921 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3922 type = REG_SZ;
3924 torture_assert(tctx,
3925 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3926 "SetPrinterData failed");
3928 blob = data_blob_string_const("torture_data2");
3930 torture_assert(tctx,
3931 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3932 "SetPrinterData failed");
3934 blob = data_blob_talloc(tctx, NULL, 4);
3935 SIVAL(blob.data, 0, 0x11223344);
3937 torture_assert(tctx,
3938 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3939 "SetPrinterData failed");
3941 torture_assert(tctx,
3942 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3943 "failed to call EnumPrinterDataEx");
3945 /* get the max sizes for value and data */
3947 torture_assert(tctx,
3948 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3949 NULL, &value_needed, &data_needed,
3950 NULL, NULL, &result),
3951 "EnumPrinterData failed");
3952 torture_assert_werr_ok(tctx, result, "unexpected result");
3954 /* check if the reply from the EnumPrinterData really matches max values */
3956 for (i=0; i < count; i++) {
3957 if (info[i].value_name_len > value_needed) {
3958 torture_fail(tctx,
3959 talloc_asprintf(tctx,
3960 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3961 info[i].value_name_len, value_needed));
3963 if (info[i].data_length > data_needed) {
3964 torture_fail(tctx,
3965 talloc_asprintf(tctx,
3966 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3967 info[i].data_length, data_needed));
3971 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3972 * sort or not sort the replies by value name, we should be able to do
3973 * the following entry comparison */
3975 data_offered = data_needed;
3976 value_offered = value_needed;
3978 for (i=0; i < count; i++) {
3980 const char *value_name;
3981 uint8_t *data;
3983 torture_assert(tctx,
3984 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3985 &type, &value_needed, &data_needed,
3986 &value_name, &data, &result),
3987 "EnumPrinterData failed");
3989 if (i -1 == count) {
3990 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3991 "unexpected result");
3992 break;
3993 } else {
3994 torture_assert_werr_ok(tctx, result, "unexpected result");
3997 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3998 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3999 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4000 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4001 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4004 torture_assert(tctx,
4005 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4006 "DeletePrinterData failed");
4007 torture_assert(tctx,
4008 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4009 "DeletePrinterData failed");
4010 torture_assert(tctx,
4011 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4012 "DeletePrinterData failed");
4014 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4016 return true;
4019 static bool test_DeletePrinterData(struct torture_context *tctx,
4020 struct dcerpc_binding_handle *b,
4021 struct policy_handle *handle,
4022 const char *value_name)
4024 NTSTATUS status;
4025 struct spoolss_DeletePrinterData r;
4027 r.in.handle = handle;
4028 r.in.value_name = value_name;
4030 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4031 r.in.value_name);
4033 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4035 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4036 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4038 return true;
4041 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4042 struct dcerpc_binding_handle *b,
4043 struct policy_handle *handle,
4044 const char *key_name,
4045 const char *value_name)
4047 struct spoolss_DeletePrinterDataEx r;
4049 r.in.handle = handle;
4050 r.in.key_name = key_name;
4051 r.in.value_name = value_name;
4053 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4054 r.in.key_name, r.in.value_name);
4056 torture_assert_ntstatus_ok(tctx,
4057 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4058 "DeletePrinterDataEx failed");
4059 torture_assert_werr_ok(tctx, r.out.result,
4060 "DeletePrinterDataEx failed");
4062 return true;
4065 static bool test_DeletePrinterKey(struct torture_context *tctx,
4066 struct dcerpc_binding_handle *b,
4067 struct policy_handle *handle,
4068 const char *key_name)
4070 struct spoolss_DeletePrinterKey r;
4072 r.in.handle = handle;
4073 r.in.key_name = key_name;
4075 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4077 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4078 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4079 return true;
4082 torture_assert_ntstatus_ok(tctx,
4083 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4084 "DeletePrinterKey failed");
4085 torture_assert_werr_ok(tctx, r.out.result,
4086 "DeletePrinterKey failed");
4088 return true;
4091 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4092 struct dcerpc_binding_handle *b,
4093 struct policy_handle *handle)
4095 struct winreg_OpenHKLM r;
4097 r.in.system_name = NULL;
4098 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4099 r.out.handle = handle;
4101 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4103 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4104 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4106 return true;
4109 static void init_winreg_String(struct winreg_String *name, const char *s)
4111 name->name = s;
4112 if (s) {
4113 name->name_len = 2 * (strlen_m(s) + 1);
4114 name->name_size = name->name_len;
4115 } else {
4116 name->name_len = 0;
4117 name->name_size = 0;
4121 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4122 struct dcerpc_binding_handle *b,
4123 struct policy_handle *hive_handle,
4124 const char *keyname,
4125 uint32_t options,
4126 struct policy_handle *key_handle)
4128 struct winreg_OpenKey r;
4130 r.in.parent_handle = hive_handle;
4131 init_winreg_String(&r.in.keyname, keyname);
4132 r.in.options = options;
4133 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4134 r.out.handle = key_handle;
4136 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4138 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4139 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4141 return true;
4144 static bool test_winreg_OpenKey(struct torture_context *tctx,
4145 struct dcerpc_binding_handle *b,
4146 struct policy_handle *hive_handle,
4147 const char *keyname,
4148 struct policy_handle *key_handle)
4150 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4151 REG_OPTION_NON_VOLATILE, key_handle);
4154 static bool test_winreg_CloseKey(struct torture_context *tctx,
4155 struct dcerpc_binding_handle *b,
4156 struct policy_handle *handle)
4158 struct winreg_CloseKey r;
4160 r.in.handle = handle;
4161 r.out.handle = handle;
4163 torture_comment(tctx, "Testing winreg_CloseKey\n");
4165 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4166 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4168 return true;
4171 bool test_winreg_QueryValue(struct torture_context *tctx,
4172 struct dcerpc_binding_handle *b,
4173 struct policy_handle *handle,
4174 const char *value_name,
4175 enum winreg_Type *type_p,
4176 uint32_t *data_size_p,
4177 uint32_t *data_length_p,
4178 uint8_t **data_p)
4180 struct winreg_QueryValue r;
4181 enum winreg_Type type = REG_NONE;
4182 uint32_t data_size = 0;
4183 uint32_t data_length = 0;
4184 struct winreg_String valuename;
4185 uint8_t *data = NULL;
4187 init_winreg_String(&valuename, value_name);
4189 data = talloc_zero_array(tctx, uint8_t, 0);
4191 r.in.handle = handle;
4192 r.in.value_name = &valuename;
4193 r.in.type = &type;
4194 r.in.data_size = &data_size;
4195 r.in.data_length = &data_length;
4196 r.in.data = data;
4197 r.out.type = &type;
4198 r.out.data = data;
4199 r.out.data_size = &data_size;
4200 r.out.data_length = &data_length;
4202 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4204 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4205 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4206 *r.in.data_size = *r.out.data_size;
4207 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4208 r.in.data = data;
4209 r.out.data = data;
4210 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4212 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4214 if (type_p) {
4215 *type_p = *r.out.type;
4217 if (data_size_p) {
4218 *data_size_p = *r.out.data_size;
4220 if (data_length_p) {
4221 *data_length_p = *r.out.data_length;
4223 if (data_p) {
4224 *data_p = r.out.data;
4227 return true;
4230 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4231 struct dcerpc_binding_handle *b,
4232 struct policy_handle *handle,
4233 const char *printer_name,
4234 const char *key_name,
4235 const char *value_name,
4236 enum winreg_Type *w_type,
4237 uint32_t *w_size,
4238 uint32_t *w_length,
4239 uint8_t **w_data)
4241 const char *printer_key;
4242 struct policy_handle key_handle;
4244 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4245 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4247 torture_assert(tctx,
4248 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4250 torture_assert(tctx,
4251 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4253 torture_assert(tctx,
4254 test_winreg_CloseKey(tctx, b, &key_handle), "");
4256 return true;
4259 static bool test_GetForm_winreg(struct torture_context *tctx,
4260 struct dcerpc_binding_handle *b,
4261 struct policy_handle *handle,
4262 const char *key_name,
4263 const char *form_name,
4264 enum winreg_Type *w_type,
4265 uint32_t *w_size,
4266 uint32_t *w_length,
4267 uint8_t **w_data)
4269 struct policy_handle key_handle;
4271 torture_assert(tctx,
4272 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4274 torture_assert(tctx,
4275 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4277 torture_assert(tctx,
4278 test_winreg_CloseKey(tctx, b, &key_handle), "");
4280 return true;
4283 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4284 struct dcerpc_binding_handle *b,
4285 struct policy_handle *handle,
4286 const char *symlink_keyname,
4287 const char *symlink_destination)
4289 /* check if the first key is a symlink to the second key */
4291 enum winreg_Type w_type;
4292 uint32_t w_size;
4293 uint32_t w_length;
4294 uint8_t *w_data;
4295 struct policy_handle key_handle;
4296 DATA_BLOB blob;
4297 const char *str;
4299 if (torture_setting_bool(tctx, "samba3", false)) {
4300 torture_skip(tctx, "skip winreg symlink test against samba");
4303 torture_assert(tctx,
4304 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4305 "failed to open key link");
4307 torture_assert(tctx,
4308 test_winreg_QueryValue(tctx, b, &key_handle,
4309 "SymbolicLinkValue",
4310 &w_type, &w_size, &w_length, &w_data),
4311 "failed to query for 'SymbolicLinkValue' attribute");
4313 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4315 blob = data_blob(w_data, w_size);
4316 str = reg_val_data_string(tctx, REG_SZ, blob);
4318 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4320 torture_assert(tctx,
4321 test_winreg_CloseKey(tctx, b, &key_handle),
4322 "failed to close key link");
4324 return true;
4327 static const char *strip_unc(const char *unc)
4329 char *name;
4331 if (!unc) {
4332 return NULL;
4335 if (unc[0] == '\\' && unc[1] == '\\') {
4336 unc +=2;
4339 name = strchr(unc, '\\');
4340 if (name) {
4341 return name+1;
4344 return unc;
4347 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4348 struct dcerpc_binding_handle *b,
4349 struct policy_handle *handle,
4350 const char *printer_name,
4351 struct dcerpc_binding_handle *winreg_handle,
4352 struct policy_handle *hive_handle)
4354 union spoolss_PrinterInfo info;
4355 const char *keys[] = {
4356 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4357 TOP_LEVEL_PRINT_PRINTERS_KEY
4359 int i;
4360 const char *printername, *sharename;
4362 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4364 torture_assert(tctx,
4365 test_GetPrinter_level(tctx, b, handle, 2, &info),
4366 "failed to get printer info level 2");
4368 printername = strip_unc(info.info2.printername);
4369 sharename = strip_unc(info.info2.sharename);
4371 #define test_sz(wname, iname) \
4372 do {\
4373 DATA_BLOB blob;\
4374 const char *str;\
4375 enum winreg_Type w_type;\
4376 uint32_t w_size;\
4377 uint32_t w_length;\
4378 uint8_t *w_data;\
4379 torture_assert(tctx,\
4380 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4381 &w_type, &w_size, &w_length, &w_data),\
4382 "failed to query winreg");\
4383 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4384 blob = data_blob(w_data, w_size);\
4385 str = reg_val_data_string(tctx, REG_SZ, blob);\
4386 if (w_size == 2 && iname == NULL) {\
4387 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4388 } else {\
4389 torture_assert_str_equal(tctx, str, iname,\
4390 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4392 } while(0);
4394 #define test_dword(wname, iname) \
4395 do {\
4396 uint32_t value;\
4397 enum winreg_Type w_type;\
4398 uint32_t w_size;\
4399 uint32_t w_length;\
4400 uint8_t *w_data;\
4401 torture_assert(tctx,\
4402 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4403 &w_type, &w_size, &w_length, &w_data),\
4404 "failed to query winreg");\
4405 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4406 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4407 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4408 value = IVAL(w_data, 0);\
4409 torture_assert_int_equal(tctx, value, iname,\
4410 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4411 } while(0);
4413 #define test_binary(wname, iname) \
4414 do {\
4415 enum winreg_Type w_type;\
4416 uint32_t w_size;\
4417 uint32_t w_length;\
4418 uint8_t *w_data;\
4419 torture_assert(tctx,\
4420 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4421 &w_type, &w_size, &w_length, &w_data),\
4422 "failed to query winreg");\
4423 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4424 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4425 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4426 "binary unequal");\
4427 } while(0);
4430 #define test_dm(wname, iname) \
4431 do {\
4432 DATA_BLOB blob;\
4433 struct spoolss_DeviceMode dm;\
4434 enum ndr_err_code ndr_err;\
4435 enum winreg_Type w_type;\
4436 uint32_t w_size;\
4437 uint32_t w_length;\
4438 uint8_t *w_data;\
4439 torture_assert(tctx,\
4440 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4441 &w_type, &w_size, &w_length, &w_data),\
4442 "failed to query winreg");\
4443 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4444 blob = data_blob(w_data, w_size);\
4445 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4446 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4447 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4448 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4449 "dm unequal");\
4450 } while(0);
4452 #define test_sd(wname, iname) \
4453 do {\
4454 DATA_BLOB blob;\
4455 struct security_descriptor sd;\
4456 enum ndr_err_code ndr_err;\
4457 enum winreg_Type w_type;\
4458 uint32_t w_size;\
4459 uint32_t w_length;\
4460 uint8_t *w_data;\
4461 torture_assert(tctx,\
4462 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4463 &w_type, &w_size, &w_length, &w_data),\
4464 "failed to query winreg");\
4465 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4466 blob = data_blob(w_data, w_size);\
4467 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4468 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4469 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4470 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4471 "sd unequal");\
4472 } while(0);
4474 #define test_multi_sz(wname, iname) \
4475 do {\
4476 DATA_BLOB blob;\
4477 const char **array;\
4478 enum winreg_Type w_type;\
4479 uint32_t w_size;\
4480 uint32_t w_length;\
4481 uint8_t *w_data;\
4482 int i;\
4483 torture_assert(tctx,\
4484 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4485 &w_type, &w_size, &w_length, &w_data),\
4486 "failed to query winreg");\
4487 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4488 blob = data_blob(w_data, w_size);\
4489 torture_assert(tctx, \
4490 pull_reg_multi_sz(tctx, &blob, &array),\
4491 "failed to pull multi sz");\
4492 for (i=0; array[i] != NULL; i++) {\
4493 torture_assert_str_equal(tctx, array[i], iname[i],\
4494 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4496 } while(0);
4498 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4499 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4500 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4502 torture_warning(tctx, "failed to check for winreg symlink");
4505 for (i=0; i < ARRAY_SIZE(keys); i++) {
4507 const char *printer_key;
4508 struct policy_handle key_handle;
4510 printer_key = talloc_asprintf(tctx, "%s\\%s",
4511 keys[i], printer_name);
4513 torture_assert(tctx,
4514 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4516 test_sz("Name", printername);
4517 test_sz("Share Name", sharename);
4518 test_sz("Port", info.info2.portname);
4519 test_sz("Printer Driver", info.info2.drivername);
4520 test_sz("Description", info.info2.comment);
4521 test_sz("Location", info.info2.location);
4522 test_sz("Separator File", info.info2.sepfile);
4523 test_sz("Print Processor", info.info2.printprocessor);
4524 test_sz("Datatype", info.info2.datatype);
4525 test_sz("Parameters", info.info2.parameters);
4526 /* winreg: 0, spoolss not */
4527 /* test_dword("Attributes", info.info2.attributes); */
4528 test_dword("Priority", info.info2.priority);
4529 test_dword("Default Priority", info.info2.defaultpriority);
4530 /* winreg: 60, spoolss: 0 */
4531 /* test_dword("StartTime", info.info2.starttime); */
4532 /* test_dword("UntilTime", info.info2.untiltime); */
4533 /* winreg != spoolss */
4534 /* test_dword("Status", info.info2.status); */
4535 test_dm("Default DevMode", info.info2.devmode);
4536 test_sd("Security", info.info2.secdesc);
4538 torture_assert(tctx,
4539 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4542 #undef test_dm
4543 #undef test_sd
4545 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4547 return true;
4550 static bool test_PrintProcessors(struct torture_context *tctx,
4551 struct dcerpc_binding_handle *b,
4552 const char *environment,
4553 struct dcerpc_binding_handle *winreg_handle,
4554 struct policy_handle *hive_handle)
4556 union spoolss_PrintProcessorInfo *info;
4557 uint32_t count;
4558 int i;
4560 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4562 torture_assert(tctx,
4563 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4564 "failed to enum print processors level 1");
4566 for (i=0; i < count; i++) {
4568 const char *processor_key;
4569 struct policy_handle key_handle;
4571 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4572 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4573 environment,
4574 info[i].info1.print_processor_name);
4576 torture_assert(tctx,
4577 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4579 /* nothing to check in there so far */
4581 torture_assert(tctx,
4582 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4585 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4587 return true;
4590 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4591 struct dcerpc_binding_handle *b,
4592 struct policy_handle *handle,
4593 const char *driver_name,
4594 const char *architecture,
4595 uint32_t level,
4596 uint32_t client_major_version,
4597 uint32_t client_minor_version,
4598 union spoolss_DriverInfo *info_p,
4599 WERROR *result);
4601 static const char *strip_path(const char *path)
4603 char *p;
4605 if (path == NULL) {
4606 return NULL;
4609 p = strrchr(path, '\\');
4610 if (p) {
4611 return p+1;
4614 return path;
4617 static const char **strip_paths(const char **path_array)
4619 int i;
4621 if (path_array == NULL) {
4622 return NULL;
4625 for (i=0; path_array[i] != NULL; i++) {
4626 path_array[i] = strip_path(path_array[i]);
4629 return path_array;
4632 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4634 time_t t;
4635 struct tm *tm;
4637 if (nt == 0) {
4638 return talloc_strdup(mem_ctx, "01/01/1601");
4641 t = nt_time_to_unix(nt);
4642 tm = localtime(&t);
4644 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4645 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4648 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4650 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4651 (unsigned)((v >> 48) & 0xFFFF),
4652 (unsigned)((v >> 32) & 0xFFFF),
4653 (unsigned)((v >> 16) & 0xFFFF),
4654 (unsigned)(v & 0xFFFF));
4657 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4658 struct dcerpc_binding_handle *b,
4659 struct policy_handle *handle,
4660 const char *printer_name,
4661 const char *driver_name,
4662 const char *environment,
4663 enum spoolss_DriverOSVersion version,
4664 struct dcerpc_binding_handle *winreg_handle,
4665 struct policy_handle *hive_handle,
4666 const char *server_name_slash)
4668 WERROR result;
4669 union spoolss_DriverInfo info;
4670 const char *driver_key;
4671 struct policy_handle key_handle;
4673 const char *driver_path;
4674 const char *data_file;
4675 const char *config_file;
4676 const char *help_file;
4677 const char **dependent_files;
4679 const char *driver_date;
4680 const char *inbox_driver_date;
4682 const char *driver_version;
4683 const char *inbox_driver_version;
4685 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4687 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4688 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4689 environment,
4690 version,
4691 driver_name);
4693 torture_assert(tctx,
4694 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4695 "failed to open driver key");
4697 if (torture_setting_bool(tctx, "samba3", false) ||
4698 torture_setting_bool(tctx, "w2k3", false)) {
4699 goto try_level6;
4702 if (handle) {
4703 torture_assert(tctx,
4704 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4705 "failed to get driver info level 8");
4706 } else {
4707 torture_assert(tctx,
4708 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4709 "failed to get driver info level 8");
4712 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4713 goto try_level6;
4716 driver_path = strip_path(info.info8.driver_path);
4717 data_file = strip_path(info.info8.data_file);
4718 config_file = strip_path(info.info8.config_file);
4719 help_file = strip_path(info.info8.help_file);
4720 dependent_files = strip_paths(info.info8.dependent_files);
4722 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4723 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4725 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4726 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4728 test_sz("Configuration File", config_file);
4729 test_sz("Data File", data_file);
4730 test_sz("Datatype", info.info8.default_datatype);
4731 test_sz("Driver", driver_path);
4732 test_sz("DriverDate", driver_date);
4733 test_sz("DriverVersion", driver_version);
4734 test_sz("HardwareID", info.info8.hardware_id);
4735 test_sz("Help File", help_file);
4736 test_sz("InfPath", info.info8.inf_path);
4737 test_sz("Manufacturer", info.info8.manufacturer_name);
4738 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4739 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4740 test_sz("Monitor", info.info8.monitor_name);
4741 test_sz("OEM URL", info.info8.manufacturer_url);
4742 test_sz("Print Processor", info.info8.print_processor);
4743 test_sz("Provider", info.info8.provider);
4744 test_sz("VendorSetup", info.info8.vendor_setup);
4745 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4746 test_multi_sz("Dependent Files", dependent_files);
4747 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4748 test_multi_sz("Previous Names", info.info8.previous_names);
4749 /* test_dword("Attributes", ?); */
4750 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4751 test_dword("Version", info.info8.version);
4752 /* test_dword("TempDir", ?); */
4754 try_level6:
4756 if (handle) {
4757 torture_assert(tctx,
4758 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4759 "failed to get driver info level 6");
4760 } else {
4761 torture_assert(tctx,
4762 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4763 "failed to get driver info level 6");
4766 driver_path = strip_path(info.info6.driver_path);
4767 data_file = strip_path(info.info6.data_file);
4768 config_file = strip_path(info.info6.config_file);
4769 help_file = strip_path(info.info6.help_file);
4770 dependent_files = strip_paths(info.info6.dependent_files);
4772 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4774 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4776 test_sz("Configuration File", config_file);
4777 test_sz("Data File", data_file);
4778 test_sz("Datatype", info.info6.default_datatype);
4779 test_sz("Driver", driver_path);
4780 if (torture_setting_bool(tctx, "w2k3", false)) {
4781 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4782 push_nttime(blob.data, 0, info.info6.driver_date);
4783 test_binary("DriverDate", blob);
4784 SBVAL(blob.data, 0, info.info6.driver_version);
4785 test_binary("DriverVersion", blob);
4786 } else {
4787 test_sz("DriverDate", driver_date);
4788 test_sz("DriverVersion", driver_version);
4790 test_sz("HardwareID", info.info6.hardware_id);
4791 test_sz("Help File", help_file);
4792 test_sz("Manufacturer", info.info6.manufacturer_name);
4793 test_sz("Monitor", info.info6.monitor_name);
4794 test_sz("OEM URL", info.info6.manufacturer_url);
4795 test_sz("Provider", info.info6.provider);
4796 test_multi_sz("Dependent Files", dependent_files);
4797 test_multi_sz("Previous Names", info.info6.previous_names);
4798 /* test_dword("Attributes", ?); */
4799 test_dword("Version", info.info6.version);
4800 /* test_dword("TempDir", ?); */
4802 if (handle) {
4803 torture_assert(tctx,
4804 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4805 "failed to get driver info level 3");
4806 } else {
4807 torture_assert(tctx,
4808 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4809 "failed to get driver info level 3");
4812 driver_path = strip_path(info.info3.driver_path);
4813 data_file = strip_path(info.info3.data_file);
4814 config_file = strip_path(info.info3.config_file);
4815 help_file = strip_path(info.info3.help_file);
4816 dependent_files = strip_paths(info.info3.dependent_files);
4818 test_sz("Configuration File", config_file);
4819 test_sz("Data File", data_file);
4820 test_sz("Datatype", info.info3.default_datatype);
4821 test_sz("Driver", driver_path);
4822 test_sz("Help File", help_file);
4823 test_sz("Monitor", info.info3.monitor_name);
4824 test_multi_sz("Dependent Files", dependent_files);
4825 /* test_dword("Attributes", ?); */
4826 test_dword("Version", info.info3.version);
4827 /* test_dword("TempDir", ?); */
4830 torture_assert(tctx,
4831 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4833 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4835 return true;
4838 #undef test_sz
4839 #undef test_dword
4841 static bool test_SetPrinterData(struct torture_context *tctx,
4842 struct dcerpc_binding_handle *b,
4843 struct policy_handle *handle,
4844 const char *value_name,
4845 enum winreg_Type type,
4846 uint8_t *data,
4847 uint32_t offered)
4849 struct spoolss_SetPrinterData r;
4851 r.in.handle = handle;
4852 r.in.value_name = value_name;
4853 r.in.type = type;
4854 r.in.data = data;
4855 r.in.offered = offered;
4857 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4858 r.in.value_name);
4860 torture_assert_ntstatus_ok(tctx,
4861 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4862 "SetPrinterData failed");
4863 torture_assert_werr_ok(tctx, r.out.result,
4864 "SetPrinterData failed");
4866 return true;
4869 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4870 struct dcerpc_binding_handle *b,
4871 struct policy_handle *handle,
4872 const char *printer_name,
4873 struct dcerpc_binding_handle *winreg_handle,
4874 struct policy_handle *hive_handle)
4876 const char *values[] = {
4877 "spootyfoot",
4878 "spooty\\foot",
4879 #if 0
4880 /* FIXME: not working with s3 atm. */
4881 "spooty,foot",
4882 "spooty,fo,ot",
4883 #endif
4884 "spooty foot",
4885 #if 0
4886 /* FIXME: not working with s3 atm. */
4887 "spooty\\fo,ot",
4888 "spooty,fo\\ot"
4889 #endif
4891 int i;
4893 for (i=0; i < ARRAY_SIZE(values); i++) {
4895 enum winreg_Type type, expected_type = REG_SZ;
4896 DATA_BLOB blob;
4897 uint8_t *data;
4898 uint32_t needed;
4900 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4901 type = REG_SZ;
4903 torture_assert(tctx,
4904 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4905 "SetPrinterData failed");
4907 torture_assert(tctx,
4908 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4909 "GetPrinterData failed");
4911 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4912 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4913 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4915 if (winreg_handle && hive_handle) {
4917 enum winreg_Type w_type;
4918 uint32_t w_size;
4919 uint32_t w_length;
4920 uint8_t *w_data;
4922 torture_assert(tctx,
4923 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4924 printer_name, "PrinterDriverData", values[i],
4925 &w_type, &w_size, &w_length, &w_data), "");
4927 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4928 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4929 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4930 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4933 torture_assert(tctx,
4934 test_DeletePrinterData(tctx, b, handle, values[i]),
4935 "DeletePrinterData failed");
4938 return true;
4942 static bool test_EnumPrinterKey(struct torture_context *tctx,
4943 struct dcerpc_binding_handle *b,
4944 struct policy_handle *handle,
4945 const char *key_name,
4946 const char ***array);
4948 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4949 struct dcerpc_binding_handle *b,
4950 struct policy_handle *handle,
4951 const char *key_name,
4952 const char *value_name,
4953 enum winreg_Type type,
4954 uint8_t *data,
4955 uint32_t offered)
4957 NTSTATUS status;
4958 struct spoolss_SetPrinterDataEx r;
4960 r.in.handle = handle;
4961 r.in.key_name = key_name;
4962 r.in.value_name = value_name;
4963 r.in.type = type;
4964 r.in.data = data;
4965 r.in.offered = offered;
4967 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4968 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4970 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4972 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4973 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4975 return true;
4978 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4979 struct dcerpc_pipe *p,
4980 struct policy_handle *handle)
4982 struct dcerpc_binding_handle *b = p->binding_handle;
4983 const char *value_name = "dog";
4984 const char *keys[] = {
4985 "torturedataex",
4986 "torture data ex",
4987 "torturedataex_with_subkey\\subkey",
4988 "torturedataex_with_subkey\\subkey:0",
4989 "torturedataex_with_subkey\\subkey:1",
4990 "torturedataex_with_subkey\\subkey\\subsubkey",
4991 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4992 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4993 "torture,data",
4994 "torture,data,ex",
4995 "torture,data\\ex",
4996 "torture\\data,ex",
4997 "torture/data",
4998 "torture/data ex",
4999 "torture/data ex/sub",
5000 "torture//data",
5001 "torture//data ex",
5002 "torture//data ex/sub",
5003 "torture//data ex//sub",
5005 int i;
5007 for (i=0; i < ARRAY_SIZE(keys); i++) {
5009 char *c;
5010 const char *key;
5011 enum winreg_Type type;
5012 DATA_BLOB blob_in, blob_out;
5013 const char **subkeys;
5014 uint32_t ecount;
5015 struct spoolss_PrinterEnumValues *einfo;
5016 uint32_t needed;
5018 blob_in = data_blob_talloc(tctx, NULL, 42);
5020 generate_random_buffer(blob_in.data, blob_in.length);
5022 torture_assert(tctx,
5023 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5024 "failed to call SetPrinterDataEx");
5026 torture_assert(tctx,
5027 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5028 "failed to call GetPrinterDataEx");
5030 blob_out.length = needed;
5031 torture_assert(tctx,
5032 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5033 "failed to call EnumPrinterDataEx");
5035 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5036 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5037 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5039 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5040 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5041 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5042 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5043 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5044 if (einfo[0].data_length > 0) {
5045 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5048 key = talloc_strdup(tctx, keys[i]);
5050 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5051 return false;
5054 c = strchr(key, '\\');
5055 if (c) {
5056 int k;
5058 /* we have subkeys */
5060 *c = 0;
5062 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5063 return false;
5066 for (k=0; subkeys && subkeys[k]; k++) {
5068 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5070 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5071 return false;
5075 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5076 return false;
5079 } else {
5080 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5081 return false;
5086 return true;
5089 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5090 struct dcerpc_pipe *p,
5091 struct policy_handle *handle)
5093 struct dcerpc_binding_handle *b = p->binding_handle;
5094 const char *key = "torturedataex";
5095 const char *values[] = {
5096 "torture_value",
5097 "torture value",
5098 "torture,value",
5099 "torture/value",
5100 "torture\\value",
5101 "torture\\\\value"
5103 int i;
5105 for (i=0; i < ARRAY_SIZE(values); i++) {
5107 enum winreg_Type type;
5108 DATA_BLOB blob_in, blob_out;
5109 uint32_t ecount;
5110 struct spoolss_PrinterEnumValues *einfo;
5111 uint32_t needed;
5113 if (torture_setting_bool(tctx, "samba3", false)) {
5114 char *q;
5115 q = strrchr(values[i], ',');
5116 if (q) {
5117 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5118 values[i]);
5119 continue;
5123 blob_in = data_blob_talloc(tctx, NULL, 42);
5125 generate_random_buffer(blob_in.data, blob_in.length);
5127 torture_assert(tctx,
5128 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5129 "failed to call SetPrinterDataEx");
5131 torture_assert(tctx,
5132 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5133 "failed to call GetPrinterDataEx");
5135 blob_out.length = needed;
5136 torture_assert(tctx,
5137 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5138 "failed to call EnumPrinterDataEx");
5140 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5141 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5142 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5144 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5145 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5146 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5147 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5148 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5149 if (einfo[0].data_length > 0) {
5150 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5153 torture_assert(tctx,
5154 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5155 "failed to call DeletePrinterDataEx");
5158 return true;
5162 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5163 struct dcerpc_pipe *p,
5164 struct policy_handle *handle,
5165 const char *printername,
5166 struct dcerpc_binding_handle *winreg_handle,
5167 struct policy_handle *hive_handle)
5169 struct dcerpc_binding_handle *b = p->binding_handle;
5170 const char *value_name = "dog";
5171 const char *key_name = "torturedataex";
5172 enum winreg_Type types[] = {
5173 REG_SZ,
5174 REG_MULTI_SZ,
5175 REG_DWORD,
5176 REG_BINARY
5178 const char *str = "abcdefghi";
5179 int t, s;
5181 for (t=0; t < ARRAY_SIZE(types); t++) {
5182 for (s=0; s < strlen(str); s++) {
5184 enum winreg_Type type;
5185 const char *string = talloc_strndup(tctx, str, s);
5186 const char *array[2];
5187 DATA_BLOB blob = data_blob_string_const(string);
5188 DATA_BLOB data;
5189 uint8_t *data_out;
5190 uint32_t needed, offered = 0;
5191 uint32_t ecount;
5192 struct spoolss_PrinterEnumValues *einfo;
5194 array[0] = talloc_strdup(tctx, string);
5195 array[1] = NULL;
5197 if (types[t] == REG_DWORD) {
5198 s = 0xffff;
5201 switch (types[t]) {
5202 case REG_BINARY:
5203 data = blob;
5204 offered = blob.length;
5205 break;
5206 case REG_DWORD:
5207 data = data_blob_talloc(tctx, NULL, 4);
5208 SIVAL(data.data, 0, 0x12345678);
5209 offered = 4;
5210 break;
5211 case REG_SZ:
5212 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5213 type = REG_SZ;
5214 offered = data.length;
5215 /*strlen_m_term(data.string)*2;*/
5216 break;
5217 case REG_MULTI_SZ:
5218 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5219 type = REG_MULTI_SZ;
5220 offered = data.length;
5221 break;
5222 default:
5223 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5226 torture_assert(tctx,
5227 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5228 "failed to call SetPrinterDataEx");
5230 torture_assert(tctx,
5231 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5232 "failed to call GetPrinterDataEx");
5234 torture_assert(tctx,
5235 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5236 "failed to call EnumPrinterDataEx");
5238 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5239 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5240 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5242 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5243 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5244 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5245 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5246 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5247 if (einfo[0].data_length > 0) {
5248 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5251 if (winreg_handle && hive_handle) {
5252 enum winreg_Type w_type;
5253 uint32_t w_size;
5254 uint32_t w_length;
5255 uint8_t *w_data;
5257 torture_assert(tctx,
5258 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5259 printername, key_name, value_name,
5260 &w_type, &w_size, &w_length, &w_data), "");
5262 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5263 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5264 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5265 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5268 torture_assert(tctx,
5269 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5270 "failed to call DeletePrinterDataEx");
5274 return true;
5277 static bool test_PrinterData_winreg(struct torture_context *tctx,
5278 struct dcerpc_pipe *p,
5279 struct policy_handle *handle,
5280 const char *printer_name)
5282 struct dcerpc_binding_handle *b = p->binding_handle;
5283 struct dcerpc_pipe *p2;
5284 bool ret = true;
5285 struct policy_handle hive_handle;
5286 struct dcerpc_binding_handle *b2;
5288 torture_assert_ntstatus_ok(tctx,
5289 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5290 "could not open winreg pipe");
5291 b2 = p2->binding_handle;
5293 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5295 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5296 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5298 test_winreg_CloseKey(tctx, b2, &hive_handle);
5300 talloc_free(p2);
5302 return ret;
5305 static bool test_Forms_winreg(struct torture_context *tctx,
5306 struct dcerpc_binding_handle *b,
5307 struct policy_handle *handle,
5308 bool print_server,
5309 const char *printer_name)
5311 struct dcerpc_pipe *p2;
5312 bool ret = true;
5313 struct policy_handle hive_handle;
5314 struct dcerpc_binding_handle *b2;
5316 torture_assert_ntstatus_ok(tctx,
5317 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5318 "could not open winreg pipe");
5319 b2 = p2->binding_handle;
5321 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5323 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5325 test_winreg_CloseKey(tctx, b2, &hive_handle);
5327 talloc_free(p2);
5329 return ret;
5332 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5333 struct dcerpc_pipe *p,
5334 struct policy_handle *handle,
5335 const char *printer_name)
5337 struct dcerpc_binding_handle *b = p->binding_handle;
5338 struct dcerpc_pipe *p2;
5339 bool ret = true;
5340 struct policy_handle hive_handle;
5341 struct dcerpc_binding_handle *b2;
5343 torture_assert_ntstatus_ok(tctx,
5344 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5345 "could not open winreg pipe");
5346 b2 = p2->binding_handle;
5348 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5350 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5352 test_winreg_CloseKey(tctx, b2, &hive_handle);
5354 talloc_free(p2);
5356 return ret;
5359 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5360 struct dcerpc_pipe *p,
5361 struct policy_handle *handle,
5362 const char *printer_name,
5363 const char *driver_name,
5364 const char *environment,
5365 enum spoolss_DriverOSVersion version)
5367 struct dcerpc_binding_handle *b = p->binding_handle;
5368 struct dcerpc_pipe *p2;
5369 bool ret = true;
5370 struct policy_handle hive_handle;
5371 struct dcerpc_binding_handle *b2;
5373 torture_assert_ntstatus_ok(tctx,
5374 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5375 "could not open winreg pipe");
5376 b2 = p2->binding_handle;
5378 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5380 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5382 test_winreg_CloseKey(tctx, b2, &hive_handle);
5384 talloc_free(p2);
5386 return ret;
5389 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5390 struct dcerpc_binding_handle *b,
5391 const char *environment)
5393 struct dcerpc_pipe *p2;
5394 bool ret = true;
5395 struct policy_handle hive_handle;
5396 struct dcerpc_binding_handle *b2;
5398 torture_assert_ntstatus_ok(tctx,
5399 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5400 "could not open winreg pipe");
5401 b2 = p2->binding_handle;
5403 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5405 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5407 test_winreg_CloseKey(tctx, b2, &hive_handle);
5409 talloc_free(p2);
5411 return ret;
5414 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5415 struct dcerpc_pipe *p,
5416 struct policy_handle *handle,
5417 const char *printer_name)
5419 struct spoolss_SetPrinterInfoCtr info_ctr;
5420 struct spoolss_DevmodeContainer devmode_ctr;
5421 struct sec_desc_buf secdesc_ctr;
5422 union spoolss_SetPrinterInfo sinfo;
5423 union spoolss_PrinterInfo info;
5424 struct dcerpc_binding_handle *b = p->binding_handle;
5425 const char *pname;
5427 ZERO_STRUCT(info_ctr);
5428 ZERO_STRUCT(devmode_ctr);
5429 ZERO_STRUCT(secdesc_ctr);
5431 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5433 torture_assert(tctx,
5434 test_GetPrinter_level(tctx, b, handle, 2, &info),
5435 "failed to query Printer level 2");
5437 torture_assert(tctx,
5438 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5439 "failed to convert");
5441 info_ctr.level = 2;
5442 info_ctr.info = sinfo;
5444 #define TEST_SZ(wname, iname) \
5445 do {\
5446 enum winreg_Type type;\
5447 uint8_t *data;\
5448 uint32_t needed;\
5449 DATA_BLOB blob;\
5450 const char *str;\
5451 torture_assert(tctx,\
5452 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5453 "failed to query");\
5454 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5455 blob = data_blob_const(data, needed);\
5456 torture_assert(tctx,\
5457 pull_reg_sz(tctx, &blob, &str),\
5458 "failed to pull REG_SZ");\
5459 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5460 } while(0);
5463 #define TEST_SET_SZ(wname, iname, val) \
5464 do {\
5465 enum winreg_Type type;\
5466 uint8_t *data;\
5467 uint32_t needed;\
5468 DATA_BLOB blob;\
5469 const char *str;\
5470 sinfo.info2->iname = val;\
5471 torture_assert(tctx,\
5472 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5473 "failed to call SetPrinter");\
5474 torture_assert(tctx,\
5475 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5476 "failed to query");\
5477 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5478 blob = data_blob_const(data, needed);\
5479 torture_assert(tctx,\
5480 pull_reg_sz(tctx, &blob, &str),\
5481 "failed to pull REG_SZ");\
5482 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5483 } while(0);
5485 #define TEST_SET_DWORD(wname, iname, val) \
5486 do {\
5487 enum winreg_Type type;\
5488 uint8_t *data;\
5489 uint32_t needed;\
5490 uint32_t value;\
5491 sinfo.info2->iname = val;\
5492 torture_assert(tctx,\
5493 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5494 "failed to call SetPrinter");\
5495 torture_assert(tctx,\
5496 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5497 "failed to query");\
5498 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5499 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5500 value = IVAL(data, 0); \
5501 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5502 } while(0);
5504 TEST_SET_SZ("description", comment, "newval");
5505 TEST_SET_SZ("location", location, "newval");
5506 TEST_SET_SZ("driverName", drivername, "newval");
5507 /* TEST_SET_DWORD("priority", priority, 25); */
5509 torture_assert(tctx,
5510 test_GetPrinter_level(tctx, b, handle, 2, &info),
5511 "failed to query Printer level 2");
5513 TEST_SZ("description", info.info2.comment);
5514 TEST_SZ("driverName", info.info2.drivername);
5515 TEST_SZ("location", info.info2.location);
5517 pname = strrchr(info.info2.printername, '\\');
5518 if (pname == NULL) {
5519 pname = info.info2.printername;
5520 } else {
5521 pname++;
5523 TEST_SZ("printerName", pname);
5524 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5525 /* TEST_SZ("printShareName", info.info2.sharename); */
5527 /* FIXME gd: complete the list */
5529 #undef TEST_SZ
5530 #undef TEST_SET_SZ
5531 #undef TEST_DWORD
5533 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5535 return true;
5538 static bool test_print_processors_winreg(struct torture_context *tctx,
5539 void *private_data)
5541 struct test_spoolss_context *ctx =
5542 talloc_get_type_abort(private_data, struct test_spoolss_context);
5543 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5544 struct dcerpc_binding_handle *b = p->binding_handle;
5546 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5549 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5550 struct dcerpc_binding_handle *b,
5551 struct policy_handle *handle,
5552 uint32_t *change_id)
5554 enum winreg_Type type;
5555 uint8_t *data;
5556 uint32_t needed;
5558 torture_assert(tctx,
5559 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5560 "failed to call GetPrinterData");
5562 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5563 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5565 *change_id = IVAL(data, 0);
5567 return true;
5570 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5571 struct dcerpc_pipe *p,
5572 struct policy_handle *handle,
5573 uint32_t *change_id)
5575 enum winreg_Type type;
5576 uint8_t *data;
5577 uint32_t needed;
5579 torture_assert(tctx,
5580 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5581 "failed to call GetPrinterData");
5583 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5584 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5586 *change_id = IVAL(data, 0);
5588 return true;
5591 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5592 struct dcerpc_binding_handle *b,
5593 struct policy_handle *handle,
5594 uint32_t *change_id)
5596 union spoolss_PrinterInfo info;
5598 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5599 "failed to query Printer level 0");
5601 *change_id = info.info0.change_id;
5603 return true;
5606 static bool test_ChangeID(struct torture_context *tctx,
5607 struct dcerpc_pipe *p,
5608 struct policy_handle *handle)
5610 uint32_t change_id, change_id_ex, change_id_info;
5611 uint32_t change_id2, change_id_ex2, change_id_info2;
5612 union spoolss_PrinterInfo info;
5613 const char *comment;
5614 struct dcerpc_binding_handle *b = p->binding_handle;
5616 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5618 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5619 "failed to query for ChangeID");
5620 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5621 "failed to query for ChangeID");
5622 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5623 "failed to query for ChangeID");
5625 torture_assert_int_equal(tctx, change_id, change_id_ex,
5626 "change_ids should all be equal");
5627 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5628 "change_ids should all be equal");
5631 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5633 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5634 "failed to query for ChangeID");
5635 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5636 "failed to query Printer level 2");
5637 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5638 "failed to query for ChangeID");
5639 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5640 "failed to query for ChangeID");
5641 torture_assert_int_equal(tctx, change_id, change_id_ex,
5642 "change_id should not have changed");
5643 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5644 "change_id should not have changed");
5647 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5649 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5650 "failed to query for ChangeID");
5651 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5652 "failed to query for ChangeID");
5653 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5654 "failed to query for ChangeID");
5655 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5656 "failed to query Printer level 2");
5657 comment = talloc_strdup(tctx, info.info2.comment);
5660 struct spoolss_SetPrinterInfoCtr info_ctr;
5661 struct spoolss_DevmodeContainer devmode_ctr;
5662 struct sec_desc_buf secdesc_ctr;
5663 union spoolss_SetPrinterInfo sinfo;
5665 ZERO_STRUCT(info_ctr);
5666 ZERO_STRUCT(devmode_ctr);
5667 ZERO_STRUCT(secdesc_ctr);
5670 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5671 sinfo.info2->comment = "torture_comment";
5673 info_ctr.level = 2;
5674 info_ctr.info = sinfo;
5676 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5677 "failed to call SetPrinter");
5679 sinfo.info2->comment = comment;
5681 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5682 "failed to call SetPrinter");
5686 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5687 "failed to query for ChangeID");
5688 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5689 "failed to query for ChangeID");
5690 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5691 "failed to query for ChangeID");
5693 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5694 "change_ids should all be equal");
5695 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5696 "change_ids should all be equal");
5698 torture_assert(tctx, (change_id < change_id2),
5699 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5700 change_id2, change_id));
5701 torture_assert(tctx, (change_id_ex < change_id_ex2),
5702 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5703 change_id_ex2, change_id_ex));
5704 torture_assert(tctx, (change_id_info < change_id_info2),
5705 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5706 change_id_info2, change_id_info));
5708 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5710 return true;
5713 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5714 struct dcerpc_pipe *p,
5715 struct policy_handle *handle)
5717 NTSTATUS status;
5718 struct dcerpc_binding *b;
5719 struct dcerpc_pipe *p2;
5720 struct spoolss_ClosePrinter cp;
5722 /* only makes sense on SMB */
5723 if (p->conn->transport.transport != NCACN_NP) {
5724 return true;
5727 torture_comment(tctx, "Testing close on secondary pipe\n");
5729 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5730 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5732 status = dcerpc_secondary_connection(p, &p2, b);
5733 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5735 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5736 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5738 cp.in.handle = handle;
5739 cp.out.handle = handle;
5741 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5742 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5743 "ERROR: Allowed close on secondary connection");
5745 talloc_free(p2);
5747 return true;
5750 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5751 struct dcerpc_binding_handle *b, const char *name)
5753 NTSTATUS status;
5754 struct spoolss_OpenPrinter op;
5755 struct spoolss_OpenPrinterEx opEx;
5756 struct policy_handle handle;
5757 bool ret = true;
5759 op.in.printername = name;
5760 op.in.datatype = NULL;
5761 op.in.devmode_ctr.devmode= NULL;
5762 op.in.access_mask = 0;
5763 op.out.handle = &handle;
5765 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5767 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5768 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5769 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5770 "unexpected result");
5772 if (W_ERROR_IS_OK(op.out.result)) {
5773 ret &=test_ClosePrinter(tctx, b, &handle);
5776 opEx.in.printername = name;
5777 opEx.in.datatype = NULL;
5778 opEx.in.devmode_ctr.devmode = NULL;
5779 opEx.in.access_mask = 0;
5780 opEx.in.level = 1;
5781 opEx.in.userlevel.level1 = NULL;
5782 opEx.out.handle = &handle;
5784 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5786 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5787 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5788 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5789 "unexpected result");
5791 if (W_ERROR_IS_OK(opEx.out.result)) {
5792 ret &=test_ClosePrinter(tctx, b, &handle);
5795 return ret;
5798 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5799 void *private_data)
5801 struct test_spoolss_context *ctx =
5802 talloc_get_type_abort(private_data, struct test_spoolss_context);
5804 const char *badnames[] = {
5805 "__INVALID_PRINTER__",
5806 "\\\\__INVALID_HOST__",
5808 "\\\\\\",
5809 "\\\\\\__INVALID_PRINTER__"
5811 const char *badname;
5812 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5813 const char *server_name = dcerpc_server_name(p);
5814 struct dcerpc_binding_handle *b = p->binding_handle;
5815 int i;
5817 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5818 torture_assert(tctx,
5819 test_OpenPrinter_badname(tctx, b, badnames[i]),
5820 "");
5823 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5824 torture_assert(tctx,
5825 test_OpenPrinter_badname(tctx, b, badname),
5826 "");
5828 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5829 torture_assert(tctx,
5830 test_OpenPrinter_badname(tctx, b, badname),
5831 "");
5833 return true;
5836 static bool test_OpenPrinter(struct torture_context *tctx,
5837 struct dcerpc_pipe *p,
5838 const char *name,
5839 const char *environment,
5840 bool open_only)
5842 NTSTATUS status;
5843 struct spoolss_OpenPrinter r;
5844 struct policy_handle handle;
5845 bool ret = true;
5846 struct dcerpc_binding_handle *b = p->binding_handle;
5848 r.in.printername = name;
5849 r.in.datatype = NULL;
5850 r.in.devmode_ctr.devmode= NULL;
5851 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5852 r.out.handle = &handle;
5854 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5856 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5858 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5860 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5862 if (open_only) {
5863 goto close_printer;
5866 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5867 ret = false;
5870 if (!torture_setting_bool(tctx, "samba3", false)) {
5871 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5872 ret = false;
5876 close_printer:
5877 if (!test_ClosePrinter(tctx, b, &handle)) {
5878 ret = false;
5881 return ret;
5884 static bool test_OpenPrinterEx(struct torture_context *tctx,
5885 struct dcerpc_binding_handle *b,
5886 const char *printername,
5887 const char *datatype,
5888 struct spoolss_DeviceMode *devmode,
5889 uint32_t access_mask,
5890 uint32_t level,
5891 union spoolss_UserLevel *userlevel,
5892 struct policy_handle *handle,
5893 WERROR expected_result)
5895 struct spoolss_OpenPrinterEx r;
5897 r.in.printername = printername;
5898 r.in.datatype = datatype;
5899 r.in.devmode_ctr.devmode= devmode;
5900 r.in.access_mask = access_mask;
5901 r.in.level = level;
5902 r.in.userlevel = *userlevel;
5903 r.out.handle = handle;
5905 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5907 torture_assert_ntstatus_ok(tctx,
5908 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5909 "OpenPrinterEx failed");
5911 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5912 "OpenPrinterEx failed");
5914 return true;
5917 static bool call_OpenPrinterEx(struct torture_context *tctx,
5918 struct dcerpc_pipe *p,
5919 const char *name,
5920 struct spoolss_DeviceMode *devmode,
5921 struct policy_handle *handle)
5923 union spoolss_UserLevel userlevel;
5924 struct spoolss_UserLevel1 userlevel1;
5925 struct dcerpc_binding_handle *b = p->binding_handle;
5927 userlevel1.size = 1234;
5928 userlevel1.client = "hello";
5929 userlevel1.user = "spottyfoot!";
5930 userlevel1.build = 1;
5931 userlevel1.major = 2;
5932 userlevel1.minor = 3;
5933 userlevel1.processor = 4;
5935 userlevel.level1 = &userlevel1;
5937 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5938 SEC_FLAG_MAXIMUM_ALLOWED,
5940 &userlevel,
5941 handle,
5942 WERR_OK);
5945 static bool test_printer_rename(struct torture_context *tctx,
5946 void *private_data)
5948 struct torture_printer_context *t =
5949 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5950 struct dcerpc_pipe *p = t->spoolss_pipe;
5952 bool ret = true;
5953 union spoolss_PrinterInfo info;
5954 union spoolss_SetPrinterInfo sinfo;
5955 struct spoolss_SetPrinterInfoCtr info_ctr;
5956 struct spoolss_DevmodeContainer devmode_ctr;
5957 struct sec_desc_buf secdesc_ctr;
5958 const char *printer_name;
5959 const char *printer_name_orig;
5960 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5961 struct policy_handle new_handle;
5962 const char *q;
5963 struct dcerpc_binding_handle *b = p->binding_handle;
5965 ZERO_STRUCT(devmode_ctr);
5966 ZERO_STRUCT(secdesc_ctr);
5968 torture_comment(tctx, "Testing Printer rename operations\n");
5970 torture_assert(tctx,
5971 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5972 "failed to call GetPrinter level 2");
5974 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5976 q = strrchr(info.info2.printername, '\\');
5977 if (q) {
5978 torture_warning(tctx,
5979 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5982 torture_assert(tctx,
5983 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5985 sinfo.info2->printername = printer_name_new;
5987 info_ctr.level = 2;
5988 info_ctr.info = sinfo;
5990 torture_assert(tctx,
5991 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5992 "failed to call SetPrinter level 2");
5994 torture_assert(tctx,
5995 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5996 "failed to call GetPrinter level 2");
5998 printer_name = talloc_strdup(tctx, info.info2.printername);
6000 q = strrchr(info.info2.printername, '\\');
6001 if (q) {
6002 torture_warning(tctx,
6003 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6004 q++;
6005 printer_name = q;
6008 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6009 "new printer name was not set");
6011 /* samba currently cannot fully rename printers */
6012 if (!torture_setting_bool(tctx, "samba3", false)) {
6013 torture_assert(tctx,
6014 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6015 "still can open printer with oldname after rename");
6016 } else {
6017 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6020 torture_assert(tctx,
6021 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6022 "failed to open printer with new name");
6024 torture_assert(tctx,
6025 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6026 "failed to call GetPrinter level 2");
6028 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6029 "new printer name was not set");
6031 torture_assert(tctx,
6032 test_ClosePrinter(tctx, b, &new_handle),
6033 "failed to close printer");
6035 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6037 return ret;
6040 static bool test_openprinter(struct torture_context *tctx,
6041 struct dcerpc_binding_handle *b,
6042 const char *real_printername)
6044 union spoolss_UserLevel userlevel;
6045 struct policy_handle handle;
6046 struct spoolss_UserLevel1 userlevel1;
6047 const char *printername = NULL;
6048 int i;
6050 struct {
6051 const char *suffix;
6052 WERROR expected_result;
6053 } tests[] = {
6055 .suffix = "rubbish",
6056 .expected_result = WERR_INVALID_PRINTER_NAME
6058 .suffix = ", LocalOnl",
6059 .expected_result = WERR_INVALID_PRINTER_NAME
6061 .suffix = ", localOnly",
6062 .expected_result = WERR_INVALID_PRINTER_NAME
6064 .suffix = ", localonl",
6065 .expected_result = WERR_INVALID_PRINTER_NAME
6067 .suffix = ",LocalOnl",
6068 .expected_result = WERR_INVALID_PRINTER_NAME
6070 .suffix = ",localOnl2",
6071 .expected_result = WERR_INVALID_PRINTER_NAME
6073 .suffix = ", DrvConver2t",
6074 .expected_result = WERR_INVALID_PRINTER_NAME
6076 .suffix = ", drvconvert",
6077 .expected_result = WERR_INVALID_PRINTER_NAME
6079 .suffix = ",drvconvert",
6080 .expected_result = WERR_INVALID_PRINTER_NAME
6082 .suffix = ", DrvConvert",
6083 .expected_result = WERR_OK
6085 .suffix = " , DrvConvert",
6086 .expected_result = WERR_INVALID_PRINTER_NAME
6088 .suffix = ",DrvConvert",
6089 .expected_result = WERR_OK
6091 .suffix = ", DrvConvertsadfasdf",
6092 .expected_result = WERR_OK
6094 .suffix = ",DrvConvertasdfasd",
6095 .expected_result = WERR_OK
6097 .suffix = ", LocalOnly",
6098 .expected_result = WERR_OK
6100 .suffix = " , LocalOnly",
6101 .expected_result = WERR_INVALID_PRINTER_NAME
6103 .suffix = ",LocalOnly",
6104 .expected_result = WERR_OK
6106 .suffix = ", LocalOnlysagi4gjfkd",
6107 .expected_result = WERR_OK
6109 .suffix = ",LocalOnlysagi4gjfkd",
6110 .expected_result = WERR_OK
6114 userlevel1.size = 1234;
6115 userlevel1.client = "hello";
6116 userlevel1.user = "spottyfoot!";
6117 userlevel1.build = 1;
6118 userlevel1.major = 2;
6119 userlevel1.minor = 3;
6120 userlevel1.processor = 4;
6122 userlevel.level1 = &userlevel1;
6124 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6126 torture_assert(tctx,
6127 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6128 &userlevel, &handle,
6129 WERR_OK),
6130 "OpenPrinterEx failed");
6131 test_ClosePrinter(tctx, b, &handle);
6133 for (i=0; i < ARRAY_SIZE(tests); i++) {
6135 printername = talloc_asprintf(tctx, "%s%s",
6136 real_printername,
6137 tests[i].suffix);
6139 torture_assert(tctx,
6140 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6141 &userlevel, &handle,
6142 tests[i].expected_result),
6143 "OpenPrinterEx failed");
6144 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6145 test_ClosePrinter(tctx, b, &handle);
6149 return true;
6153 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6154 struct dcerpc_pipe *p,
6155 const char *name,
6156 const char *environment)
6158 struct policy_handle handle;
6159 bool ret = true;
6160 struct dcerpc_binding_handle *b = p->binding_handle;
6162 if (!test_openprinter(tctx, b, name)) {
6163 return false;
6166 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6167 return false;
6170 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6171 ret = false;
6174 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6175 ret = false;
6178 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6179 ret = false;
6182 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6183 ret = false;
6186 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6187 ret = false;
6190 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6191 ret = false;
6194 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6195 ret = false;
6198 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6199 ret = false;
6202 if (!test_printer_all_keys(tctx, b, &handle)) {
6203 ret = false;
6206 if (!test_PausePrinter(tctx, b, &handle)) {
6207 ret = false;
6210 if (!test_DoPrintTest(tctx, b, &handle)) {
6211 ret = false;
6214 if (!test_ResumePrinter(tctx, b, &handle)) {
6215 ret = false;
6218 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6219 ret = false;
6222 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6223 ret = false;
6226 if (!torture_setting_bool(tctx, "samba3", false)) {
6227 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6228 ret = false;
6232 if (!test_ClosePrinter(tctx, b, &handle)) {
6233 ret = false;
6236 return ret;
6239 static bool test_EnumPrinters_old(struct torture_context *tctx,
6240 void *private_data)
6242 struct test_spoolss_context *ctx =
6243 talloc_get_type_abort(private_data, struct test_spoolss_context);
6244 struct spoolss_EnumPrinters r;
6245 NTSTATUS status;
6246 uint16_t levels[] = {1, 2, 4, 5};
6247 int i;
6248 bool ret = true;
6249 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6250 struct dcerpc_binding_handle *b = p->binding_handle;
6252 for (i=0;i<ARRAY_SIZE(levels);i++) {
6253 union spoolss_PrinterInfo *info;
6254 int j;
6255 uint32_t needed;
6256 uint32_t count;
6258 r.in.flags = PRINTER_ENUM_LOCAL;
6259 r.in.server = "";
6260 r.in.level = levels[i];
6261 r.in.buffer = NULL;
6262 r.in.offered = 0;
6263 r.out.needed = &needed;
6264 r.out.count = &count;
6265 r.out.info = &info;
6267 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6269 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6270 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6272 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6273 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6274 r.in.buffer = &blob;
6275 r.in.offered = needed;
6276 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6279 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6281 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6283 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6285 if (!info) {
6286 torture_comment(tctx, "No printers returned\n");
6287 return true;
6290 for (j=0;j<count;j++) {
6291 if (r.in.level == 1) {
6292 char *unc = talloc_strdup(tctx, info[j].info1.name);
6293 char *slash, *name, *full_name;
6294 name = unc;
6295 if (unc[0] == '\\' && unc[1] == '\\') {
6296 unc +=2;
6298 slash = strchr(unc, '\\');
6299 if (slash) {
6300 slash++;
6301 name = slash;
6303 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6304 dcerpc_server_name(p), name);
6305 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6306 ret = false;
6308 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6309 ret = false;
6311 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6312 ret = false;
6314 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6315 ret = false;
6321 return ret;
6324 static bool test_EnumPrinters_level(struct torture_context *tctx,
6325 struct dcerpc_binding_handle *b,
6326 uint32_t flags,
6327 const char *servername,
6328 uint32_t level,
6329 uint32_t *count_p,
6330 union spoolss_PrinterInfo **info_p)
6332 struct spoolss_EnumPrinters r;
6333 union spoolss_PrinterInfo *info;
6334 uint32_t needed;
6335 uint32_t count;
6337 r.in.flags = flags;
6338 r.in.server = servername;
6339 r.in.level = level;
6340 r.in.buffer = NULL;
6341 r.in.offered = 0;
6342 r.out.needed = &needed;
6343 r.out.count = &count;
6344 r.out.info = &info;
6346 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6347 r.in.server, r.in.level);
6349 torture_assert_ntstatus_ok(tctx,
6350 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6351 "EnumPrinters failed");
6352 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6353 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6354 r.in.buffer = &blob;
6355 r.in.offered = needed;
6356 torture_assert_ntstatus_ok(tctx,
6357 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6358 "EnumPrinters failed");
6361 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6363 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6365 if (count_p) {
6366 *count_p = count;
6368 if (info_p) {
6369 *info_p = info;
6372 return true;
6375 static const char *get_short_printername(struct torture_context *tctx,
6376 const char *name)
6378 const char *short_name;
6380 if (name[0] == '\\' && name[1] == '\\') {
6381 name += 2;
6382 short_name = strchr(name, '\\');
6383 if (short_name) {
6384 return talloc_strdup(tctx, short_name+1);
6388 return name;
6391 static const char *get_full_printername(struct torture_context *tctx,
6392 const char *name)
6394 const char *full_name = talloc_strdup(tctx, name);
6395 char *p;
6397 if (name && name[0] == '\\' && name[1] == '\\') {
6398 name += 2;
6399 p = strchr(name, '\\');
6400 if (p) {
6401 return full_name;
6405 return NULL;
6408 static bool test_OnePrinter_servername(struct torture_context *tctx,
6409 struct dcerpc_pipe *p,
6410 struct dcerpc_binding_handle *b,
6411 const char *servername,
6412 const char *printername)
6414 union spoolss_PrinterInfo info;
6415 const char *short_name = get_short_printername(tctx, printername);
6416 const char *full_name = get_full_printername(tctx, printername);
6418 if (short_name) {
6419 struct policy_handle handle;
6420 torture_assert(tctx,
6421 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6422 "failed to open printer");
6424 torture_assert(tctx,
6425 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6426 "failed to get printer info");
6428 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6429 "unexpected servername");
6430 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6431 "unexpected printername");
6433 if (info.info2.devmode) {
6434 const char *expected_devicename;
6435 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6436 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6437 "unexpected devicemode devicename");
6440 torture_assert(tctx,
6441 test_ClosePrinter(tctx, b, &handle),
6442 "failed to close printer");
6445 if (full_name) {
6446 struct policy_handle handle;
6448 torture_assert(tctx,
6449 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6450 "failed to open printer");
6452 torture_assert(tctx,
6453 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6454 "failed to get printer info");
6456 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6457 "unexpected servername");
6458 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6459 "unexpected printername");
6461 if (info.info2.devmode) {
6462 const char *expected_devicename;
6463 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6464 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6465 "unexpected devicemode devicename");
6468 torture_assert(tctx,
6469 test_ClosePrinter(tctx, b, &handle),
6470 "failed to close printer");
6473 return true;
6476 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6477 void *private_data)
6479 struct test_spoolss_context *ctx =
6480 talloc_get_type_abort(private_data, struct test_spoolss_context);
6481 int i;
6482 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6483 struct dcerpc_binding_handle *b = p->binding_handle;
6484 uint32_t count;
6485 union spoolss_PrinterInfo *info;
6486 const char *servername;
6487 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6489 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6491 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6493 torture_assert(tctx,
6494 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6495 "failed to enumerate printers");
6497 for (i=0; i < count; i++) {
6499 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6500 "unexpected servername");
6502 torture_assert(tctx,
6503 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6504 "failed to check printer");
6507 servername = "";
6509 torture_assert(tctx,
6510 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6511 "failed to enumerate printers");
6513 for (i=0; i < count; i++) {
6515 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6516 "unexpected servername");
6518 torture_assert(tctx,
6519 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6520 "failed to check printer");
6524 return true;
6528 static bool test_GetPrinterDriver(struct torture_context *tctx,
6529 struct dcerpc_binding_handle *b,
6530 struct policy_handle *handle,
6531 const char *driver_name)
6533 struct spoolss_GetPrinterDriver r;
6534 uint32_t needed;
6536 r.in.handle = handle;
6537 r.in.architecture = "W32X86";
6538 r.in.level = 1;
6539 r.in.buffer = NULL;
6540 r.in.offered = 0;
6541 r.out.needed = &needed;
6543 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6545 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6546 "failed to call GetPrinterDriver");
6547 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6548 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6549 r.in.buffer = &blob;
6550 r.in.offered = needed;
6551 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6552 "failed to call GetPrinterDriver");
6555 torture_assert_werr_ok(tctx, r.out.result,
6556 "failed to call GetPrinterDriver");
6558 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6560 return true;
6563 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6564 struct dcerpc_binding_handle *b,
6565 struct policy_handle *handle,
6566 const char *driver_name,
6567 const char *architecture,
6568 uint32_t level,
6569 uint32_t client_major_version,
6570 uint32_t client_minor_version,
6571 union spoolss_DriverInfo *info_p,
6572 WERROR *result_p)
6575 struct spoolss_GetPrinterDriver2 r;
6576 uint32_t needed;
6577 uint32_t server_major_version;
6578 uint32_t server_minor_version;
6580 r.in.handle = handle;
6581 r.in.architecture = architecture;
6582 r.in.client_major_version = client_major_version;
6583 r.in.client_minor_version = client_minor_version;
6584 r.in.buffer = NULL;
6585 r.in.offered = 0;
6586 r.in.level = level;
6587 r.out.needed = &needed;
6588 r.out.server_major_version = &server_major_version;
6589 r.out.server_minor_version = &server_minor_version;
6591 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6592 driver_name, r.in.level);
6594 torture_assert_ntstatus_ok(tctx,
6595 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6596 "failed to call GetPrinterDriver2");
6597 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6598 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6599 r.in.buffer = &blob;
6600 r.in.offered = needed;
6601 torture_assert_ntstatus_ok(tctx,
6602 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6603 "failed to call GetPrinterDriver2");
6606 if (result_p) {
6607 *result_p = r.out.result;
6610 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6611 switch (r.in.level) {
6612 case 101:
6613 case 8:
6614 torture_comment(tctx,
6615 "level %d not implemented, not considering as an error\n",
6616 r.in.level);
6617 return true;
6618 default:
6619 break;
6623 torture_assert_werr_ok(tctx, r.out.result,
6624 "failed to call GetPrinterDriver2");
6626 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6628 if (info_p) {
6629 *info_p = *r.out.info;
6632 return true;
6635 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6636 struct dcerpc_binding_handle *b,
6637 struct policy_handle *handle,
6638 const char *driver_name,
6639 const char *architecture)
6641 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6642 int i;
6645 for (i=0;i<ARRAY_SIZE(levels);i++) {
6647 torture_assert(tctx,
6648 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6649 "");
6652 return true;
6655 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6656 void *private_data)
6658 struct test_spoolss_context *ctx =
6659 talloc_get_type_abort(private_data, struct test_spoolss_context);
6660 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6661 int i;
6662 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6663 struct dcerpc_binding_handle *b = p->binding_handle;
6664 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6666 for (i=0;i<ARRAY_SIZE(levels);i++) {
6668 uint32_t count;
6669 union spoolss_DriverInfo *info;
6671 torture_assert(tctx,
6672 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6673 "failed to enumerate drivers");
6675 if (!info) {
6676 torture_comment(tctx, "No printer drivers returned\n");
6677 break;
6681 return true;
6684 static bool test_DeletePrinter(struct torture_context *tctx,
6685 struct dcerpc_binding_handle *b,
6686 struct policy_handle *handle)
6688 struct spoolss_DeletePrinter r;
6690 torture_comment(tctx, "Testing DeletePrinter\n");
6692 r.in.handle = handle;
6694 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6695 "failed to delete printer");
6696 torture_assert_werr_ok(tctx, r.out.result,
6697 "failed to delete printer");
6699 return true;
6702 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6703 struct dcerpc_binding_handle *b,
6704 uint32_t flags,
6705 uint32_t level,
6706 const char *name,
6707 bool *found)
6709 struct spoolss_EnumPrinters e;
6710 uint32_t count;
6711 union spoolss_PrinterInfo *info;
6712 uint32_t needed;
6713 int i;
6715 *found = false;
6717 e.in.flags = flags;
6718 e.in.server = NULL;
6719 e.in.level = level;
6720 e.in.buffer = NULL;
6721 e.in.offered = 0;
6722 e.out.count = &count;
6723 e.out.info = &info;
6724 e.out.needed = &needed;
6726 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6727 "failed to enum printers");
6729 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6730 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6731 e.in.buffer = &blob;
6732 e.in.offered = needed;
6734 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6735 "failed to enum printers");
6738 torture_assert_werr_ok(tctx, e.out.result,
6739 "failed to enum printers");
6741 for (i=0; i < count; i++) {
6743 const char *current = NULL;
6744 const char *q;
6746 switch (level) {
6747 case 1:
6748 current = info[i].info1.name;
6749 break;
6752 if (strequal(current, name)) {
6753 *found = true;
6754 break;
6757 q = strrchr(current, '\\');
6758 if (q) {
6759 if (!e.in.server) {
6760 torture_warning(tctx,
6761 "server returns printername %s incl. servername although we did not set servername", current);
6763 q++;
6764 if (strequal(q, name)) {
6765 *found = true;
6766 break;
6771 return true;
6774 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6775 struct dcerpc_pipe *p,
6776 const char *printername,
6777 bool ex)
6779 WERROR result;
6780 struct spoolss_AddPrinter r;
6781 struct spoolss_AddPrinterEx rex;
6782 struct spoolss_SetPrinterInfoCtr info_ctr;
6783 struct spoolss_SetPrinterInfo1 info1;
6784 struct spoolss_DevmodeContainer devmode_ctr;
6785 struct sec_desc_buf secdesc_ctr;
6786 struct spoolss_UserLevelCtr userlevel_ctr;
6787 struct policy_handle handle;
6788 bool found = false;
6789 struct dcerpc_binding_handle *b = p->binding_handle;
6791 ZERO_STRUCT(devmode_ctr);
6792 ZERO_STRUCT(secdesc_ctr);
6793 ZERO_STRUCT(userlevel_ctr);
6794 ZERO_STRUCT(info1);
6796 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6797 ex ? "Ex":"", printername);
6799 /* try to add printer to wellknown printer list (level 1) */
6801 userlevel_ctr.level = 1;
6803 info_ctr.info.info1 = &info1;
6804 info_ctr.level = 1;
6806 rex.in.server = NULL;
6807 rex.in.info_ctr = &info_ctr;
6808 rex.in.devmode_ctr = &devmode_ctr;
6809 rex.in.secdesc_ctr = &secdesc_ctr;
6810 rex.in.userlevel_ctr = &userlevel_ctr;
6811 rex.out.handle = &handle;
6813 r.in.server = NULL;
6814 r.in.info_ctr = &info_ctr;
6815 r.in.devmode_ctr = &devmode_ctr;
6816 r.in.secdesc_ctr = &secdesc_ctr;
6817 r.out.handle = &handle;
6819 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6820 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6821 "failed to add printer");
6822 result = ex ? rex.out.result : r.out.result;
6823 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6824 "unexpected result code");
6826 info1.name = printername;
6827 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6829 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6830 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6831 "failed to add printer");
6832 result = ex ? rex.out.result : r.out.result;
6833 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6834 "unexpected result code");
6836 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6837 better do a real check to see the printer is really there */
6839 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6840 PRINTER_ENUM_NETWORK, 1,
6841 printername,
6842 &found),
6843 "failed to enum printers");
6845 torture_assert(tctx, found, "failed to find newly added printer");
6847 info1.flags = 0;
6849 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6850 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6851 "failed to add printer");
6852 result = ex ? rex.out.result : r.out.result;
6853 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6854 "unexpected result code");
6856 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6857 better do a real check to see the printer has really been removed
6858 from the well known printer list */
6860 found = false;
6862 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6863 PRINTER_ENUM_NETWORK, 1,
6864 printername,
6865 &found),
6866 "failed to enum printers");
6867 #if 0
6868 torture_assert(tctx, !found, "printer still in well known printer list");
6869 #endif
6870 return true;
6873 static bool test_AddPrinter_normal(struct torture_context *tctx,
6874 struct dcerpc_pipe *p,
6875 struct policy_handle *handle_p,
6876 const char *printername,
6877 const char *drivername,
6878 const char *portname,
6879 struct spoolss_DeviceMode *devmode,
6880 bool ex)
6882 WERROR result;
6883 struct spoolss_AddPrinter r;
6884 struct spoolss_AddPrinterEx rex;
6885 struct spoolss_SetPrinterInfoCtr info_ctr;
6886 struct spoolss_SetPrinterInfo2 info2;
6887 struct spoolss_DevmodeContainer devmode_ctr;
6888 struct sec_desc_buf secdesc_ctr;
6889 struct spoolss_UserLevelCtr userlevel_ctr;
6890 struct policy_handle handle;
6891 bool found = false;
6892 bool existing_printer_deleted = false;
6893 struct dcerpc_binding_handle *b = p->binding_handle;
6895 ZERO_STRUCT(devmode_ctr);
6896 ZERO_STRUCT(secdesc_ctr);
6897 ZERO_STRUCT(userlevel_ctr);
6899 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6900 ex ? "Ex":"", printername);
6902 devmode_ctr.devmode = devmode;
6904 userlevel_ctr.level = 1;
6906 rex.in.server = NULL;
6907 rex.in.info_ctr = &info_ctr;
6908 rex.in.devmode_ctr = &devmode_ctr;
6909 rex.in.secdesc_ctr = &secdesc_ctr;
6910 rex.in.userlevel_ctr = &userlevel_ctr;
6911 rex.out.handle = &handle;
6913 r.in.server = NULL;
6914 r.in.info_ctr = &info_ctr;
6915 r.in.devmode_ctr = &devmode_ctr;
6916 r.in.secdesc_ctr = &secdesc_ctr;
6917 r.out.handle = &handle;
6919 again:
6921 /* try to add printer to printer list (level 2) */
6923 ZERO_STRUCT(info2);
6925 info_ctr.info.info2 = &info2;
6926 info_ctr.level = 2;
6928 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6929 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6930 "failed to add printer");
6931 result = ex ? rex.out.result : r.out.result;
6932 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6933 "unexpected result code");
6935 info2.printername = printername;
6937 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6938 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6939 "failed to add printer");
6940 result = ex ? rex.out.result : r.out.result;
6942 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6943 struct policy_handle printer_handle;
6945 if (existing_printer_deleted) {
6946 torture_fail(tctx, "already deleted printer still existing?");
6949 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6950 "failed to open printer handle");
6952 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6953 "failed to delete printer");
6955 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6956 "failed to close server handle");
6958 existing_printer_deleted = true;
6960 goto again;
6963 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6964 "unexpected result code");
6966 info2.portname = portname;
6968 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6969 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6970 "failed to add printer");
6971 result = ex ? rex.out.result : r.out.result;
6972 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6973 "unexpected result code");
6975 info2.drivername = drivername;
6977 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6978 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6979 "failed to add printer");
6980 result = ex ? rex.out.result : r.out.result;
6982 /* w2k8r2 allows to add printer w/o defining printprocessor */
6984 if (!W_ERROR_IS_OK(result)) {
6985 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6986 "unexpected result code");
6988 info2.printprocessor = "winprint";
6990 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6991 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6992 "failed to add printer");
6993 result = ex ? rex.out.result : r.out.result;
6994 torture_assert_werr_ok(tctx, result,
6995 "failed to add printer");
6998 *handle_p = handle;
7000 /* we are paranoid, really check if the printer is there now */
7002 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7003 PRINTER_ENUM_LOCAL, 1,
7004 printername,
7005 &found),
7006 "failed to enum printers");
7007 torture_assert(tctx, found, "failed to find newly added printer");
7009 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7010 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7011 "failed to add printer");
7012 result = ex ? rex.out.result : r.out.result;
7013 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7014 "unexpected result code");
7016 return true;
7019 static bool test_printer_info(struct torture_context *tctx,
7020 void *private_data)
7022 struct torture_printer_context *t =
7023 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7024 struct dcerpc_pipe *p = t->spoolss_pipe;
7025 struct dcerpc_binding_handle *b = p->binding_handle;
7027 bool ret = true;
7029 if (torture_setting_bool(tctx, "samba3", false)) {
7030 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7033 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7034 ret = false;
7037 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7038 ret = false;
7041 return ret;
7044 static bool test_EnumPrinterKey(struct torture_context *tctx,
7045 struct dcerpc_binding_handle *b,
7046 struct policy_handle *handle,
7047 const char *key_name,
7048 const char ***array)
7050 struct spoolss_EnumPrinterKey r;
7051 uint32_t needed = 0;
7052 union spoolss_KeyNames key_buffer;
7053 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7054 uint32_t _ndr_size;
7055 int i;
7057 r.in.handle = handle;
7058 r.in.key_name = key_name;
7059 r.out.key_buffer = &key_buffer;
7060 r.out.needed = &needed;
7061 r.out._ndr_size = &_ndr_size;
7063 for (i=0; i < ARRAY_SIZE(offered); i++) {
7065 if (offered[i] < 0 && needed) {
7066 if (needed <= 4) {
7067 continue;
7069 r.in.offered = needed + offered[i];
7070 } else {
7071 r.in.offered = offered[i];
7074 ZERO_STRUCT(key_buffer);
7076 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7078 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7079 "failed to call EnumPrinterKey");
7080 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7082 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7083 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7084 _ndr_size, r.in.offered/2));
7086 r.in.offered = needed;
7087 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7088 "failed to call EnumPrinterKey");
7091 if (offered[i] > 0) {
7092 torture_assert_werr_ok(tctx, r.out.result,
7093 "failed to call EnumPrinterKey");
7096 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7097 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7098 _ndr_size, r.in.offered/2));
7100 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7101 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7103 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7104 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7106 if (key_buffer.string_array) {
7107 uint32_t calc_needed = 0;
7108 int s;
7109 for (s=0; key_buffer.string_array[s]; s++) {
7110 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7112 if (!key_buffer.string_array[0]) {
7113 calc_needed += 2;
7115 calc_needed += 2;
7117 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7118 "EnumPrinterKey unexpected size");
7122 if (array) {
7123 *array = key_buffer.string_array;
7126 return true;
7129 bool test_printer_all_keys(struct torture_context *tctx,
7130 struct dcerpc_binding_handle *b,
7131 struct policy_handle *handle)
7133 const char **key_array = NULL;
7134 int i;
7136 torture_comment(tctx, "Testing Printer Keys\n");
7138 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7139 "failed to call test_EnumPrinterKey");
7141 for (i=0; key_array && key_array[i]; i++) {
7142 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7143 "failed to call test_EnumPrinterKey");
7145 for (i=0; key_array && key_array[i]; i++) {
7146 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7147 "failed to call test_EnumPrinterDataEx");
7150 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7152 return true;
7155 static bool test_openprinter_wrap(struct torture_context *tctx,
7156 void *private_data)
7158 struct torture_printer_context *t =
7159 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7160 struct dcerpc_pipe *p = t->spoolss_pipe;
7161 struct dcerpc_binding_handle *b = p->binding_handle;
7162 const char *printername = t->info2.printername;
7164 return test_openprinter(tctx, b, printername);
7167 static bool test_csetprinter(struct torture_context *tctx,
7168 void *private_data)
7170 struct torture_printer_context *t =
7171 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7172 struct dcerpc_pipe *p = t->spoolss_pipe;
7174 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7175 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7176 const char *portname = t->info2.portname;
7178 union spoolss_PrinterInfo info;
7179 struct policy_handle new_handle, new_handle2;
7180 struct dcerpc_binding_handle *b = p->binding_handle;
7182 torture_comment(tctx, "Testing c_setprinter\n");
7184 torture_assert(tctx,
7185 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7186 "failed to get level 0 printer info");
7187 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7188 info.info0.c_setprinter);
7190 /* check if c_setprinter on 1st handle increases after a printer has
7191 * been added */
7193 torture_assert(tctx,
7194 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7195 "failed to add new printer");
7196 torture_assert(tctx,
7197 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7198 "failed to get level 0 printer info");
7199 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7200 info.info0.c_setprinter);
7202 /* check if c_setprinter on new handle increases after a printer has
7203 * been added */
7205 torture_assert(tctx,
7206 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7207 "failed to get level 0 printer info");
7208 torture_comment(tctx, "csetprinter on created handle: %d\n",
7209 info.info0.c_setprinter);
7211 /* open the new printer and check if c_setprinter increases */
7213 torture_assert(tctx,
7214 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7215 "failed to open created printer");
7216 torture_assert(tctx,
7217 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7218 "failed to get level 0 printer info");
7219 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7220 info.info0.c_setprinter);
7222 /* cleanup */
7224 torture_assert(tctx,
7225 test_ClosePrinter(tctx, b, &new_handle2),
7226 "failed to close printer");
7227 torture_assert(tctx,
7228 test_DeletePrinter(tctx, b, &new_handle),
7229 "failed to delete new printer");
7231 return true;
7234 static bool compose_local_driver_directory(struct torture_context *tctx,
7235 const char *environment,
7236 const char *local_dir,
7237 const char **path)
7239 char *p;
7241 p = strrchr(local_dir, '/');
7242 if (!p) {
7243 return NULL;
7245 p++;
7247 if (strequal(environment, "Windows x64")) {
7248 if (!strequal(p, "x64")) {
7249 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7251 } else if (strequal(environment, "Windows NT x86")) {
7252 if (!strequal(p, "i386")) {
7253 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7255 } else {
7256 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7259 return true;
7262 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7263 const char *devicename)
7265 struct spoolss_DeviceMode *r;
7267 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7268 if (r == NULL) {
7269 return NULL;
7272 r->devicename = talloc_strdup(r, devicename);
7273 r->specversion = DMSPEC_NT4_AND_ABOVE;
7274 r->driverversion = 0x0600;
7275 r->size = 0x00dc;
7276 r->__driverextra_length = 0;
7277 r->fields = DEVMODE_FORMNAME |
7278 DEVMODE_TTOPTION |
7279 DEVMODE_PRINTQUALITY |
7280 DEVMODE_DEFAULTSOURCE |
7281 DEVMODE_COPIES |
7282 DEVMODE_SCALE |
7283 DEVMODE_PAPERSIZE |
7284 DEVMODE_ORIENTATION;
7285 r->orientation = DMORIENT_PORTRAIT;
7286 r->papersize = DMPAPER_LETTER;
7287 r->paperlength = 0;
7288 r->paperwidth = 0;
7289 r->scale = 100;
7290 r->copies = 55;
7291 r->defaultsource = DMBIN_FORMSOURCE;
7292 r->printquality = DMRES_HIGH;
7293 r->color = DMRES_MONOCHROME;
7294 r->duplex = DMDUP_SIMPLEX;
7295 r->yresolution = 0;
7296 r->ttoption = DMTT_SUBDEV;
7297 r->collate = DMCOLLATE_FALSE;
7298 r->formname = talloc_strdup(r, "Letter");
7300 return r;
7303 static bool test_architecture_buffer(struct torture_context *tctx,
7304 void *private_data)
7306 struct test_spoolss_context *ctx =
7307 talloc_get_type_abort(private_data, struct test_spoolss_context);
7309 struct spoolss_OpenPrinterEx r;
7310 struct spoolss_UserLevel1 u1;
7311 struct policy_handle handle;
7312 uint32_t architectures[] = {
7313 PROCESSOR_ARCHITECTURE_INTEL,
7314 PROCESSOR_ARCHITECTURE_IA64,
7315 PROCESSOR_ARCHITECTURE_AMD64
7317 uint32_t needed[3];
7318 int i;
7319 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7320 struct dcerpc_binding_handle *b = p->binding_handle;
7322 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7324 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7326 u1.size = 0;
7327 u1.client = NULL;
7328 u1.user = NULL;
7329 u1.build = 0;
7330 u1.major = 3;
7331 u1.minor = 0;
7332 u1.processor = architectures[i];
7334 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7335 r.in.datatype = NULL;
7336 r.in.devmode_ctr.devmode= NULL;
7337 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7338 r.in.level = 1;
7339 r.in.userlevel.level1 = &u1;
7340 r.out.handle = &handle;
7342 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7343 torture_assert_werr_ok(tctx, r.out.result, "");
7346 struct spoolss_EnumPrinters e;
7347 uint32_t count;
7348 union spoolss_PrinterInfo *info;
7350 e.in.flags = PRINTER_ENUM_LOCAL;
7351 e.in.server = NULL;
7352 e.in.level = 2;
7353 e.in.buffer = NULL;
7354 e.in.offered = 0;
7355 e.out.count = &count;
7356 e.out.info = &info;
7357 e.out.needed = &needed[i];
7359 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7360 #if 0
7361 torture_comment(tctx, "needed was %d\n", needed[i]);
7362 #endif
7365 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7368 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7369 if (needed[i-1] != needed[i]) {
7370 torture_fail(tctx,
7371 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7372 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7376 return true;
7379 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7380 void *private_data)
7382 struct test_spoolss_context *ctx =
7383 talloc_get_type_abort(private_data, struct test_spoolss_context);
7384 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7385 struct dcerpc_binding_handle *b = p->binding_handle;
7387 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7390 static bool test_PrintServer_Forms(struct torture_context *tctx,
7391 void *private_data)
7393 struct test_spoolss_context *ctx =
7394 talloc_get_type_abort(private_data, struct test_spoolss_context);
7395 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7396 struct dcerpc_binding_handle *b = p->binding_handle;
7398 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7401 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7402 void *private_data)
7404 struct test_spoolss_context *ctx =
7405 talloc_get_type_abort(private_data, struct test_spoolss_context);
7406 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7407 struct dcerpc_binding_handle *b = p->binding_handle;
7409 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7412 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7414 NTSTATUS status;
7416 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7418 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7420 torture_assert(tctx,
7421 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7422 "failed to open printserver");
7423 torture_assert(tctx,
7424 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7425 "failed to get environment");
7427 return true;
7430 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7432 struct test_spoolss_context *t;
7434 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7436 return torture_rpc_spoolss_setup_common(tctx, t);
7439 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7441 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7443 return true;
7446 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7448 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7449 bool ret;
7451 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7452 talloc_free(t);
7454 return ret;
7457 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7459 struct dcerpc_pipe *p;
7460 struct dcerpc_binding_handle *b;
7461 const char *server_name_slash;
7462 const char *driver_name;
7463 const char *printer_name;
7464 const char *port_name;
7466 torture_assert_ntstatus_ok(tctx,
7467 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7468 "Error connecting to server");
7470 p = t->spoolss_pipe;
7471 b = p->binding_handle;
7472 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7474 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7475 t->driver.info8.driver_name = TORTURE_DRIVER;
7476 t->driver.info8.driver_path = "pscript5.dll";
7477 t->driver.info8.data_file = "cups6.ppd";
7478 t->driver.info8.config_file = "ps5ui.dll";
7479 t->driver.info8.help_file = "pscript.hlp";
7480 t->driver.info8.default_datatype = "RAW";
7481 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7482 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7483 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7484 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7485 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7486 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7487 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7488 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7489 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7490 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7492 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7494 t->info2.drivername = "Microsoft XPS Document Writer";
7495 t->info2.portname = "LPT1:";
7497 printer_name = t->info2.printername;
7498 port_name = t->info2.portname;
7500 torture_assert(tctx,
7501 fillup_printserver_info(tctx, p, &t->driver),
7502 "failed to fillup printserver info");
7504 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7506 torture_assert(tctx,
7507 compose_local_driver_directory(tctx, t->driver.remote.environment,
7508 t->driver.local.driver_directory,
7509 &t->driver.local.driver_directory),
7510 "failed to compose local driver directory");
7512 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7513 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7514 t->info2.drivername, t->driver.remote.environment);
7515 t->have_driver = true;
7516 goto try_add;
7519 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7520 t->info2.drivername, t->driver.remote.environment);
7521 torture_comment(tctx, "trying to upload own driver\n");
7523 if (!directory_exist(t->driver.local.driver_directory)) {
7524 torture_warning(tctx, "no local driver is available!");
7525 t->have_driver = false;
7526 goto try_add;
7529 torture_assert(tctx,
7530 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7531 "failed to upload printer driver");
7533 torture_assert(tctx,
7534 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7535 "failed to add driver");
7537 t->added_driver = true;
7538 t->have_driver = true;
7540 try_add:
7541 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7543 if (t->wellknown) {
7544 torture_assert(tctx,
7545 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7546 "failed to add wellknown printer");
7547 } else {
7548 torture_assert(tctx,
7549 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7550 "failed to add printer");
7553 return true;
7556 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7558 struct torture_printer_context *t;
7560 *data = t = talloc_zero(tctx, struct torture_printer_context);
7562 t->ex = false;
7563 t->wellknown = false;
7564 t->info2.printername = TORTURE_PRINTER;
7565 t->devmode = NULL;
7567 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7570 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7572 struct torture_printer_context *t;
7574 *data = t = talloc_zero(tctx, struct torture_printer_context);
7576 t->ex = true;
7577 t->wellknown = false;
7578 t->info2.printername = TORTURE_PRINTER_EX;
7579 t->devmode = NULL;
7581 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7584 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7586 struct torture_printer_context *t;
7588 *data = t = talloc_zero(tctx, struct torture_printer_context);
7590 t->ex = false;
7591 t->wellknown = true;
7592 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7593 t->devmode = NULL;
7595 /* FIXME */
7596 if (t->wellknown) {
7597 torture_skip(tctx, "skipping AddPrinter level 1");
7600 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7603 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7605 struct torture_printer_context *t;
7607 *data = t = talloc_zero(tctx, struct torture_printer_context);
7609 t->ex = true;
7610 t->wellknown = true;
7611 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7612 t->devmode = NULL;
7614 /* FIXME */
7615 if (t->wellknown) {
7616 torture_skip(tctx, "skipping AddPrinterEx level 1");
7619 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7622 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7624 struct torture_printer_context *t;
7626 *data = t = talloc_zero(tctx, struct torture_printer_context);
7628 t->ex = true;
7629 t->wellknown = false;
7630 t->info2.printername = TORTURE_PRINTER_EX;
7631 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7633 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7636 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7638 bool found = false;
7639 struct dcerpc_pipe *p = t->spoolss_pipe;
7640 struct dcerpc_binding_handle *b;
7641 const char *printer_name = t->info2.printername;
7643 if (t->added_driver) {
7644 torture_assert(tctx,
7645 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7646 "failed to remove printer driver");
7649 if (p) {
7650 b = p->binding_handle;
7653 if (!t->wellknown) {
7654 torture_assert(tctx,
7655 test_DeletePrinter(tctx, b, &t->handle),
7656 "failed to delete printer");
7658 torture_assert(tctx,
7659 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7660 printer_name, &found),
7661 "failed to enumerate printers");
7663 torture_assert(tctx, !found, "deleted printer still there");
7666 return true;
7669 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7671 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7672 bool ret;
7674 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7675 talloc_free(t);
7677 return ret;
7680 static bool test_print_test(struct torture_context *tctx,
7681 void *private_data)
7683 struct torture_printer_context *t =
7684 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7685 struct dcerpc_pipe *p = t->spoolss_pipe;
7686 struct dcerpc_binding_handle *b = p->binding_handle;
7688 torture_assert(tctx,
7689 test_PausePrinter(tctx, b, &t->handle),
7690 "failed to pause printer");
7692 torture_assert(tctx,
7693 test_DoPrintTest(tctx, b, &t->handle),
7694 "failed to do print test");
7696 torture_assert(tctx,
7697 test_ResumePrinter(tctx, b, &t->handle),
7698 "failed to resume printer");
7700 return true;
7703 static bool test_print_test_extended(struct torture_context *tctx,
7704 void *private_data)
7706 struct torture_printer_context *t =
7707 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7708 struct dcerpc_pipe *p = t->spoolss_pipe;
7709 struct dcerpc_binding_handle *b = p->binding_handle;
7710 bool ret = true;
7712 torture_assert(tctx,
7713 test_PausePrinter(tctx, b, &t->handle),
7714 "failed to pause printer");
7716 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7717 if (ret == false) {
7718 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7719 if (torture_setting_bool(tctx, "samba3", false)) {
7720 torture_comment(tctx, "non-critical for samba3\n");
7721 ret = true;
7722 tctx->last_result = TORTURE_SKIP;
7726 torture_assert(tctx,
7727 test_ResumePrinter(tctx, b, &t->handle),
7728 "failed to resume printer");
7730 return ret;
7733 /* use smbd file IO to spool a print job */
7734 static bool test_print_test_smbd(struct torture_context *tctx,
7735 void *private_data)
7737 struct torture_printer_context *t =
7738 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7739 struct dcerpc_pipe *p = t->spoolss_pipe;
7740 struct dcerpc_binding_handle *b = p->binding_handle;
7741 NTSTATUS status;
7742 uint32_t count;
7743 union spoolss_JobInfo *info = NULL;
7744 int i;
7746 struct smb2_tree *tree;
7747 struct smb2_handle job_h;
7748 struct cli_credentials *credentials = cmdline_credentials;
7749 struct smbcli_options options;
7750 TALLOC_CTX *mem_ctx = talloc_new(tctx);
7752 * Do not test against the dynamically added printers, printing via
7753 * smbd means that a different spoolss process may handle the
7754 * OpenPrinter request to the one that handled the AddPrinter request.
7755 * This currently leads to an ugly race condition where one process
7756 * sees the new printer and one doesn't.
7758 const char *share = TORTURE_PRINTER_STATIC1;
7760 torture_comment(tctx, "Testing smbd job spooling\n");
7761 lpcfg_smbcli_options(tctx->lp_ctx, &options);
7763 status = smb2_connect_ext(mem_ctx,
7764 torture_setting_string(tctx, "host", NULL),
7765 lpcfg_smb_ports(tctx->lp_ctx),
7766 share,
7767 lpcfg_resolve_context(tctx->lp_ctx),
7768 credentials,
7770 &tree,
7771 tctx->ev,
7772 &options,
7773 lpcfg_socket_options(tctx->lp_ctx),
7774 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
7775 if (!NT_STATUS_IS_OK(status)) {
7776 printf("Failed to connect to SMB2 printer %s - %s\n",
7777 share, nt_errstr(status));
7778 return false;
7781 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
7782 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
7784 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
7785 sizeof("exciting print job data"));
7786 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
7788 /* check back end spoolss job was created */
7789 torture_assert(tctx,
7790 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
7791 "EnumJobs level 1 failed");
7793 for (i = 0; i < count; i++) {
7794 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
7795 break;
7798 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
7800 status = smb2_util_close(tree, job_h);
7801 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
7803 /* disconnect from printer share */
7804 talloc_free(mem_ctx);
7806 return true;
7809 static bool test_printer_sd(struct torture_context *tctx,
7810 void *private_data)
7812 struct torture_printer_context *t =
7813 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7814 struct dcerpc_pipe *p = t->spoolss_pipe;
7815 struct dcerpc_binding_handle *b = p->binding_handle;
7817 torture_assert(tctx,
7818 test_PrinterInfo_SD(tctx, b, &t->handle),
7819 "failed to test security descriptors");
7821 return true;
7824 static bool test_printer_dm(struct torture_context *tctx,
7825 void *private_data)
7827 struct torture_printer_context *t =
7828 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7829 struct dcerpc_pipe *p = t->spoolss_pipe;
7831 torture_assert(tctx,
7832 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7833 "failed to test devicemodes");
7835 return true;
7838 static bool test_printer_info_winreg(struct torture_context *tctx,
7839 void *private_data)
7841 struct torture_printer_context *t =
7842 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7843 struct dcerpc_pipe *p = t->spoolss_pipe;
7845 torture_assert(tctx,
7846 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7847 "failed to test printer info winreg");
7849 return true;
7852 static bool test_printer_change_id(struct torture_context *tctx,
7853 void *private_data)
7855 struct torture_printer_context *t =
7856 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7857 struct dcerpc_pipe *p = t->spoolss_pipe;
7859 torture_assert(tctx,
7860 test_ChangeID(tctx, p, &t->handle),
7861 "failed to test change id");
7863 return true;
7866 static bool test_printer_keys(struct torture_context *tctx,
7867 void *private_data)
7869 struct torture_printer_context *t =
7870 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7871 struct dcerpc_pipe *p = t->spoolss_pipe;
7872 struct dcerpc_binding_handle *b = p->binding_handle;
7874 torture_assert(tctx,
7875 test_printer_all_keys(tctx, b, &t->handle),
7876 "failed to test printer keys");
7878 return true;
7881 static bool test_printer_data_consistency(struct torture_context *tctx,
7882 void *private_data)
7884 struct torture_printer_context *t =
7885 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7886 struct dcerpc_pipe *p = t->spoolss_pipe;
7888 torture_assert(tctx,
7889 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7890 "failed to test printer data consistency");
7892 return true;
7895 static bool test_printer_data_keys(struct torture_context *tctx,
7896 void *private_data)
7898 struct torture_printer_context *t =
7899 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7900 struct dcerpc_pipe *p = t->spoolss_pipe;
7902 torture_assert(tctx,
7903 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7904 "failed to test printer data keys");
7906 return true;
7909 static bool test_printer_data_values(struct torture_context *tctx,
7910 void *private_data)
7912 struct torture_printer_context *t =
7913 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7914 struct dcerpc_pipe *p = t->spoolss_pipe;
7916 torture_assert(tctx,
7917 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7918 "failed to test printer data values");
7920 return true;
7923 static bool test_printer_data_set(struct torture_context *tctx,
7924 void *private_data)
7926 struct torture_printer_context *t =
7927 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7928 struct dcerpc_pipe *p = t->spoolss_pipe;
7930 torture_assert(tctx,
7931 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7932 "failed to test printer data set");
7934 return true;
7937 static bool test_printer_data_winreg(struct torture_context *tctx,
7938 void *private_data)
7940 struct torture_printer_context *t =
7941 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7942 struct dcerpc_pipe *p = t->spoolss_pipe;
7944 torture_assert(tctx,
7945 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7946 "failed to test printer data winreg");
7948 return true;
7951 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7952 void *private_data)
7954 struct torture_printer_context *t =
7955 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7956 struct dcerpc_pipe *p = t->spoolss_pipe;
7958 torture_assert(tctx,
7959 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7960 "failed to test printer data winreg dsspooler");
7962 return true;
7965 static bool test_driver_info_winreg(struct torture_context *tctx,
7966 void *private_data)
7968 struct torture_printer_context *t =
7969 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7970 struct dcerpc_pipe *p = t->spoolss_pipe;
7971 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7973 if (!t->have_driver) {
7974 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7977 torture_assert(tctx,
7978 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7979 "failed to test driver info winreg");
7981 return true;
7984 void torture_tcase_printer(struct torture_tcase *tcase)
7986 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7987 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7988 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7989 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7990 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
7991 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7992 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7993 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7994 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7995 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7996 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7997 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7998 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7999 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8000 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8001 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8002 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8003 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8004 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8007 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8009 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8010 struct torture_tcase *tcase;
8012 tcase = torture_suite_add_tcase(suite, "addprinter");
8014 torture_tcase_set_fixture(tcase,
8015 torture_rpc_spoolss_printer_setup,
8016 torture_rpc_spoolss_printer_teardown);
8018 torture_tcase_printer(tcase);
8020 tcase = torture_suite_add_tcase(suite, "addprinterex");
8022 torture_tcase_set_fixture(tcase,
8023 torture_rpc_spoolss_printerex_setup,
8024 torture_rpc_spoolss_printer_teardown);
8026 torture_tcase_printer(tcase);
8028 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8030 torture_tcase_set_fixture(tcase,
8031 torture_rpc_spoolss_printerwkn_setup,
8032 torture_rpc_spoolss_printer_teardown);
8034 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8036 torture_tcase_set_fixture(tcase,
8037 torture_rpc_spoolss_printerexwkn_setup,
8038 torture_rpc_spoolss_printer_teardown);
8040 #if 0
8041 /* test is not correct */
8042 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8044 torture_tcase_set_fixture(tcase,
8045 torture_rpc_spoolss_printerdm_setup,
8046 torture_rpc_spoolss_printer_teardown);
8048 torture_tcase_printer(tcase);
8049 #endif
8050 return suite;
8053 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8055 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8056 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8058 torture_tcase_set_fixture(tcase,
8059 torture_rpc_spoolss_setup,
8060 torture_rpc_spoolss_teardown);
8062 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8063 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8064 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8065 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8066 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8067 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8068 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8069 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8070 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8071 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8072 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8073 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8074 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8075 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8076 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8077 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8078 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8079 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8080 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8081 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8083 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8085 return suite;
8088 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8089 struct dcerpc_binding_handle *b,
8090 const char *server,
8091 const char *environment,
8092 const char **dir_p)
8094 struct spoolss_GetPrinterDriverDirectory r;
8095 uint32_t needed;
8097 r.in.server = server;
8098 r.in.environment = environment;
8099 r.in.level = 1;
8100 r.in.buffer = NULL;
8101 r.in.offered = 0;
8102 r.out.needed = &needed;
8104 torture_assert_ntstatus_ok(tctx,
8105 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8106 "failed to query driver directory");
8108 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8109 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8110 r.in.buffer = &blob;
8111 r.in.offered = needed;
8113 torture_assert_ntstatus_ok(tctx,
8114 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8115 "failed to query driver directory");
8118 torture_assert_werr_ok(tctx, r.out.result,
8119 "failed to query driver directory");
8121 if (dir_p) {
8122 *dir_p = r.out.info->info1.directory_name;
8125 return true;
8128 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8130 if (info_ctr == NULL) {
8131 return NULL;
8134 switch (info_ctr->level) {
8135 case 1:
8136 return info_ctr->info.info1->driver_name;
8137 case 2:
8138 return info_ctr->info.info2->driver_name;
8139 case 3:
8140 return info_ctr->info.info3->driver_name;
8141 case 4:
8142 return info_ctr->info.info4->driver_name;
8143 case 6:
8144 return info_ctr->info.info6->driver_name;
8145 case 8:
8146 return info_ctr->info.info8->driver_name;
8147 default:
8148 return NULL;
8152 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8154 if (info_ctr == NULL) {
8155 return NULL;
8158 switch (info_ctr->level) {
8159 case 2:
8160 return info_ctr->info.info2->architecture;
8161 case 3:
8162 return info_ctr->info.info3->architecture;
8163 case 4:
8164 return info_ctr->info.info4->architecture;
8165 case 6:
8166 return info_ctr->info.info6->architecture;
8167 case 8:
8168 return info_ctr->info.info8->architecture;
8169 default:
8170 return NULL;
8175 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8176 struct dcerpc_binding_handle *b,
8177 const char *servername,
8178 struct spoolss_AddDriverInfoCtr *info_ctr,
8179 WERROR expected_result)
8181 struct spoolss_AddPrinterDriver r;
8182 const char *drivername = get_driver_from_info(info_ctr);
8183 const char *environment = get_environment_from_info(info_ctr);
8185 r.in.servername = servername;
8186 r.in.info_ctr = info_ctr;
8188 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8189 drivername, info_ctr->level, environment);
8191 torture_assert_ntstatus_ok(tctx,
8192 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8193 "spoolss_AddPrinterDriver failed");
8194 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8195 "spoolss_AddPrinterDriver failed with unexpected result");
8197 return true;
8201 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8202 struct dcerpc_binding_handle *b,
8203 const char *servername,
8204 struct spoolss_AddDriverInfoCtr *info_ctr,
8205 uint32_t flags,
8206 WERROR expected_result)
8208 struct spoolss_AddPrinterDriverEx r;
8209 const char *drivername = get_driver_from_info(info_ctr);
8210 const char *environment = get_environment_from_info(info_ctr);
8212 r.in.servername = servername;
8213 r.in.info_ctr = info_ctr;
8214 r.in.flags = flags;
8216 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8217 drivername, info_ctr->level, environment);
8219 torture_assert_ntstatus_ok(tctx,
8220 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8221 "AddPrinterDriverEx failed");
8222 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8223 "AddPrinterDriverEx failed with unexpected result");
8225 return true;
8228 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8229 if (path && strlen(path)) {\
8230 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8233 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8234 struct dcerpc_binding_handle *b,
8235 const char *server_name,
8236 struct spoolss_AddDriverInfo8 *r,
8237 uint32_t flags,
8238 bool ex,
8239 const char *remote_driver_dir)
8241 struct spoolss_AddDriverInfoCtr info_ctr;
8242 struct spoolss_AddDriverInfo1 info1;
8244 ZERO_STRUCT(info1);
8246 info_ctr.level = 1;
8247 info_ctr.info.info1 = &info1;
8249 if (ex) {
8250 torture_assert(tctx,
8251 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8252 "failed to test AddPrinterDriverEx level 1");
8253 } else {
8254 torture_assert(tctx,
8255 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8256 "failed to test AddPrinterDriver level 1");
8259 info1.driver_name = r->driver_name;
8261 if (ex) {
8262 torture_assert(tctx,
8263 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8264 "failed to test AddPrinterDriverEx level 1");
8265 } else {
8266 torture_assert(tctx,
8267 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8268 "failed to test AddPrinterDriver level 1");
8271 return true;
8274 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8275 struct dcerpc_binding_handle *b,
8276 const char *server_name,
8277 struct spoolss_AddDriverInfo8 *r,
8278 uint32_t flags,
8279 bool ex,
8280 const char *remote_driver_dir)
8282 struct spoolss_AddDriverInfoCtr info_ctr;
8283 struct spoolss_AddDriverInfo2 info2;
8284 union spoolss_DriverInfo info;
8286 ZERO_STRUCT(info2);
8288 info_ctr.level = 2;
8289 info_ctr.info.info2 = &info2;
8291 if (ex) {
8292 torture_assert(tctx,
8293 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8294 "failed to test AddPrinterDriverEx level 2");
8295 } else {
8296 torture_assert(tctx,
8297 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8298 "failed to test AddPrinterDriver level 2");
8301 info2.driver_name = r->driver_name;
8303 if (ex) {
8304 torture_assert(tctx,
8305 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8306 "failed to test AddPrinterDriverEx level 2");
8307 } else {
8308 torture_assert(tctx,
8309 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8310 "failed to test AddPrinterDriver level 2");
8313 info2.version = r->version;
8315 if (ex) {
8316 torture_assert(tctx,
8317 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8318 "failed to test AddPrinterDriverEx level 2");
8319 } else {
8320 torture_assert(tctx,
8321 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8322 "failed to test AddPrinterDriver level 2");
8325 info2.architecture = r->architecture;
8327 if (ex) {
8328 torture_assert(tctx,
8329 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8330 "failed to test AddPrinterDriverEx level 2");
8331 } else {
8332 torture_assert(tctx,
8333 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8334 "failed to test AddPrinterDriver level 2");
8337 info2.driver_path = r->driver_path;
8339 if (ex) {
8340 torture_assert(tctx,
8341 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8342 "failed to test AddPrinterDriverEx level 2");
8343 } else {
8344 torture_assert(tctx,
8345 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8346 "failed to test AddPrinterDriver level 2");
8349 info2.data_file = r->data_file;
8351 if (ex) {
8352 torture_assert(tctx,
8353 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8354 "failed to test AddPrinterDriverEx level 2");
8355 } else {
8356 torture_assert(tctx,
8357 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8358 "failed to test AddPrinterDriver level 2");
8361 info2.config_file = r->config_file;
8363 if (ex) {
8364 torture_assert(tctx,
8365 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8366 "failed to test AddPrinterDriverEx");
8369 if (ex) {
8370 torture_assert(tctx,
8371 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8372 "failed to test AddPrinterDriverEx level 2");
8373 } else {
8374 torture_assert(tctx,
8375 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8376 "failed to test AddPrinterDriver level 2");
8379 torture_assert(tctx,
8380 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8381 "failed to find added printer driver");
8383 if (remote_driver_dir) {
8384 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8385 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8386 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8389 return true;
8392 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8393 struct dcerpc_binding_handle *b,
8394 const char *server_name,
8395 struct spoolss_AddDriverInfo8 *r,
8396 uint32_t flags,
8397 bool ex,
8398 const char *remote_driver_dir)
8400 struct spoolss_AddDriverInfoCtr info_ctr;
8401 struct spoolss_AddDriverInfo3 info3;
8402 union spoolss_DriverInfo info;
8404 info3.driver_name = r->driver_name;
8405 info3.version = r->version;
8406 info3.architecture = r->architecture;
8407 info3.driver_path = r->driver_path;
8408 info3.data_file = r->data_file;
8409 info3.config_file = r->config_file;
8410 info3.help_file = r->help_file;
8411 info3.monitor_name = r->monitor_name;
8412 info3.default_datatype = r->default_datatype;
8413 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8414 info3.dependent_files = r->dependent_files;
8416 info_ctr.level = 3;
8417 info_ctr.info.info3 = &info3;
8419 if (ex) {
8420 torture_assert(tctx,
8421 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8422 "failed to test AddPrinterDriverEx level 3");
8423 } else {
8424 torture_assert(tctx,
8425 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8426 "failed to test AddPrinterDriver level 3");
8429 torture_assert(tctx,
8430 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8431 "failed to find added printer driver");
8433 if (remote_driver_dir) {
8434 int i;
8435 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8436 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8437 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8438 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8439 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8440 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8444 return true;
8447 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8448 struct dcerpc_binding_handle *b,
8449 const char *server_name,
8450 struct spoolss_AddDriverInfo8 *r,
8451 uint32_t flags,
8452 bool ex,
8453 const char *remote_driver_dir)
8455 struct spoolss_AddDriverInfoCtr info_ctr;
8456 struct spoolss_AddDriverInfo4 info4;
8457 union spoolss_DriverInfo info;
8459 info4.version = r->version;
8460 info4.driver_name = r->driver_name;
8461 info4.architecture = r->architecture;
8462 info4.driver_path = r->driver_path;
8463 info4.data_file = r->data_file;
8464 info4.config_file = r->config_file;
8465 info4.help_file = r->help_file;
8466 info4.monitor_name = r->monitor_name;
8467 info4.default_datatype = r->default_datatype;
8468 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8469 info4.dependent_files = r->dependent_files;
8470 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8471 info4.previous_names = r->previous_names;
8473 info_ctr.level = 4;
8474 info_ctr.info.info4 = &info4;
8476 if (ex) {
8477 torture_assert(tctx,
8478 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8479 "failed to test AddPrinterDriverEx level 4");
8480 } else {
8481 torture_assert(tctx,
8482 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8483 "failed to test AddPrinterDriver level 4");
8486 torture_assert(tctx,
8487 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8488 "failed to find added printer driver");
8490 if (remote_driver_dir) {
8491 int i;
8492 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8493 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8494 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8495 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8496 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8497 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8501 return true;
8504 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8505 struct dcerpc_binding_handle *b,
8506 const char *server_name,
8507 struct spoolss_AddDriverInfo8 *r,
8508 uint32_t flags,
8509 bool ex,
8510 const char *remote_driver_dir)
8512 struct spoolss_AddDriverInfoCtr info_ctr;
8513 struct spoolss_AddDriverInfo6 info6;
8514 union spoolss_DriverInfo info;
8516 info6.version = r->version;
8517 info6.driver_name = r->driver_name;
8518 info6.architecture = r->architecture;
8519 info6.driver_path = r->driver_path;
8520 info6.data_file = r->data_file;
8521 info6.config_file = r->config_file;
8522 info6.help_file = r->help_file;
8523 info6.monitor_name = r->monitor_name;
8524 info6.default_datatype = r->default_datatype;
8525 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8526 info6.dependent_files = r->dependent_files;
8527 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8528 info6.previous_names = r->previous_names;
8529 info6.driver_date = r->driver_date;
8530 info6.driver_version = r->driver_version;
8531 info6.manufacturer_name = r->manufacturer_name;
8532 info6.manufacturer_url = r->manufacturer_url;
8533 info6.hardware_id = r->hardware_id;
8534 info6.provider = r->provider;
8536 info_ctr.level = 6;
8537 info_ctr.info.info6 = &info6;
8539 if (ex) {
8540 torture_assert(tctx,
8541 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8542 "failed to test AddPrinterDriverEx level 6");
8543 } else {
8544 torture_assert(tctx,
8545 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8546 "failed to test AddPrinterDriver level 6");
8549 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8551 if (!ex) {
8552 return true;
8555 torture_assert(tctx,
8556 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8557 "failed to find added printer driver");
8559 if (remote_driver_dir) {
8560 int i;
8561 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8562 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8563 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8564 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8565 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8566 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8570 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8571 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8573 return true;
8576 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8577 struct dcerpc_binding_handle *b,
8578 const char *server_name,
8579 struct spoolss_AddDriverInfo8 *r,
8580 uint32_t flags,
8581 bool ex,
8582 const char *remote_driver_dir)
8584 struct spoolss_AddDriverInfoCtr info_ctr;
8585 union spoolss_DriverInfo info;
8587 info_ctr.level = 8;
8588 info_ctr.info.info8 = r;
8590 if (ex) {
8591 torture_assert(tctx,
8592 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8593 "failed to test AddPrinterDriverEx level 8");
8594 } else {
8595 torture_assert(tctx,
8596 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8597 "failed to test AddPrinterDriver level 8");
8600 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8602 if (!ex) {
8603 return true;
8606 torture_assert(tctx,
8607 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8608 "failed to find added printer driver");
8610 if (remote_driver_dir) {
8611 int i;
8612 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8613 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8614 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8615 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8616 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8617 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8621 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8622 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8624 return true;
8627 #undef ASSERT_DRIVER_PATH
8629 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8630 struct dcerpc_binding_handle *b,
8631 const char *server,
8632 const char *driver,
8633 const char *environment,
8634 WERROR expected_result)
8636 struct spoolss_DeletePrinterDriver r;
8638 r.in.server = server;
8639 r.in.architecture = environment;
8640 r.in.driver = driver;
8642 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8644 torture_assert_ntstatus_ok(tctx,
8645 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8646 "DeletePrinterDriver failed");
8647 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8648 "DeletePrinterDriver failed with unexpected result");
8650 return true;
8653 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8654 struct dcerpc_binding_handle *b,
8655 const char *server,
8656 const char *driver,
8657 const char *environment,
8658 uint32_t delete_flags,
8659 uint32_t version,
8660 WERROR expected_result)
8662 struct spoolss_DeletePrinterDriverEx r;
8664 r.in.server = server;
8665 r.in.architecture = environment;
8666 r.in.driver = driver;
8667 r.in.delete_flags = delete_flags;
8668 r.in.version = version;
8670 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8672 torture_assert_ntstatus_ok(tctx,
8673 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8674 "DeletePrinterDriverEx failed");
8675 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8676 "DeletePrinterDriverEx failed with unexpected result");
8678 return true;
8681 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8682 struct dcerpc_binding_handle *b,
8683 const char *server_name,
8684 const char *driver,
8685 const char *environment)
8687 torture_assert(tctx,
8688 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8689 "failed to delete driver");
8691 torture_assert(tctx,
8692 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8693 "failed to delete driver");
8695 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8696 torture_fail(tctx, "deleted driver still enumerated");
8699 torture_assert(tctx,
8700 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8701 "2nd delete failed");
8703 return true;
8706 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8707 struct dcerpc_binding_handle *b,
8708 const char *server_name,
8709 const char *driver,
8710 const char *environment,
8711 uint32_t delete_flags,
8712 uint32_t version)
8714 torture_assert(tctx,
8715 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8716 "failed to delete driver");
8718 torture_assert(tctx,
8719 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8720 "failed to delete driver");
8722 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8723 torture_fail(tctx, "deleted driver still enumerated");
8726 torture_assert(tctx,
8727 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8728 "2nd delete failed");
8730 return true;
8733 static bool test_PrinterDriver_args(struct torture_context *tctx,
8734 struct dcerpc_binding_handle *b,
8735 const char *server_name,
8736 uint32_t level,
8737 struct spoolss_AddDriverInfo8 *r,
8738 uint32_t add_flags,
8739 uint32_t delete_flags,
8740 uint32_t delete_version,
8741 bool ex,
8742 const char *remote_driver_dir)
8744 bool ret = true;
8746 switch (level) {
8747 case 1:
8748 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8749 break;
8750 case 2:
8751 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8752 break;
8753 case 3:
8754 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8755 break;
8756 case 4:
8757 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8758 break;
8759 case 6:
8760 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8761 break;
8762 case 8:
8763 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8764 break;
8765 default:
8766 return false;
8769 if (ret == false) {
8770 return ret;
8773 if (level == 1) {
8774 return ret;
8777 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8779 if (!ex && (level == 6 || level == 8)) {
8780 return ret;
8784 struct dcerpc_pipe *p2;
8785 struct policy_handle hive_handle;
8786 struct dcerpc_binding_handle *b2;
8788 torture_assert_ntstatus_ok(tctx,
8789 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8790 "could not open winreg pipe");
8791 b2 = p2->binding_handle;
8793 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8795 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8797 test_winreg_CloseKey(tctx, b2, &hive_handle);
8799 talloc_free(p2);
8802 if (ex) {
8803 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8804 } else {
8805 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8809 static bool fillup_printserver_info(struct torture_context *tctx,
8810 struct dcerpc_pipe *p,
8811 struct torture_driver_context *d)
8813 struct policy_handle server_handle;
8814 struct dcerpc_binding_handle *b = p->binding_handle;
8815 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8817 torture_assert(tctx,
8818 test_OpenPrinter_server(tctx, p, &server_handle),
8819 "failed to open printserver");
8820 torture_assert(tctx,
8821 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8822 "failed to get environment");
8823 torture_assert(tctx,
8824 test_ClosePrinter(tctx, b, &server_handle),
8825 "failed to close printserver");
8827 torture_assert(tctx,
8828 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8829 d->local.environment ? d->local.environment : d->remote.environment,
8830 &d->remote.driver_directory),
8831 "failed to get driver directory");
8833 return true;
8836 static const char *driver_directory_dir(const char *driver_directory)
8838 char *p;
8840 p = strrchr(driver_directory, '\\');
8841 if (p) {
8842 return p+1;
8845 return NULL;
8848 static const char *driver_directory_share(struct torture_context *tctx,
8849 const char *driver_directory)
8851 const char *p;
8852 char *tok;
8854 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8855 driver_directory += 2;
8858 p = talloc_strdup(tctx, driver_directory);
8860 torture_assert(tctx,
8861 next_token_talloc(tctx, &p, &tok, "\\"),
8862 "cannot explode uri");
8863 torture_assert(tctx,
8864 next_token_talloc(tctx, &p, &tok, "\\"),
8865 "cannot explode uri");
8867 return tok;
8870 static bool upload_printer_driver_file(struct torture_context *tctx,
8871 struct smbcli_state *cli,
8872 struct torture_driver_context *d,
8873 const char *file_name)
8875 XFILE *f;
8876 int fnum;
8877 uint8_t *buf;
8878 int maxwrite = 64512;
8879 off_t nread = 0;
8880 size_t start = 0;
8881 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8882 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8883 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8885 if (!file_name || strlen(file_name) == 0) {
8886 return true;
8889 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8891 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8892 if (fnum == -1) {
8893 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8896 f = x_fopen(local_name, O_RDONLY, 0);
8897 if (f == NULL) {
8898 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8901 buf = talloc_array(tctx, uint8_t, maxwrite);
8902 if (!buf) {
8903 return false;
8906 while (!x_feof(f)) {
8907 int n = maxwrite;
8908 int ret;
8910 if ((n = x_fread(buf, 1, n, f)) < 1) {
8911 if((n == 0) && x_feof(f))
8912 break; /* Empty local file. */
8914 torture_warning(tctx,
8915 "failed to read file: %s\n", strerror(errno));
8916 break;
8919 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8921 if (n != ret) {
8922 torture_warning(tctx,
8923 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8924 break;
8927 nread += n;
8930 x_fclose(f);
8932 torture_assert_ntstatus_ok(tctx,
8933 smbcli_close(cli->tree, fnum),
8934 "failed to close file");
8936 return true;
8939 static bool connect_printer_driver_share(struct torture_context *tctx,
8940 const char *server_name,
8941 const char *share_name,
8942 struct smbcli_state **cli)
8944 struct smbcli_options smb_options;
8945 struct smbcli_session_options smb_session_options;
8947 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8948 share_name, server_name);
8950 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8951 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8953 torture_assert_ntstatus_ok(tctx,
8954 smbcli_full_connection(tctx, cli, server_name,
8955 lpcfg_smb_ports(tctx->lp_ctx),
8956 share_name, NULL,
8957 lpcfg_socket_options(tctx->lp_ctx),
8958 cmdline_credentials,
8959 lpcfg_resolve_context(tctx->lp_ctx),
8960 tctx->ev,
8961 &smb_options,
8962 &smb_session_options,
8963 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8964 "failed to open driver share");
8966 return true;
8969 static bool upload_printer_driver(struct torture_context *tctx,
8970 const char *server_name,
8971 struct torture_driver_context *d)
8973 struct smbcli_state *cli;
8974 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8975 int i;
8977 torture_assert(tctx,
8978 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8979 "failed to connect to driver share");
8981 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8982 server_name, share_name);
8984 torture_assert(tctx,
8985 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8986 "failed to upload driver_path");
8987 torture_assert(tctx,
8988 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8989 "failed to upload data_file");
8990 torture_assert(tctx,
8991 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8992 "failed to upload config_file");
8993 torture_assert(tctx,
8994 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8995 "failed to upload help_file");
8996 if (d->info8.dependent_files) {
8997 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8998 torture_assert(tctx,
8999 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9000 "failed to upload dependent_files");
9004 talloc_free(cli);
9006 return true;
9009 static bool check_printer_driver_file(struct torture_context *tctx,
9010 struct smbcli_state *cli,
9011 struct torture_driver_context *d,
9012 const char *file_name)
9014 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9015 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9016 remote_arch_dir,
9017 d->info8.version,
9018 file_name);
9019 int fnum;
9021 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9023 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9025 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9026 if (fnum == -1) {
9027 return false;
9030 torture_assert_ntstatus_ok(tctx,
9031 smbcli_close(cli->tree, fnum),
9032 "failed to close driver file");
9034 return true;
9037 static bool check_printer_driver_files(struct torture_context *tctx,
9038 const char *server_name,
9039 struct torture_driver_context *d,
9040 bool expect_exist)
9042 struct smbcli_state *cli;
9043 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9044 int i;
9046 torture_assert(tctx,
9047 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9048 "failed to connect to driver share");
9050 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9051 (expect_exist ? "": "non-"),
9052 server_name, share_name);
9054 if (d->info8.driver_path && d->info8.driver_path[0]) {
9055 torture_assert(tctx,
9056 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9057 "failed driver_path check");
9059 if (d->info8.data_file && d->info8.data_file[0]) {
9060 torture_assert(tctx,
9061 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9062 "failed data_file check");
9064 if (d->info8.config_file && d->info8.config_file[0]) {
9065 torture_assert(tctx,
9066 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9067 "failed config_file check");
9069 if (d->info8.help_file && d->info8.help_file[0]) {
9070 torture_assert(tctx,
9071 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9072 "failed help_file check");
9074 if (d->info8.dependent_files) {
9075 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9076 torture_assert(tctx,
9077 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9078 "failed dependent_files check");
9082 talloc_free(cli);
9084 return true;
9087 static bool remove_printer_driver_file(struct torture_context *tctx,
9088 struct smbcli_state *cli,
9089 struct torture_driver_context *d,
9090 const char *file_name)
9092 const char *remote_name;
9093 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9095 if (!file_name || strlen(file_name) == 0) {
9096 return true;
9099 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9101 torture_comment(tctx, "Removing %s\n", remote_name);
9103 torture_assert_ntstatus_ok(tctx,
9104 smbcli_unlink(cli->tree, remote_name),
9105 "failed to unlink");
9107 return true;
9110 static bool remove_printer_driver(struct torture_context *tctx,
9111 const char *server_name,
9112 struct torture_driver_context *d)
9114 struct smbcli_state *cli;
9115 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9116 int i;
9118 torture_assert(tctx,
9119 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9120 "failed to connect to driver share");
9122 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9123 server_name, share_name);
9125 torture_assert(tctx,
9126 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9127 "failed to remove driver_path");
9128 torture_assert(tctx,
9129 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9130 "failed to remove data_file");
9131 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9132 torture_assert(tctx,
9133 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9134 "failed to remove config_file");
9136 torture_assert(tctx,
9137 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9138 "failed to remove help_file");
9139 if (d->info8.dependent_files) {
9140 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9141 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9142 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9143 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9144 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9145 continue;
9147 torture_assert(tctx,
9148 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9149 "failed to remove dependent_files");
9153 talloc_free(cli);
9155 return true;
9159 static bool test_add_driver_arg(struct torture_context *tctx,
9160 struct dcerpc_pipe *p,
9161 struct torture_driver_context *d)
9163 bool ret = true;
9164 struct dcerpc_binding_handle *b = p->binding_handle;
9165 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9166 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9167 int i;
9168 struct spoolss_AddDriverInfo8 info8;
9169 uint32_t add_flags = APD_COPY_NEW_FILES;
9170 uint32_t delete_flags = 0;
9172 ZERO_STRUCT(info8);
9174 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9175 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9177 torture_assert(tctx,
9178 fillup_printserver_info(tctx, p, d),
9179 "failed to fillup printserver info");
9181 if (!directory_exist(d->local.driver_directory)) {
9182 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9185 torture_assert(tctx,
9186 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9187 "failed to upload printer driver");
9189 info8 = d->info8;
9190 if (d->info8.dependent_files) {
9191 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9192 if (d->info8.dependent_files->string) {
9193 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9195 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9196 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9197 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9201 info8.architecture = d->local.environment;
9203 for (i=0; i < ARRAY_SIZE(levels); i++) {
9205 if (torture_setting_bool(tctx, "samba3", false)) {
9206 switch (levels[i]) {
9207 case 2:
9208 case 4:
9209 case 8:
9210 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9211 continue;
9212 default:
9213 break;
9216 if (torture_setting_bool(tctx, "w2k3", false)) {
9217 switch (levels[i]) {
9218 case 8:
9219 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9220 continue;
9221 default:
9222 break;
9226 torture_comment(tctx,
9227 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9228 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9230 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);
9233 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9234 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9235 if (d->info8.config_file) {
9236 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9238 if (d->info8.help_file) {
9239 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9241 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9242 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9243 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9247 for (i=0; i < ARRAY_SIZE(levels); i++) {
9249 if (torture_setting_bool(tctx, "samba3", false)) {
9250 switch (levels[i]) {
9251 case 2:
9252 case 4:
9253 case 8:
9254 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9255 continue;
9256 default:
9257 break;
9260 if (torture_setting_bool(tctx, "w2k3", false)) {
9261 switch (levels[i]) {
9262 case 8:
9263 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9264 continue;
9265 default:
9266 break;
9270 torture_comment(tctx,
9271 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9272 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9274 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);
9277 torture_assert(tctx,
9278 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9279 "failed to remove printer driver");
9281 torture_comment(tctx, "\n");
9283 return ret;
9286 static bool test_add_driver_ex_64(struct torture_context *tctx,
9287 struct dcerpc_pipe *p)
9289 struct torture_driver_context *d;
9291 d = talloc_zero(tctx, struct torture_driver_context);
9293 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9294 d->info8.driver_name = TORTURE_DRIVER_EX;
9295 d->info8.architecture = NULL;
9296 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9297 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9298 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9299 d->local.environment = talloc_strdup(d, "Windows x64");
9300 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9301 d->ex = true;
9303 return test_add_driver_arg(tctx, p, d);
9306 static bool test_add_driver_ex_32(struct torture_context *tctx,
9307 struct dcerpc_pipe *p)
9309 struct torture_driver_context *d;
9311 d = talloc_zero(tctx, struct torture_driver_context);
9313 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9314 d->info8.driver_name = TORTURE_DRIVER_EX;
9315 d->info8.architecture = NULL;
9316 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9317 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9318 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9319 d->local.environment = talloc_strdup(d, "Windows NT x86");
9320 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9321 d->ex = true;
9323 return test_add_driver_arg(tctx, p, d);
9326 static bool test_add_driver_64(struct torture_context *tctx,
9327 struct dcerpc_pipe *p)
9329 struct torture_driver_context *d;
9331 d = talloc_zero(tctx, struct torture_driver_context);
9333 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9334 d->info8.driver_name = TORTURE_DRIVER;
9335 d->info8.architecture = NULL;
9336 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9337 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9338 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9339 d->local.environment = talloc_strdup(d, "Windows x64");
9340 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9341 d->ex = false;
9343 return test_add_driver_arg(tctx, p, d);
9346 static bool test_add_driver_32(struct torture_context *tctx,
9347 struct dcerpc_pipe *p)
9349 struct torture_driver_context *d;
9351 d = talloc_zero(tctx, struct torture_driver_context);
9353 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9354 d->info8.driver_name = TORTURE_DRIVER;
9355 d->info8.architecture = NULL;
9356 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9357 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9358 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9359 d->local.environment = talloc_strdup(d, "Windows NT x86");
9360 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9361 d->ex = false;
9363 return test_add_driver_arg(tctx, p, d);
9366 static bool test_add_driver_adobe(struct torture_context *tctx,
9367 struct dcerpc_pipe *p)
9369 struct torture_driver_context *d;
9371 if (!torture_setting_bool(tctx, "samba3", false)) {
9372 torture_skip(tctx, "skipping adobe test which only works against samba3");
9375 d = talloc_zero(tctx, struct torture_driver_context);
9377 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9378 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9379 d->info8.architecture = NULL;
9380 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9381 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9382 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9383 #if 0
9384 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9385 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9386 #endif
9387 d->local.environment = talloc_strdup(d, "Windows 4.0");
9388 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9389 d->ex = false;
9391 return test_add_driver_arg(tctx, p, d);
9394 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9395 struct dcerpc_pipe *p)
9397 struct torture_driver_context *d;
9398 struct spoolss_StringArray *a;
9400 if (!torture_setting_bool(tctx, "samba3", false)) {
9401 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9404 d = talloc_zero(tctx, struct torture_driver_context);
9406 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9407 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9408 d->info8.architecture = NULL;
9409 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9410 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9411 d->info8.config_file = NULL;
9412 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9413 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9414 d->info8.default_datatype = talloc_strdup(d, "RAW");
9416 a = talloc_zero(d, struct spoolss_StringArray);
9417 a->string = talloc_zero_array(a, const char *, 7);
9418 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9419 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9420 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9421 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9422 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9423 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9425 d->info8.dependent_files = a;
9426 d->local.environment = talloc_strdup(d, "Windows 4.0");
9427 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9428 d->ex = false;
9430 return test_add_driver_arg(tctx, p, d);
9433 static bool test_add_driver_timestamps(struct torture_context *tctx,
9434 struct dcerpc_pipe *p)
9436 struct torture_driver_context *d;
9437 struct timeval t = timeval_current();
9439 d = talloc_zero(tctx, struct torture_driver_context);
9441 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9442 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9443 d->info8.architecture = NULL;
9444 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9445 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9446 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9447 d->info8.driver_date = timeval_to_nttime(&t);
9448 d->local.environment = talloc_strdup(d, "Windows NT x86");
9449 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9450 d->ex = true;
9452 torture_assert(tctx,
9453 test_add_driver_arg(tctx, p, d),
9454 "");
9456 unix_to_nt_time(&d->info8.driver_date, 1);
9458 torture_assert(tctx,
9459 test_add_driver_arg(tctx, p, d),
9460 "");
9462 return true;
9465 static bool test_multiple_drivers(struct torture_context *tctx,
9466 struct dcerpc_pipe *p)
9468 struct torture_driver_context *d;
9469 struct dcerpc_binding_handle *b = p->binding_handle;
9470 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9471 int i;
9472 struct spoolss_AddDriverInfo8 info8;
9473 uint32_t add_flags = APD_COPY_NEW_FILES;
9474 uint32_t delete_flags = 0;
9476 d = talloc_zero(tctx, struct torture_driver_context);
9478 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9479 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9480 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9481 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9482 d->local.environment = talloc_strdup(d, "Windows NT x86");
9483 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9484 d->ex = true;
9486 torture_assert(tctx,
9487 fillup_printserver_info(tctx, p, d),
9488 "failed to fillup printserver info");
9490 if (!directory_exist(d->local.driver_directory)) {
9491 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9494 torture_assert(tctx,
9495 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9496 "failed to upload printer driver");
9498 info8 = d->info8;
9499 info8.architecture = d->local.environment;
9501 for (i=0; i < 3; i++) {
9502 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9504 torture_assert(tctx,
9505 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9506 "failed to add driver");
9509 torture_assert(tctx,
9510 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9511 "failed to delete driver");
9513 torture_assert(tctx,
9514 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9515 "torture_test_driver_1 no longer on the server");
9517 torture_assert(tctx,
9518 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9519 "torture_test_driver_2 no longer on the server");
9521 torture_assert(tctx,
9522 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9523 "failed to delete driver");
9525 torture_assert(tctx,
9526 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9527 "torture_test_driver_2 no longer on the server");
9529 torture_assert(tctx,
9530 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9531 "failed to delete driver");
9533 torture_assert(tctx,
9534 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9535 "failed to remove printer driver");
9537 return true;
9540 static bool test_del_driver_all_files(struct torture_context *tctx,
9541 struct dcerpc_pipe *p)
9543 struct torture_driver_context *d;
9544 struct spoolss_StringArray *a;
9545 uint32_t add_flags = APD_COPY_NEW_FILES;
9546 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9547 struct dcerpc_binding_handle *b = p->binding_handle;
9548 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9550 d = talloc_zero(tctx, struct torture_driver_context);
9552 d->ex = true;
9553 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9554 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9555 d->info8.architecture = NULL;
9556 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9557 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9558 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9559 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9560 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9561 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9563 a = talloc_zero(d, struct spoolss_StringArray);
9564 a->string = talloc_zero_array(a, const char *, 3);
9565 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9566 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9568 d->info8.dependent_files = a;
9569 d->info8.architecture = d->local.environment;
9571 torture_assert(tctx,
9572 fillup_printserver_info(tctx, p, d),
9573 "failed to fillup printserver info");
9575 if (!directory_exist(d->local.driver_directory)) {
9576 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9579 torture_assert(tctx,
9580 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9581 "failed to upload printer driver");
9583 torture_assert(tctx,
9584 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9585 "failed to add driver");
9587 torture_assert(tctx,
9588 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9589 d->info8.driver_name,
9590 d->local.environment,
9591 delete_flags,
9592 d->info8.version),
9593 "failed to delete driver");
9595 torture_assert(tctx,
9596 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9597 "printer driver file check failed");
9599 talloc_free(d);
9600 return true;
9603 static bool test_del_driver_unused_files(struct torture_context *tctx,
9604 struct dcerpc_pipe *p)
9606 struct torture_driver_context *d1;
9607 struct torture_driver_context *d2;
9608 uint32_t add_flags = APD_COPY_NEW_FILES;
9609 struct dcerpc_binding_handle *b = p->binding_handle;
9610 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9612 d1 = talloc_zero(tctx, struct torture_driver_context);
9613 d1->ex = true;
9614 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9615 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9616 d1->info8.architecture = NULL;
9617 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9618 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9619 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9620 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9621 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9622 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9623 d1->info8.architecture = d1->local.environment;
9625 d2 = talloc_zero(tctx, struct torture_driver_context);
9626 d2->ex = true;
9627 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9628 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9629 d2->info8.architecture = NULL;
9630 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9631 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9632 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9633 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9634 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9635 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9636 d2->info8.architecture = d2->local.environment;
9638 torture_assert(tctx,
9639 fillup_printserver_info(tctx, p, d1),
9640 "failed to fillup printserver info");
9641 torture_assert(tctx,
9642 fillup_printserver_info(tctx, p, d2),
9643 "failed to fillup printserver info");
9645 if (!directory_exist(d1->local.driver_directory)) {
9646 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9649 torture_assert(tctx,
9650 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9651 "failed to upload printer driver");
9652 torture_assert(tctx,
9653 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9654 "failed to add driver");
9656 torture_assert(tctx,
9657 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9658 "failed to upload printer driver");
9659 torture_assert(tctx,
9660 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9661 "failed to add driver");
9663 /* some files are in use by a separate driver, should fail */
9664 torture_assert(tctx,
9665 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9666 d1->info8.driver_name,
9667 d1->local.environment,
9668 DPD_DELETE_ALL_FILES,
9669 d1->info8.version,
9670 WERR_PRINTER_DRIVER_IN_USE),
9671 "invalid delete driver response");
9673 /* should only delete files not in use by other driver */
9674 torture_assert(tctx,
9675 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9676 d1->info8.driver_name,
9677 d1->local.environment,
9678 DPD_DELETE_UNUSED_FILES,
9679 d1->info8.version,
9680 WERR_OK),
9681 "failed to delete driver (unused files)");
9683 /* check non-overlapping were deleted */
9684 d1->info8.driver_path = NULL;
9685 d1->info8.help_file = NULL;
9686 torture_assert(tctx,
9687 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9688 "printer driver file check failed");
9689 /* d2 files should be uneffected */
9690 torture_assert(tctx,
9691 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9692 "printer driver file check failed");
9694 torture_assert(tctx,
9695 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9696 d2->info8.driver_name,
9697 d2->local.environment,
9698 DPD_DELETE_ALL_FILES,
9699 d2->info8.version,
9700 WERR_OK),
9701 "failed to delete driver");
9703 torture_assert(tctx,
9704 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9705 "printer driver file check failed");
9707 talloc_free(d1);
9708 talloc_free(d2);
9709 return true;
9712 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9714 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9716 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9717 "driver", &ndr_table_spoolss);
9718 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9719 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9721 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9722 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9724 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9726 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9728 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9730 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9732 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9734 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9736 return suite;