spoolss: make spoolss deal with ndr64 SetForm by using proper container object.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / spoolss.c
blobd13a11dc87053b54f405c8d895d27b7aaf8eb227
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 = NULL;
248 s->info2->sepfile = i->info2.sepfile;
249 s->info2->printprocessor = i->info2.printprocessor;
250 s->info2->datatype = i->info2.datatype;
251 s->info2->parameters = i->info2.parameters;
252 s->info2->secdesc_ptr = NULL;
253 s->info2->attributes = i->info2.attributes;
254 s->info2->priority = i->info2.priority;
255 s->info2->defaultpriority = i->info2.defaultpriority;
256 s->info2->starttime = i->info2.starttime;
257 s->info2->untiltime = i->info2.untiltime;
258 s->info2->status = i->info2.status;
259 s->info2->cjobs = i->info2.cjobs;
260 s->info2->averageppm = i->info2.averageppm;
261 break;
262 case 3:
263 case 4:
264 case 5:
265 case 6:
266 case 7:
267 case 8:
268 case 9:
269 default:
270 return false;
273 return true;
276 static bool test_OpenPrinter_server(struct torture_context *tctx,
277 struct dcerpc_pipe *p,
278 struct policy_handle *server_handle)
280 NTSTATUS status;
281 struct spoolss_OpenPrinter op;
282 struct dcerpc_binding_handle *b = p->binding_handle;
284 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
285 op.in.datatype = NULL;
286 op.in.devmode_ctr.devmode= NULL;
287 op.in.access_mask = 0;
288 op.out.handle = server_handle;
290 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
292 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
293 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
294 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
296 return true;
299 static bool test_EnumPorts(struct torture_context *tctx,
300 void *private_data)
302 struct test_spoolss_context *ctx =
303 talloc_get_type_abort(private_data, struct test_spoolss_context);
304 struct dcerpc_pipe *p = ctx->spoolss_pipe;
305 struct dcerpc_binding_handle *b = p->binding_handle;
306 NTSTATUS status;
307 struct spoolss_EnumPorts r;
308 uint16_t levels[] = { 1, 2 };
309 int i, j;
311 for (i=0;i<ARRAY_SIZE(levels);i++) {
312 int level = levels[i];
313 DATA_BLOB blob;
314 uint32_t needed;
315 uint32_t count;
316 union spoolss_PortInfo *info;
318 r.in.servername = "";
319 r.in.level = level;
320 r.in.buffer = NULL;
321 r.in.offered = 0;
322 r.out.needed = &needed;
323 r.out.count = &count;
324 r.out.info = &info;
326 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
328 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
329 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
330 if (W_ERROR_IS_OK(r.out.result)) {
331 /* TODO: do some more checks here */
332 continue;
334 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
335 "EnumPorts unexpected return code");
337 blob = data_blob_talloc_zero(ctx, needed);
338 r.in.buffer = &blob;
339 r.in.offered = needed;
341 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
342 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
344 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
346 torture_assert(tctx, info, "EnumPorts returned no info");
348 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
350 ctx->port_count[level] = count;
351 ctx->ports[level] = info;
354 for (i=1;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 int old_level = levels[i-1];
357 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
358 "EnumPorts invalid value");
360 /* if the array sizes are not the same we would maybe segfault in the following code */
362 for (i=0;i<ARRAY_SIZE(levels);i++) {
363 int level = levels[i];
364 for (j=0;j<ctx->port_count[level];j++) {
365 union spoolss_PortInfo *cur = &ctx->ports[level][j];
366 union spoolss_PortInfo *ref = &ctx->ports[2][j];
367 switch (level) {
368 case 1:
369 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
370 break;
371 case 2:
372 /* level 2 is our reference, and it makes no sense to compare it to itself */
373 break;
378 return true;
381 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
382 void *private_data)
384 struct test_spoolss_context *ctx =
385 talloc_get_type_abort(private_data, struct test_spoolss_context);
387 NTSTATUS status;
388 struct dcerpc_pipe *p = ctx->spoolss_pipe;
389 struct dcerpc_binding_handle *b = p->binding_handle;
390 struct spoolss_GetPrintProcessorDirectory r;
391 struct {
392 uint16_t level;
393 const char *server;
394 } levels[] = {{
395 .level = 1,
396 .server = NULL
398 .level = 1,
399 .server = ""
401 .level = 78,
402 .server = ""
404 .level = 1,
405 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
407 .level = 1024,
408 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
411 int i;
412 uint32_t needed;
414 for (i=0;i<ARRAY_SIZE(levels);i++) {
415 int level = levels[i].level;
416 DATA_BLOB blob;
418 r.in.server = levels[i].server;
419 r.in.environment = ctx->environment;
420 r.in.level = level;
421 r.in.buffer = NULL;
422 r.in.offered = 0;
423 r.out.needed = &needed;
425 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
427 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
428 torture_assert_ntstatus_ok(tctx, status,
429 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
430 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
431 "GetPrintProcessorDirectory unexpected return code");
433 blob = data_blob_talloc_zero(tctx, needed);
434 r.in.buffer = &blob;
435 r.in.offered = needed;
437 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
438 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
440 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
442 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
445 return true;
449 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
450 void *private_data)
452 struct test_spoolss_context *ctx =
453 talloc_get_type_abort(private_data, struct test_spoolss_context);
455 NTSTATUS status;
456 struct dcerpc_pipe *p = ctx->spoolss_pipe;
457 struct dcerpc_binding_handle *b = p->binding_handle;
458 struct spoolss_GetPrinterDriverDirectory r;
459 struct {
460 uint16_t level;
461 const char *server;
462 } levels[] = {{
463 .level = 1,
464 .server = NULL
466 .level = 1,
467 .server = ""
469 .level = 78,
470 .server = ""
472 .level = 1,
473 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
475 .level = 1024,
476 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
479 int i;
480 uint32_t needed;
482 for (i=0;i<ARRAY_SIZE(levels);i++) {
483 int level = levels[i].level;
484 DATA_BLOB blob;
486 r.in.server = levels[i].server;
487 r.in.environment = ctx->environment;
488 r.in.level = level;
489 r.in.buffer = NULL;
490 r.in.offered = 0;
491 r.out.needed = &needed;
493 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
495 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
496 torture_assert_ntstatus_ok(tctx, status,
497 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
498 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
499 "GetPrinterDriverDirectory unexpected return code");
501 blob = data_blob_talloc_zero(tctx, needed);
502 r.in.buffer = &blob;
503 r.in.offered = needed;
505 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
506 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
508 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
510 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
513 return true;
516 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
517 struct dcerpc_binding_handle *b,
518 const char *server_name,
519 const char *environment,
520 uint32_t level,
521 uint32_t *count_p,
522 union spoolss_DriverInfo **info_p)
524 struct spoolss_EnumPrinterDrivers r;
525 uint32_t needed;
526 uint32_t count;
527 union spoolss_DriverInfo *info;
529 r.in.server = server_name;
530 r.in.environment = environment;
531 r.in.level = level;
532 r.in.buffer = NULL;
533 r.in.offered = 0;
534 r.out.needed = &needed;
535 r.out.count = &count;
536 r.out.info = &info;
538 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
539 r.in.environment, r.in.level);
541 torture_assert_ntstatus_ok(tctx,
542 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
543 "EnumPrinterDrivers failed");
544 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
545 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
546 r.in.buffer = &blob;
547 r.in.offered = needed;
549 torture_assert_ntstatus_ok(tctx,
550 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
551 "EnumPrinterDrivers failed");
554 torture_assert_werr_ok(tctx, r.out.result,
555 "EnumPrinterDrivers failed");
557 if (count_p) {
558 *count_p = count;
560 if (info_p) {
561 *info_p = info;
564 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
566 return true;
570 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
571 struct dcerpc_binding_handle *b,
572 const char *server_name,
573 const char *environment,
574 uint32_t level,
575 const char *driver_name,
576 union spoolss_DriverInfo *info_p)
578 uint32_t count;
579 union spoolss_DriverInfo *info;
580 int i;
581 const char *environment_ret = NULL;
583 torture_assert(tctx,
584 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
585 "failed to enumerate printer drivers");
587 for (i=0; i < count; i++) {
588 const char *driver_name_ret;
589 switch (level) {
590 case 1:
591 driver_name_ret = info[i].info1.driver_name;
592 break;
593 case 2:
594 driver_name_ret = info[i].info2.driver_name;
595 environment_ret = info[i].info2.architecture;
596 break;
597 case 3:
598 driver_name_ret = info[i].info3.driver_name;
599 environment_ret = info[i].info3.architecture;
600 break;
601 case 4:
602 driver_name_ret = info[i].info4.driver_name;
603 environment_ret = info[i].info4.architecture;
604 break;
605 case 5:
606 driver_name_ret = info[i].info5.driver_name;
607 environment_ret = info[i].info5.architecture;
608 break;
609 case 6:
610 driver_name_ret = info[i].info6.driver_name;
611 environment_ret = info[i].info6.architecture;
612 break;
613 case 7:
614 driver_name_ret = info[i].info7.driver_name;
615 break;
616 case 8:
617 driver_name_ret = info[i].info8.driver_name;
618 environment_ret = info[i].info8.architecture;
619 break;
620 default:
621 break;
623 if (environment_ret) {
624 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
626 if (strequal(driver_name, driver_name_ret)) {
627 if (info_p) {
628 *info_p = info[i];
630 return true;
634 return false;
637 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
638 void *private_data)
640 struct test_spoolss_context *ctx =
641 talloc_get_type_abort(private_data, struct test_spoolss_context);
642 struct dcerpc_pipe *p = ctx->spoolss_pipe;
643 struct dcerpc_binding_handle *b = p->binding_handle;
644 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
645 int i, j, a;
647 /* FIXME: gd, come back and fix "" as server, and handle
648 * priority of returned error codes in torture test and samba 3
649 * server */
650 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
651 const char *environments[2];
653 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
654 environments[1] = ctx->environment;
656 for (a=0;a<ARRAY_SIZE(environments);a++) {
658 for (i=0;i<ARRAY_SIZE(levels);i++) {
659 int level = levels[i];
660 uint32_t count;
661 union spoolss_DriverInfo *info;
663 torture_assert(tctx,
664 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
665 "failed to enumerate drivers");
667 ctx->driver_count[level] = count;
668 ctx->drivers[level] = info;
671 for (i=1;i<ARRAY_SIZE(levels);i++) {
672 int level = levels[i];
673 int old_level = levels[i-1];
675 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
676 "EnumPrinterDrivers invalid value");
679 for (i=0;i<ARRAY_SIZE(levels);i++) {
680 int level = levels[i];
682 for (j=0;j<ctx->driver_count[level];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 = NULL;
1421 r->info.info2->devmode_ptr = NULL;
1425 static bool test_PrinterInfo(struct torture_context *tctx,
1426 struct dcerpc_binding_handle *b,
1427 struct policy_handle *handle)
1429 NTSTATUS status;
1430 struct spoolss_SetPrinter s;
1431 struct spoolss_GetPrinter q;
1432 struct spoolss_GetPrinter q0;
1433 struct spoolss_SetPrinterInfoCtr info_ctr;
1434 union spoolss_PrinterInfo info;
1435 struct spoolss_DevmodeContainer devmode_ctr;
1436 struct sec_desc_buf secdesc_ctr;
1437 uint32_t needed;
1438 bool ret = true;
1439 int i;
1441 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1443 uint32_t status_list[] = {
1444 /* these do not stick
1445 PRINTER_STATUS_PAUSED,
1446 PRINTER_STATUS_ERROR,
1447 PRINTER_STATUS_PENDING_DELETION, */
1448 PRINTER_STATUS_PAPER_JAM,
1449 PRINTER_STATUS_PAPER_OUT,
1450 PRINTER_STATUS_MANUAL_FEED,
1451 PRINTER_STATUS_PAPER_PROBLEM,
1452 PRINTER_STATUS_OFFLINE,
1453 PRINTER_STATUS_IO_ACTIVE,
1454 PRINTER_STATUS_BUSY,
1455 PRINTER_STATUS_PRINTING,
1456 PRINTER_STATUS_OUTPUT_BIN_FULL,
1457 PRINTER_STATUS_NOT_AVAILABLE,
1458 PRINTER_STATUS_WAITING,
1459 PRINTER_STATUS_PROCESSING,
1460 PRINTER_STATUS_INITIALIZING,
1461 PRINTER_STATUS_WARMING_UP,
1462 PRINTER_STATUS_TONER_LOW,
1463 PRINTER_STATUS_NO_TONER,
1464 PRINTER_STATUS_PAGE_PUNT,
1465 PRINTER_STATUS_USER_INTERVENTION,
1466 PRINTER_STATUS_OUT_OF_MEMORY,
1467 PRINTER_STATUS_DOOR_OPEN,
1468 PRINTER_STATUS_SERVER_UNKNOWN,
1469 PRINTER_STATUS_POWER_SAVE,
1470 /* these do not stick
1471 0x02000000,
1472 0x04000000,
1473 0x08000000,
1474 0x10000000,
1475 0x20000000,
1476 0x40000000,
1477 0x80000000 */
1479 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1480 uint32_t attribute_list[] = {
1481 PRINTER_ATTRIBUTE_QUEUED,
1482 /* fails with WERR_INVALID_DATATYPE:
1483 PRINTER_ATTRIBUTE_DIRECT, */
1484 /* does not stick
1485 PRINTER_ATTRIBUTE_DEFAULT, */
1486 PRINTER_ATTRIBUTE_SHARED,
1487 /* does not stick
1488 PRINTER_ATTRIBUTE_NETWORK, */
1489 PRINTER_ATTRIBUTE_HIDDEN,
1490 PRINTER_ATTRIBUTE_LOCAL,
1491 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1492 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1493 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1494 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1495 /* does not stick
1496 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1497 /* fails with WERR_INVALID_DATATYPE:
1498 PRINTER_ATTRIBUTE_RAW_ONLY, */
1499 /* these do not stick
1500 PRINTER_ATTRIBUTE_PUBLISHED,
1501 PRINTER_ATTRIBUTE_FAX,
1502 PRINTER_ATTRIBUTE_TS,
1503 0x00010000,
1504 0x00020000,
1505 0x00040000,
1506 0x00080000,
1507 0x00100000,
1508 0x00200000,
1509 0x00400000,
1510 0x00800000,
1511 0x01000000,
1512 0x02000000,
1513 0x04000000,
1514 0x08000000,
1515 0x10000000,
1516 0x20000000,
1517 0x40000000,
1518 0x80000000 */
1521 ZERO_STRUCT(devmode_ctr);
1522 ZERO_STRUCT(secdesc_ctr);
1524 s.in.handle = handle;
1525 s.in.command = 0;
1526 s.in.info_ctr = &info_ctr;
1527 s.in.devmode_ctr = &devmode_ctr;
1528 s.in.secdesc_ctr = &secdesc_ctr;
1530 q.in.handle = handle;
1531 q.out.info = &info;
1532 q0 = q;
1534 #define TESTGETCALL(call, r) \
1535 r.in.buffer = NULL; \
1536 r.in.offered = 0;\
1537 r.out.needed = &needed; \
1538 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1539 if (!NT_STATUS_IS_OK(status)) { \
1540 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1541 r.in.level, nt_errstr(status), __location__); \
1542 ret = false; \
1543 break; \
1545 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1546 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1547 r.in.buffer = &blob; \
1548 r.in.offered = needed; \
1550 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1551 if (!NT_STATUS_IS_OK(status)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, nt_errstr(status), __location__); \
1554 ret = false; \
1555 break; \
1557 if (!W_ERROR_IS_OK(r.out.result)) { \
1558 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1559 r.in.level, win_errstr(r.out.result), __location__); \
1560 ret = false; \
1561 break; \
1565 #define TESTSETCALL_EXP(call, r, err) \
1566 clear_info2(&info_ctr);\
1567 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1568 if (!NT_STATUS_IS_OK(status)) { \
1569 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1570 r.in.info_ctr->level, nt_errstr(status), __location__); \
1571 ret = false; \
1572 break; \
1574 if (!W_ERROR_IS_OK(err)) { \
1575 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1576 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1577 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1578 ret = false; \
1580 break; \
1582 if (!W_ERROR_IS_OK(r.out.result)) { \
1583 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1584 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1585 ret = false; \
1586 break; \
1589 #define TESTSETCALL(call, r) \
1590 TESTSETCALL_EXP(call, r, WERR_OK)
1592 #define STRING_EQUAL(s1, s2, field) \
1593 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1594 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1595 #field, s2, __location__); \
1596 ret = false; \
1597 break; \
1600 #define MEM_EQUAL(s1, s2, length, field) \
1601 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1602 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1603 #field, (const char *)s2, __location__); \
1604 ret = false; \
1605 break; \
1608 #define INT_EQUAL(i1, i2, field) \
1609 if (i1 != i2) { \
1610 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1611 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1612 ret = false; \
1613 break; \
1616 #define SD_EQUAL(sd1, sd2, field) \
1617 if (!security_descriptor_equal(sd1, sd2)) { \
1618 torture_comment(tctx, "Failed to set %s (%s)\n", \
1619 #field, __location__); \
1620 ret = false; \
1621 break; \
1624 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1625 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626 q.in.level = lvl1; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.level = lvl1; \
1629 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630 info_ctr.info.info ## lvl1->field1 = value;\
1631 TESTSETCALL_EXP(SetPrinter, s, err) \
1632 info_ctr.info.info ## lvl1->field1 = ""; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl1->field1 = value; \
1635 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1636 q.in.level = lvl2; \
1637 TESTGETCALL(GetPrinter, q) \
1638 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1640 } while (0)
1642 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1643 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1644 } while (0);
1646 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1647 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1648 q.in.level = lvl1; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.level = lvl1; \
1651 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1652 info_ctr.info.info ## lvl1->field1 = value; \
1653 TESTSETCALL(SetPrinter, s) \
1654 info_ctr.info.info ## lvl1->field1 = 0; \
1655 TESTGETCALL(GetPrinter, q) \
1656 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1657 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1658 q.in.level = lvl2; \
1659 TESTGETCALL(GetPrinter, q) \
1660 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1661 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1662 } while (0)
1664 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1665 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1666 } while (0)
1668 q0.in.level = 0;
1669 do { TESTGETCALL(GetPrinter, q0) } while (0);
1671 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1672 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1674 /* level 0 printername does not stick */
1675 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1676 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1677 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1680 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1681 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1682 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1685 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1686 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1687 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1691 /* servername can be set but does not stick
1692 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1693 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1697 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1698 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1703 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1704 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1705 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1706 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1707 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1708 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1709 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1710 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1711 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1712 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1714 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1715 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1716 attribute_list[i],
1717 (attribute_list[i] | default_attribute)
1718 ); */
1719 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1720 attribute_list[i],
1721 (attribute_list[i] | default_attribute)
1723 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1724 attribute_list[i],
1725 (attribute_list[i] | default_attribute)
1727 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1728 attribute_list[i],
1729 (attribute_list[i] | default_attribute)
1731 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1732 attribute_list[i],
1733 (attribute_list[i] | default_attribute)
1734 ); */
1735 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1736 attribute_list[i],
1737 (attribute_list[i] | default_attribute)
1739 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1740 attribute_list[i],
1741 (attribute_list[i] | default_attribute)
1743 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1744 attribute_list[i],
1745 (attribute_list[i] | default_attribute)
1747 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1748 attribute_list[i],
1749 (attribute_list[i] | default_attribute)
1750 ); */
1751 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1752 attribute_list[i],
1753 (attribute_list[i] | default_attribute)
1755 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1756 attribute_list[i],
1757 (attribute_list[i] | default_attribute)
1759 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1760 attribute_list[i],
1761 (attribute_list[i] | default_attribute)
1765 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1766 /* level 2 sets do not stick
1767 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1770 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1775 /* priorities need to be between 0 and 99
1776 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1777 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1780 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1781 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1784 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1786 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1787 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1789 /* does not stick
1790 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1791 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1793 /* does not stick
1794 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1795 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1797 /* FIXME: gd also test devmode and secdesc behavior */
1800 /* verify composition of level 1 description field */
1801 const char *description;
1802 const char *tmp;
1804 q0.in.level = 1;
1805 do { TESTGETCALL(GetPrinter, q0) } while (0);
1807 description = talloc_strdup(tctx, q0.out.info->info1.description);
1809 q0.in.level = 2;
1810 do { TESTGETCALL(GetPrinter, q0) } while (0);
1812 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1813 q0.out.info->info2.printername,
1814 q0.out.info->info2.drivername,
1815 q0.out.info->info2.location);
1817 do { STRING_EQUAL(description, tmp, "description")} while (0);
1820 return ret;
1823 static bool test_security_descriptor_equal(struct torture_context *tctx,
1824 const struct security_descriptor *sd1,
1825 const struct security_descriptor *sd2)
1827 if (sd1 == sd2) {
1828 return true;
1831 if (!sd1 || !sd2) {
1832 torture_comment(tctx, "%s\n", __location__);
1833 return false;
1836 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1837 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1839 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1840 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1842 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1843 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1846 return false;
1848 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1849 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1850 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1851 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1852 return false;
1855 return true;
1858 static bool test_sd_set_level(struct torture_context *tctx,
1859 struct dcerpc_binding_handle *b,
1860 struct policy_handle *handle,
1861 uint32_t level,
1862 struct security_descriptor *sd)
1864 struct spoolss_SetPrinterInfoCtr info_ctr;
1865 struct spoolss_DevmodeContainer devmode_ctr;
1866 struct sec_desc_buf secdesc_ctr;
1867 union spoolss_SetPrinterInfo sinfo;
1869 ZERO_STRUCT(devmode_ctr);
1870 ZERO_STRUCT(secdesc_ctr);
1872 switch (level) {
1873 case 2: {
1874 union spoolss_PrinterInfo info;
1875 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1876 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1878 info_ctr.level = 2;
1879 info_ctr.info = sinfo;
1881 break;
1883 case 3: {
1884 struct spoolss_SetPrinterInfo3 info3;
1886 info3.sec_desc_ptr = NULL;
1888 info_ctr.level = 3;
1889 info_ctr.info.info3 = &info3;
1891 break;
1893 default:
1894 return false;
1897 secdesc_ctr.sd = sd;
1899 torture_assert(tctx,
1900 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1902 return true;
1905 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1906 struct dcerpc_binding_handle *b,
1907 struct policy_handle *handle)
1909 union spoolss_PrinterInfo info;
1910 struct security_descriptor *sd1, *sd2;
1911 int i;
1913 /* just compare level 2 and level 3 */
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1917 sd1 = info.info2.secdesc;
1919 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1921 sd2 = info.info3.secdesc;
1923 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1924 "SD level 2 != SD level 3");
1927 /* query level 2, set level 2, query level 2 */
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd1 = info.info2.secdesc;
1933 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1935 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1937 sd2 = info.info2.secdesc;
1938 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1939 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1940 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1943 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1944 "SD level 2 != SD level 2 after SD has been set via level 2");
1947 /* query level 2, set level 3, query level 2 */
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd1 = info.info2.secdesc;
1953 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1955 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1957 sd2 = info.info2.secdesc;
1959 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1960 "SD level 2 != SD level 2 after SD has been set via level 3");
1962 /* set modified sd level 3, query level 2 */
1964 for (i=0; i < 93; i++) {
1965 struct security_ace a;
1966 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1967 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1968 a.flags = 0;
1969 a.size = 0; /* autogenerated */
1970 a.access_mask = 0;
1971 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1972 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1975 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1977 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1978 sd2 = info.info2.secdesc;
1980 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1981 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1982 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1985 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1986 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1989 return true;
1993 * wrapper call that saves original sd, runs tests, and restores sd
1996 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1997 struct dcerpc_binding_handle *b,
1998 struct policy_handle *handle)
2000 union spoolss_PrinterInfo info;
2001 struct security_descriptor *sd;
2002 bool ret = true;
2004 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2006 /* save original sd */
2008 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2009 "failed to get initial security descriptor");
2011 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2013 /* run tests */
2015 ret = test_PrinterInfo_SDs(tctx, b, handle);
2017 /* restore original sd */
2019 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2020 "failed to restore initial security descriptor");
2022 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2023 ret ? "succeeded" : "failed");
2026 return ret;
2029 static bool test_devmode_set_level(struct torture_context *tctx,
2030 struct dcerpc_binding_handle *b,
2031 struct policy_handle *handle,
2032 uint32_t level,
2033 struct spoolss_DeviceMode *devmode)
2035 struct spoolss_SetPrinterInfoCtr info_ctr;
2036 struct spoolss_DevmodeContainer devmode_ctr;
2037 struct sec_desc_buf secdesc_ctr;
2038 union spoolss_SetPrinterInfo sinfo;
2040 ZERO_STRUCT(devmode_ctr);
2041 ZERO_STRUCT(secdesc_ctr);
2043 switch (level) {
2044 case 2: {
2045 union spoolss_PrinterInfo info;
2046 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2047 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2049 info_ctr.level = 2;
2050 info_ctr.info = sinfo;
2052 break;
2054 case 8: {
2055 struct spoolss_SetPrinterInfo8 info8;
2057 info8.devmode_ptr = NULL;
2059 info_ctr.level = 8;
2060 info_ctr.info.info8 = &info8;
2062 break;
2064 default:
2065 return false;
2068 devmode_ctr.devmode = devmode;
2070 torture_assert(tctx,
2071 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2073 return true;
2077 static bool test_devicemode_equal(struct torture_context *tctx,
2078 const struct spoolss_DeviceMode *d1,
2079 const struct spoolss_DeviceMode *d2)
2081 if (d1 == d2) {
2082 return true;
2085 if (!d1 || !d2) {
2086 torture_comment(tctx, "%s\n", __location__);
2087 return false;
2089 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2090 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2091 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2092 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2093 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2094 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2095 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2096 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2097 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2098 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2099 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2100 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2101 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2102 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2103 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2104 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2105 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2106 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2107 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2108 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2109 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2110 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2111 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2112 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2113 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2114 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2115 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2116 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2117 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2118 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2119 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2121 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2122 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2123 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2125 return true;
2128 static bool test_devicemode_full(struct torture_context *tctx,
2129 struct dcerpc_binding_handle *b,
2130 struct policy_handle *handle)
2132 struct spoolss_SetPrinter s;
2133 struct spoolss_GetPrinter q;
2134 struct spoolss_GetPrinter q0;
2135 struct spoolss_SetPrinterInfoCtr info_ctr;
2136 struct spoolss_SetPrinterInfo8 info8;
2137 union spoolss_PrinterInfo info;
2138 struct spoolss_DevmodeContainer devmode_ctr;
2139 struct sec_desc_buf secdesc_ctr;
2140 uint32_t needed;
2141 bool ret = true;
2142 NTSTATUS status;
2144 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2145 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2146 q.in.level = lvl1; \
2147 TESTGETCALL(GetPrinter, q) \
2148 info_ctr.level = lvl1; \
2149 if (lvl1 == 2) {\
2150 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2151 } else if (lvl1 == 8) {\
2152 info_ctr.info.info ## lvl1 = &info8; \
2154 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2155 devmode_ctr.devmode->field1 = value; \
2156 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2157 if (W_ERROR_IS_OK(expected_result)) { \
2158 TESTGETCALL(GetPrinter, q) \
2159 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2160 q.in.level = lvl2; \
2161 TESTGETCALL(GetPrinter, q) \
2162 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2164 } while (0)
2166 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2167 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2168 } while (0)
2170 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2171 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2172 } while (0)
2174 ZERO_STRUCT(devmode_ctr);
2175 ZERO_STRUCT(secdesc_ctr);
2176 ZERO_STRUCT(info8);
2178 s.in.handle = handle;
2179 s.in.command = 0;
2180 s.in.info_ctr = &info_ctr;
2181 s.in.devmode_ctr = &devmode_ctr;
2182 s.in.secdesc_ctr = &secdesc_ctr;
2184 q.in.handle = handle;
2185 q.out.info = &info;
2186 q0 = q;
2188 #if 0
2189 const char *devicename;/* [charset(UTF16)] */
2190 enum spoolss_DeviceModeSpecVersion specversion;
2191 uint16_t driverversion;
2192 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2193 uint32_t fields;
2194 #endif
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2199 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2201 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2202 torture_assert(tctx,
2203 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2204 "failed to set devmode");
2206 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2207 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2209 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2210 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2211 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2212 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2213 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2214 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2215 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2216 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2217 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2218 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2219 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2220 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2221 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2222 #if 0
2223 const char *formname;/* [charset(UTF16)] */
2224 #endif
2225 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2226 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2227 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2228 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2229 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2230 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2231 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2232 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2233 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2234 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2237 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2238 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2240 return ret;
2243 static bool call_OpenPrinterEx(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 const char *name,
2246 struct spoolss_DeviceMode *devmode,
2247 struct policy_handle *handle);
2249 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2250 struct dcerpc_pipe *p,
2251 struct policy_handle *handle,
2252 const char *name)
2254 union spoolss_PrinterInfo info;
2255 struct spoolss_DeviceMode *devmode;
2256 struct spoolss_DeviceMode *devmode2;
2257 struct policy_handle handle_devmode;
2258 struct dcerpc_binding_handle *b = p->binding_handle;
2260 /* simply compare level8 and level2 devmode */
2262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264 devmode = info.info8.devmode;
2266 if (devmode && devmode->size == 0) {
2267 torture_fail(tctx,
2268 "devmode of zero size!");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2273 devmode2 = info.info2.devmode;
2275 if (devmode2 && devmode2->size == 0) {
2276 torture_fail(tctx,
2277 "devmode of zero size!");
2280 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2281 "DM level 8 != DM level 2");
2284 /* set devicemode level 8 and see if it persists */
2286 devmode->copies = 93;
2287 devmode->formname = talloc_strdup(tctx, "Legal");
2289 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2291 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2293 devmode2 = info.info8.devmode;
2295 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2296 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2298 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2300 devmode2 = info.info2.devmode;
2302 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2303 "modified DM level 8 != DM level 2");
2306 /* set devicemode level 2 and see if it persists */
2308 devmode->copies = 39;
2309 devmode->formname = talloc_strdup(tctx, "Executive");
2311 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2313 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2315 devmode2 = info.info8.devmode;
2317 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2318 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2320 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2322 devmode2 = info.info2.devmode;
2324 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2325 "modified DM level 8 != DM level 2");
2328 /* check every single bit in public part of devicemode */
2330 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2331 "failed to set every single devicemode component");
2334 /* change formname upon open and see if it persists in getprinter calls */
2336 devmode->formname = talloc_strdup(tctx, "A4");
2337 devmode->copies = 42;
2339 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2340 "failed to open printer handle");
2342 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2344 devmode2 = info.info8.devmode;
2346 if (strequal(devmode->devicename, devmode2->devicename)) {
2347 torture_warning(tctx, "devicenames are the same\n");
2348 } else {
2349 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2350 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2353 if (strequal(devmode->formname, devmode2->formname)) {
2354 torture_warning(tctx, "formname are the same\n");
2355 } else {
2356 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2357 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2360 if (devmode->copies == devmode2->copies) {
2361 torture_warning(tctx, "copies are the same\n");
2362 } else {
2363 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2364 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2367 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2369 devmode2 = info.info2.devmode;
2371 if (strequal(devmode->devicename, devmode2->devicename)) {
2372 torture_warning(tctx, "devicenames are the same\n");
2373 } else {
2374 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2375 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2378 if (strequal(devmode->formname, devmode2->formname)) {
2379 torture_warning(tctx, "formname is the same\n");
2380 } else {
2381 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2382 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2385 if (devmode->copies == devmode2->copies) {
2386 torture_warning(tctx, "copies are the same\n");
2387 } else {
2388 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2389 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2392 test_ClosePrinter(tctx, b, &handle_devmode);
2394 return true;
2398 * wrapper call that saves original devmode, runs tests, and restores devmode
2401 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2402 struct dcerpc_pipe *p,
2403 struct policy_handle *handle,
2404 const char *name,
2405 struct spoolss_DeviceMode *addprinter_devmode)
2407 union spoolss_PrinterInfo info;
2408 struct spoolss_DeviceMode *devmode;
2409 bool ret = true;
2410 struct dcerpc_binding_handle *b = p->binding_handle;
2412 torture_comment(tctx, "Testing Printer Devicemodes\n");
2414 /* save original devmode */
2416 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2417 "failed to get initial global devicemode");
2419 devmode = info.info8.devmode;
2421 if (devmode && devmode->size == 0) {
2422 torture_fail(tctx,
2423 "devmode of zero size!");
2426 if (addprinter_devmode) {
2427 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2428 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2432 /* run tests */
2434 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2436 /* restore original devmode */
2438 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2439 "failed to restore initial global device mode");
2441 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2442 ret ? "succeeded" : "failed");
2445 return ret;
2448 bool test_ClosePrinter(struct torture_context *tctx,
2449 struct dcerpc_binding_handle *b,
2450 struct policy_handle *handle)
2452 NTSTATUS status;
2453 struct spoolss_ClosePrinter r;
2455 r.in.handle = handle;
2456 r.out.handle = handle;
2458 torture_comment(tctx, "Testing ClosePrinter\n");
2460 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2464 return true;
2467 static bool test_GetForm_args(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 const char *form_name,
2471 uint32_t level,
2472 union spoolss_FormInfo *info_p)
2474 NTSTATUS status;
2475 struct spoolss_GetForm r;
2476 uint32_t needed;
2478 r.in.handle = handle;
2479 r.in.form_name = form_name;
2480 r.in.level = level;
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2485 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2487 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2488 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2492 r.in.buffer = &blob;
2493 r.in.offered = needed;
2494 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 torture_assert(tctx, r.out.info, "No form info returned");
2502 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2504 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2506 if (info_p) {
2507 *info_p = *r.out.info;
2510 return true;
2513 static bool test_GetForm(struct torture_context *tctx,
2514 struct dcerpc_binding_handle *b,
2515 struct policy_handle *handle,
2516 const char *form_name,
2517 uint32_t level)
2519 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2522 static bool test_EnumForms(struct torture_context *tctx,
2523 struct dcerpc_binding_handle *b,
2524 struct policy_handle *handle,
2525 bool print_server,
2526 uint32_t level,
2527 uint32_t *count_p,
2528 union spoolss_FormInfo **info_p)
2530 struct spoolss_EnumForms r;
2531 uint32_t needed;
2532 uint32_t count;
2533 union spoolss_FormInfo *info;
2535 r.in.handle = handle;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2540 r.out.count = &count;
2541 r.out.info = &info;
2543 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2545 torture_assert_ntstatus_ok(tctx,
2546 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2547 "EnumForms failed");
2549 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2550 torture_skip(tctx, "EnumForms level 2 not supported");
2553 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2554 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2557 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2558 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2559 r.in.buffer = &blob;
2560 r.in.offered = needed;
2562 torture_assert_ntstatus_ok(tctx,
2563 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2564 "EnumForms failed");
2566 torture_assert(tctx, info, "No forms returned");
2569 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2571 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2573 if (info_p) {
2574 *info_p = info;
2576 if (count_p) {
2577 *count_p = count;
2580 return true;
2583 static bool test_EnumForms_all(struct torture_context *tctx,
2584 struct dcerpc_binding_handle *b,
2585 struct policy_handle *handle,
2586 bool print_server)
2588 uint32_t levels[] = { 1, 2 };
2589 int i, j;
2591 for (i=0; i<ARRAY_SIZE(levels); i++) {
2593 uint32_t count = 0;
2594 union spoolss_FormInfo *info = NULL;
2596 torture_assert(tctx,
2597 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2598 "failed to enum forms");
2600 for (j = 0; j < count; j++) {
2601 if (!print_server) {
2602 torture_assert(tctx,
2603 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2604 "failed to get form");
2609 return true;
2612 static bool test_EnumForms_find_one(struct torture_context *tctx,
2613 struct dcerpc_binding_handle *b,
2614 struct policy_handle *handle,
2615 bool print_server,
2616 const char *form_name)
2618 union spoolss_FormInfo *info;
2619 uint32_t count;
2620 bool found = false;
2621 int i;
2623 torture_assert(tctx,
2624 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2625 "failed to enumerate forms");
2627 for (i=0; i<count; i++) {
2628 if (strequal(form_name, info[i].info1.form_name)) {
2629 found = true;
2630 break;
2634 return found;
2637 static bool test_DeleteForm(struct torture_context *tctx,
2638 struct dcerpc_binding_handle *b,
2639 struct policy_handle *handle,
2640 const char *form_name,
2641 WERROR expected_result)
2643 struct spoolss_DeleteForm r;
2645 r.in.handle = handle;
2646 r.in.form_name = form_name;
2648 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2650 torture_assert_ntstatus_ok(tctx,
2651 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2652 "DeleteForm failed");
2653 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2654 "DeleteForm gave unexpected result");
2655 if (W_ERROR_IS_OK(r.out.result)) {
2656 torture_assert_ntstatus_ok(tctx,
2657 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2658 "2nd DeleteForm failed");
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2660 "2nd DeleteForm failed");
2663 return true;
2666 static bool test_AddForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 uint32_t level,
2670 union spoolss_AddFormInfo *info,
2671 WERROR expected_result)
2673 struct spoolss_AddForm r;
2674 struct spoolss_AddFormInfoCtr info_ctr;
2676 info_ctr.level = level;
2677 info_ctr.info = *info;
2679 if (level != 1) {
2680 torture_skip(tctx, "only level 1 supported");
2683 r.in.handle = handle;
2684 r.in.info_ctr = &info_ctr;
2686 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2687 r.in.info_ctr->info.info1->form_name, level,
2688 r.in.info_ctr->info.info1->flags);
2690 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2691 "AddForm failed");
2692 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2693 "AddForm gave unexpected result");
2695 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2696 "2nd AddForm failed");
2697 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2698 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2699 "2nd AddForm gave unexpected result");
2700 } else {
2701 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2702 "2nd AddForm gave unexpected result");
2705 return true;
2708 static bool test_SetForm(struct torture_context *tctx,
2709 struct dcerpc_binding_handle *b,
2710 struct policy_handle *handle,
2711 const char *form_name,
2712 uint32_t level,
2713 union spoolss_AddFormInfo *info)
2715 struct spoolss_SetForm r;
2716 struct spoolss_AddFormInfoCtr info_ctr;
2718 info_ctr.level = level;
2719 info_ctr.info = *info;
2721 r.in.handle = handle;
2722 r.in.form_name = form_name;
2723 r.in.info_ctr = &info_ctr;
2725 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2726 form_name, level);
2728 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2729 "SetForm failed");
2731 torture_assert_werr_ok(tctx, r.out.result,
2732 "SetForm failed");
2734 return true;
2737 static bool test_GetForm_winreg(struct torture_context *tctx,
2738 struct dcerpc_binding_handle *b,
2739 struct policy_handle *handle,
2740 const char *key_name,
2741 const char *form_name,
2742 enum winreg_Type *w_type,
2743 uint32_t *w_size,
2744 uint32_t *w_length,
2745 uint8_t **w_data);
2747 static bool test_Forms_args(struct torture_context *tctx,
2748 struct dcerpc_binding_handle *b,
2749 struct policy_handle *handle,
2750 bool print_server,
2751 const char *printer_name,
2752 struct dcerpc_binding_handle *winreg_handle,
2753 struct policy_handle *hive_handle,
2754 const char *form_name,
2755 struct spoolss_AddFormInfo1 *info1,
2756 WERROR expected_add_result,
2757 WERROR expected_delete_result)
2759 union spoolss_FormInfo info;
2760 union spoolss_AddFormInfo add_info;
2762 enum winreg_Type w_type;
2763 uint32_t w_size;
2764 uint32_t w_length;
2765 uint8_t *w_data;
2767 add_info.info1 = info1;
2769 torture_assert(tctx,
2770 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2771 "failed to add form");
2773 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2775 struct spoolss_FormInfo1 i1;
2777 torture_assert(tctx,
2778 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2779 "failed to get form via winreg");
2781 i1.size.width = IVAL(w_data, 0);
2782 i1.size.height = IVAL(w_data, 4);
2783 i1.area.left = IVAL(w_data, 8);
2784 i1.area.top = IVAL(w_data, 12);
2785 i1.area.right = IVAL(w_data, 16);
2786 i1.area.bottom = IVAL(w_data, 20);
2787 /* skip index here */
2788 i1.flags = IVAL(w_data, 28);
2790 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2791 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2792 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2793 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2794 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2795 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2796 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2797 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2798 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2799 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2802 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2803 torture_assert(tctx,
2804 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2805 "failed to get added form");
2807 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2808 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2809 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2810 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2811 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2812 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2813 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2815 if (winreg_handle && hive_handle) {
2817 struct spoolss_FormInfo1 i1;
2819 i1.size.width = IVAL(w_data, 0);
2820 i1.size.height = IVAL(w_data, 4);
2821 i1.area.left = IVAL(w_data, 8);
2822 i1.area.top = IVAL(w_data, 12);
2823 i1.area.right = IVAL(w_data, 16);
2824 i1.area.bottom = IVAL(w_data, 20);
2825 /* skip index here */
2826 i1.flags = IVAL(w_data, 28);
2828 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2829 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2830 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2831 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2832 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2833 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2834 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2837 add_info.info1->size.width = 1234;
2839 torture_assert(tctx,
2840 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2841 "failed to set form");
2842 torture_assert(tctx,
2843 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2844 "failed to get setted form");
2846 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2849 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2850 torture_assert(tctx,
2851 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2852 "Newly added form not found in enum call");
2855 torture_assert(tctx,
2856 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2857 "failed to delete form");
2859 return true;
2862 static bool test_Forms(struct torture_context *tctx,
2863 struct dcerpc_binding_handle *b,
2864 struct policy_handle *handle,
2865 bool print_server,
2866 const char *printer_name,
2867 struct dcerpc_binding_handle *winreg_handle,
2868 struct policy_handle *hive_handle)
2870 const struct spoolss_FormSize size = {
2871 .width = 50,
2872 .height = 25
2874 const struct spoolss_FormArea area = {
2875 .left = 5,
2876 .top = 10,
2877 .right = 45,
2878 .bottom = 15
2880 int i;
2882 struct {
2883 struct spoolss_AddFormInfo1 info1;
2884 WERROR expected_add_result;
2885 WERROR expected_delete_result;
2886 } forms[] = {
2888 .info1 = {
2889 .flags = SPOOLSS_FORM_USER,
2890 .form_name = "testform_user",
2891 .size = size,
2892 .area = area,
2894 .expected_add_result = WERR_OK,
2895 .expected_delete_result = WERR_OK
2898 weird, we can add a builtin form but we can never remove it
2899 again - gd
2902 .info1 = {
2903 .flags = SPOOLSS_FORM_BUILTIN,
2904 .form_name = "testform_builtin",
2905 .size = size,
2906 .area = area,
2908 .expected_add_result = WERR_OK,
2909 .expected_delete_result = WERR_INVALID_PARAM,
2913 .info1 = {
2914 .flags = SPOOLSS_FORM_PRINTER,
2915 .form_name = "testform_printer",
2916 .size = size,
2917 .area = area,
2919 .expected_add_result = WERR_OK,
2920 .expected_delete_result = WERR_OK
2923 .info1 = {
2924 .flags = SPOOLSS_FORM_USER,
2925 .form_name = "Letter",
2926 .size = size,
2927 .area = area,
2929 .expected_add_result = WERR_FILE_EXISTS,
2930 .expected_delete_result = WERR_INVALID_PARAM
2933 .info1 = {
2934 .flags = SPOOLSS_FORM_BUILTIN,
2935 .form_name = "Letter",
2936 .size = size,
2937 .area = area,
2939 .expected_add_result = WERR_FILE_EXISTS,
2940 .expected_delete_result = WERR_INVALID_PARAM
2943 .info1 = {
2944 .flags = SPOOLSS_FORM_PRINTER,
2945 .form_name = "Letter",
2946 .size = size,
2947 .area = area,
2949 .expected_add_result = WERR_FILE_EXISTS,
2950 .expected_delete_result = WERR_INVALID_PARAM
2953 .info1 = {
2954 .flags = 12345,
2955 .form_name = "invalid_flags",
2956 .size = size,
2957 .area = area,
2959 .expected_add_result = WERR_INVALID_PARAM,
2960 .expected_delete_result = WERR_INVALID_FORM_NAME
2965 for (i=0; i < ARRAY_SIZE(forms); i++) {
2966 torture_assert(tctx,
2967 test_Forms_args(tctx, b, handle, print_server, printer_name,
2968 winreg_handle, hive_handle,
2969 forms[i].info1.form_name,
2970 &forms[i].info1,
2971 forms[i].expected_add_result,
2972 forms[i].expected_delete_result),
2973 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2976 return true;
2979 static bool test_EnumPorts_old(struct torture_context *tctx,
2980 void *private_data)
2982 struct test_spoolss_context *ctx =
2983 talloc_get_type_abort(private_data, struct test_spoolss_context);
2985 NTSTATUS status;
2986 struct spoolss_EnumPorts r;
2987 uint32_t needed;
2988 uint32_t count;
2989 union spoolss_PortInfo *info;
2990 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2991 struct dcerpc_binding_handle *b = p->binding_handle;
2993 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2994 dcerpc_server_name(p));
2995 r.in.level = 2;
2996 r.in.buffer = NULL;
2997 r.in.offered = 0;
2998 r.out.needed = &needed;
2999 r.out.count = &count;
3000 r.out.info = &info;
3002 torture_comment(tctx, "Testing EnumPorts\n");
3004 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3006 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3008 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3009 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3010 r.in.buffer = &blob;
3011 r.in.offered = needed;
3013 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3014 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3015 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3017 torture_assert(tctx, info, "No ports returned");
3020 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3022 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3024 return true;
3027 static bool test_AddPort(struct torture_context *tctx,
3028 void *private_data)
3030 struct test_spoolss_context *ctx =
3031 talloc_get_type_abort(private_data, struct test_spoolss_context);
3033 NTSTATUS status;
3034 struct spoolss_AddPort r;
3035 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3036 struct dcerpc_binding_handle *b = p->binding_handle;
3038 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3039 dcerpc_server_name(p));
3040 r.in.unknown = 0;
3041 r.in.monitor_name = "foo";
3043 torture_comment(tctx, "Testing AddPort\n");
3045 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3047 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3049 /* win2k3 returns WERR_NOT_SUPPORTED */
3051 #if 0
3053 if (!W_ERROR_IS_OK(r.out.result)) {
3054 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3055 return false;
3058 #endif
3060 return true;
3063 static bool test_GetJob_args(struct torture_context *tctx,
3064 struct dcerpc_binding_handle *b,
3065 struct policy_handle *handle,
3066 uint32_t job_id,
3067 uint32_t level,
3068 union spoolss_JobInfo *info_p)
3070 NTSTATUS status;
3071 struct spoolss_GetJob r;
3072 union spoolss_JobInfo info;
3073 uint32_t needed;
3075 r.in.handle = handle;
3076 r.in.job_id = job_id;
3077 r.in.level = level;
3078 r.in.buffer = NULL;
3079 r.in.offered = 0;
3080 r.out.needed = &needed;
3081 r.out.info = &info;
3083 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3085 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3086 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3087 if (level == 0) {
3088 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3091 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3092 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3093 r.in.buffer = &blob;
3094 r.in.offered = needed;
3096 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3097 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3100 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3101 torture_assert(tctx, r.out.info, "No job info returned");
3103 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3105 if (info_p) {
3106 *info_p = *r.out.info;
3109 return true;
3112 static bool test_GetJob(struct torture_context *tctx,
3113 struct dcerpc_binding_handle *b,
3114 struct policy_handle *handle,
3115 uint32_t job_id)
3117 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3118 uint32_t i;
3120 for (i=0; i < ARRAY_SIZE(levels); i++) {
3121 torture_assert(tctx,
3122 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3123 "GetJob failed");
3126 return true;
3129 static bool test_SetJob(struct torture_context *tctx,
3130 struct dcerpc_binding_handle *b,
3131 struct policy_handle *handle,
3132 uint32_t job_id,
3133 struct spoolss_JobInfoContainer *ctr,
3134 enum spoolss_JobControl command)
3136 NTSTATUS status;
3137 struct spoolss_SetJob r;
3139 r.in.handle = handle;
3140 r.in.job_id = job_id;
3141 r.in.ctr = ctr;
3142 r.in.command = command;
3144 switch (command) {
3145 case SPOOLSS_JOB_CONTROL_PAUSE:
3146 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3147 break;
3148 case SPOOLSS_JOB_CONTROL_RESUME:
3149 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3150 break;
3151 case SPOOLSS_JOB_CONTROL_CANCEL:
3152 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3153 break;
3154 case SPOOLSS_JOB_CONTROL_RESTART:
3155 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3156 break;
3157 case SPOOLSS_JOB_CONTROL_DELETE:
3158 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3159 break;
3160 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3161 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3162 break;
3163 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3164 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3165 break;
3166 case SPOOLSS_JOB_CONTROL_RETAIN:
3167 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3168 break;
3169 case SPOOLSS_JOB_CONTROL_RELEASE:
3170 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3171 break;
3172 default:
3173 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3174 break;
3177 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3178 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3179 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3181 return true;
3184 static bool test_AddJob(struct torture_context *tctx,
3185 struct dcerpc_binding_handle *b,
3186 struct policy_handle *handle)
3188 NTSTATUS status;
3189 struct spoolss_AddJob r;
3190 uint32_t needed;
3192 r.in.level = 0;
3193 r.in.handle = handle;
3194 r.in.offered = 0;
3195 r.out.needed = &needed;
3196 r.in.buffer = r.out.buffer = NULL;
3198 torture_comment(tctx, "Testing AddJob\n");
3200 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3201 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3203 r.in.level = 1;
3205 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3206 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3208 return true;
3212 static bool test_EnumJobs_args(struct torture_context *tctx,
3213 struct dcerpc_binding_handle *b,
3214 struct policy_handle *handle,
3215 uint32_t level,
3216 uint32_t *count_p,
3217 union spoolss_JobInfo **info_p)
3219 NTSTATUS status;
3220 struct spoolss_EnumJobs r;
3221 uint32_t needed;
3222 uint32_t count;
3223 union spoolss_JobInfo *info;
3225 r.in.handle = handle;
3226 r.in.firstjob = 0;
3227 r.in.numjobs = 0xffffffff;
3228 r.in.level = level;
3229 r.in.buffer = NULL;
3230 r.in.offered = 0;
3231 r.out.needed = &needed;
3232 r.out.count = &count;
3233 r.out.info = &info;
3235 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3237 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3239 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3241 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3242 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3243 r.in.buffer = &blob;
3244 r.in.offered = needed;
3246 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3248 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3249 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3250 torture_assert(tctx, info, "No jobs returned");
3252 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3254 } else {
3255 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3258 if (count_p) {
3259 *count_p = count;
3261 if (info_p) {
3262 *info_p = info;
3265 return true;
3268 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3269 struct dcerpc_binding_handle *b,
3270 struct policy_handle *handle,
3271 const char *document_name,
3272 uint32_t *job_id)
3274 NTSTATUS status;
3275 struct spoolss_StartDocPrinter s;
3276 struct spoolss_DocumentInfo1 info1;
3277 struct spoolss_StartPagePrinter sp;
3278 struct spoolss_WritePrinter w;
3279 struct spoolss_EndPagePrinter ep;
3280 struct spoolss_EndDocPrinter e;
3281 int i;
3282 uint32_t num_written;
3284 torture_comment(tctx, "Testing StartDocPrinter\n");
3286 s.in.handle = handle;
3287 s.in.level = 1;
3288 s.in.info.info1 = &info1;
3289 s.out.job_id = job_id;
3290 info1.document_name = document_name;
3291 info1.output_file = NULL;
3292 info1.datatype = "RAW";
3294 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3295 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3296 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3298 for (i=1; i < 4; i++) {
3299 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3301 sp.in.handle = handle;
3303 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3304 torture_assert_ntstatus_ok(tctx, status,
3305 "dcerpc_spoolss_StartPagePrinter failed");
3306 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3308 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3310 w.in.handle = handle;
3311 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3312 w.out.num_written = &num_written;
3314 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3315 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3316 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3318 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3320 ep.in.handle = handle;
3322 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3323 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3324 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3327 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3329 e.in.handle = handle;
3331 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3332 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3333 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3335 return true;
3338 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3339 struct dcerpc_binding_handle *b,
3340 struct policy_handle *handle,
3341 uint32_t num_jobs,
3342 uint32_t *job_ids)
3344 uint32_t count;
3345 union spoolss_JobInfo *info = NULL;
3346 int i;
3348 torture_assert(tctx,
3349 test_AddJob(tctx, b, handle),
3350 "AddJob failed");
3352 torture_assert(tctx,
3353 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3354 "EnumJobs level 1 failed");
3356 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3358 for (i=0; i < num_jobs; i++) {
3359 union spoolss_JobInfo ginfo;
3360 const char *document_name;
3361 const char *new_document_name = "any_other_docname";
3362 struct spoolss_JobInfoContainer ctr;
3363 struct spoolss_SetJobInfo1 info1;
3365 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3367 torture_assert(tctx,
3368 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3369 "failed to call test_GetJob");
3371 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3373 document_name = ginfo.info1.document_name;
3375 info1.job_id = ginfo.info1.job_id;
3376 info1.printer_name = ginfo.info1.printer_name;
3377 info1.server_name = ginfo.info1.server_name;
3378 info1.user_name = ginfo.info1.user_name;
3379 info1.document_name = new_document_name;
3380 info1.data_type = ginfo.info1.data_type;
3381 info1.text_status = ginfo.info1.text_status;
3382 info1.status = ginfo.info1.status;
3383 info1.priority = ginfo.info1.priority;
3384 info1.position = ginfo.info1.position;
3385 info1.total_pages = ginfo.info1.total_pages;
3386 info1.pages_printed = ginfo.info1.pages_printed;
3387 info1.submitted = ginfo.info1.submitted;
3389 ctr.level = 1;
3390 ctr.info.info1 = &info1;
3392 torture_assert(tctx,
3393 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3394 "failed to call test_SetJob level 1");
3396 torture_assert(tctx,
3397 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3398 "failed to call test_GetJob");
3400 if (strequal(ginfo.info1.document_name, document_name)) {
3401 torture_warning(tctx,
3402 "document_name did *NOT* change from '%s' to '%s'\n",
3403 document_name, new_document_name);
3407 for (i=0; i < num_jobs; i++) {
3408 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3409 torture_warning(tctx, "failed to pause printjob\n");
3411 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3412 torture_warning(tctx, "failed to resume printjob\n");
3416 return true;
3419 static bool test_DoPrintTest(struct torture_context *tctx,
3420 struct dcerpc_binding_handle *b,
3421 struct policy_handle *handle)
3423 bool ret = true;
3424 uint32_t num_jobs = 8;
3425 uint32_t *job_ids;
3426 int i;
3428 torture_comment(tctx, "Testing real print operations\n");
3430 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3432 for (i=0; i < num_jobs; i++) {
3433 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3436 for (i=0; i < num_jobs; i++) {
3437 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3440 if (ret == true) {
3441 torture_comment(tctx, "real print operations test succeeded\n\n");
3444 return ret;
3447 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3448 struct dcerpc_binding_handle *b,
3449 struct policy_handle *handle)
3451 bool ret = true;
3452 uint32_t num_jobs = 8;
3453 uint32_t *job_ids;
3454 int i;
3455 torture_comment(tctx, "Testing real print operations (extended)\n");
3457 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3459 for (i=0; i < num_jobs; i++) {
3460 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3463 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3465 for (i=0; i < num_jobs; i++) {
3466 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3469 if (ret == true) {
3470 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3473 return ret;
3476 static bool test_PausePrinter(struct torture_context *tctx,
3477 struct dcerpc_binding_handle *b,
3478 struct policy_handle *handle)
3480 NTSTATUS status;
3481 struct spoolss_SetPrinter r;
3482 struct spoolss_SetPrinterInfoCtr info_ctr;
3483 struct spoolss_DevmodeContainer devmode_ctr;
3484 struct sec_desc_buf secdesc_ctr;
3486 info_ctr.level = 0;
3487 info_ctr.info.info0 = NULL;
3489 ZERO_STRUCT(devmode_ctr);
3490 ZERO_STRUCT(secdesc_ctr);
3492 r.in.handle = handle;
3493 r.in.info_ctr = &info_ctr;
3494 r.in.devmode_ctr = &devmode_ctr;
3495 r.in.secdesc_ctr = &secdesc_ctr;
3496 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3498 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3500 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3502 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3504 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3506 return true;
3509 static bool test_ResumePrinter(struct torture_context *tctx,
3510 struct dcerpc_binding_handle *b,
3511 struct policy_handle *handle)
3513 NTSTATUS status;
3514 struct spoolss_SetPrinter r;
3515 struct spoolss_SetPrinterInfoCtr info_ctr;
3516 struct spoolss_DevmodeContainer devmode_ctr;
3517 struct sec_desc_buf secdesc_ctr;
3519 info_ctr.level = 0;
3520 info_ctr.info.info0 = NULL;
3522 ZERO_STRUCT(devmode_ctr);
3523 ZERO_STRUCT(secdesc_ctr);
3525 r.in.handle = handle;
3526 r.in.info_ctr = &info_ctr;
3527 r.in.devmode_ctr = &devmode_ctr;
3528 r.in.secdesc_ctr = &secdesc_ctr;
3529 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3531 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3533 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3535 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3537 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3539 return true;
3542 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3543 struct dcerpc_binding_handle *b,
3544 struct policy_handle *handle,
3545 const char *value_name,
3546 enum winreg_Type *expected_type,
3547 enum winreg_Type *type_p,
3548 uint8_t **data_p,
3549 uint32_t *needed_p)
3551 NTSTATUS status;
3552 struct spoolss_GetPrinterData r;
3553 uint32_t needed;
3554 enum winreg_Type type;
3555 union spoolss_PrinterData data;
3557 r.in.handle = handle;
3558 r.in.value_name = value_name;
3559 r.in.offered = 0;
3560 r.out.needed = &needed;
3561 r.out.type = &type;
3562 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3564 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3566 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3567 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3569 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3570 if (expected_type) {
3571 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3573 r.in.offered = needed;
3574 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3575 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3576 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3579 torture_assert_werr_ok(tctx, r.out.result,
3580 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3582 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3584 if (type_p) {
3585 *type_p = type;
3588 if (data_p) {
3589 *data_p = r.out.data;
3592 if (needed_p) {
3593 *needed_p = needed;
3596 return true;
3599 static bool test_GetPrinterData(struct torture_context *tctx,
3600 struct dcerpc_binding_handle *b,
3601 struct policy_handle *handle,
3602 const char *value_name,
3603 enum winreg_Type *type_p,
3604 uint8_t **data_p,
3605 uint32_t *needed_p)
3607 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3608 NULL, type_p, data_p, needed_p);
3611 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3612 struct dcerpc_pipe *p,
3613 struct policy_handle *handle,
3614 const char *key_name,
3615 const char *value_name,
3616 enum winreg_Type *expected_type,
3617 enum winreg_Type *type_p,
3618 uint8_t **data_p,
3619 uint32_t *needed_p)
3621 NTSTATUS status;
3622 struct spoolss_GetPrinterDataEx r;
3623 enum winreg_Type type;
3624 uint32_t needed;
3625 union spoolss_PrinterData data;
3626 struct dcerpc_binding_handle *b = p->binding_handle;
3628 r.in.handle = handle;
3629 r.in.key_name = key_name;
3630 r.in.value_name = value_name;
3631 r.in.offered = 0;
3632 r.out.type = &type;
3633 r.out.needed = &needed;
3634 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3636 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3637 r.in.key_name, r.in.value_name);
3639 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3642 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3644 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3647 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3648 if (expected_type) {
3649 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3651 r.in.offered = needed;
3652 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3653 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3654 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3657 torture_assert_werr_ok(tctx, r.out.result,
3658 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3660 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3662 if (type_p) {
3663 *type_p = type;
3666 if (data_p) {
3667 *data_p = r.out.data;
3670 if (needed_p) {
3671 *needed_p = needed;
3674 return true;
3677 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3678 struct dcerpc_pipe *p,
3679 struct policy_handle *handle,
3680 const char *key_name,
3681 const char *value_name,
3682 enum winreg_Type *type_p,
3683 uint8_t **data_p,
3684 uint32_t *needed_p)
3686 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3687 NULL, type_p, data_p, needed_p);
3690 static bool test_get_environment(struct torture_context *tctx,
3691 struct dcerpc_binding_handle *b,
3692 struct policy_handle *handle,
3693 const char **architecture)
3695 DATA_BLOB blob;
3696 enum winreg_Type type;
3697 uint8_t *data;
3698 uint32_t needed;
3700 torture_assert(tctx,
3701 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3702 "failed to get Architecture");
3704 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3706 blob = data_blob_const(data, needed);
3707 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3709 return true;
3712 static bool test_GetPrinterData_list(struct torture_context *tctx,
3713 void *private_data)
3715 struct test_spoolss_context *ctx =
3716 talloc_get_type_abort(private_data, struct test_spoolss_context);
3717 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3718 struct dcerpc_binding_handle *b = p->binding_handle;
3719 const char *list[] = {
3720 "W3SvcInstalled",
3721 "BeepEnabled",
3722 "EventLog",
3723 /* "NetPopup", not on w2k8 */
3724 /* "NetPopupToComputer", not on w2k8 */
3725 "MajorVersion",
3726 "MinorVersion",
3727 "DefaultSpoolDirectory",
3728 "Architecture",
3729 "DsPresent",
3730 "OSVersion",
3731 /* "OSVersionEx", not on s3 */
3732 "DNSMachineName"
3734 int i;
3736 for (i=0; i < ARRAY_SIZE(list); i++) {
3737 enum winreg_Type type, type_ex;
3738 uint8_t *data, *data_ex;
3739 uint32_t needed, needed_ex;
3741 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3742 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3743 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3744 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3745 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3746 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3747 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3750 return true;
3753 static bool test_EnumPrinterData(struct torture_context *tctx,
3754 struct dcerpc_pipe *p,
3755 struct policy_handle *handle,
3756 uint32_t enum_index,
3757 uint32_t value_offered,
3758 uint32_t data_offered,
3759 enum winreg_Type *type_p,
3760 uint32_t *value_needed_p,
3761 uint32_t *data_needed_p,
3762 const char **value_name_p,
3763 uint8_t **data_p,
3764 WERROR *result_p)
3766 struct spoolss_EnumPrinterData r;
3767 uint32_t data_needed;
3768 uint32_t value_needed;
3769 enum winreg_Type type;
3770 struct dcerpc_binding_handle *b = p->binding_handle;
3772 r.in.handle = handle;
3773 r.in.enum_index = enum_index;
3774 r.in.value_offered = value_offered;
3775 r.in.data_offered = data_offered;
3776 r.out.data_needed = &data_needed;
3777 r.out.value_needed = &value_needed;
3778 r.out.type = &type;
3779 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3780 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3782 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3784 torture_assert_ntstatus_ok(tctx,
3785 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3786 "EnumPrinterData failed");
3788 if (type_p) {
3789 *type_p = type;
3791 if (value_needed_p) {
3792 *value_needed_p = value_needed;
3794 if (data_needed_p) {
3795 *data_needed_p = data_needed;
3797 if (value_name_p) {
3798 *value_name_p = r.out.value_name;
3800 if (data_p) {
3801 *data_p = r.out.data;
3803 if (result_p) {
3804 *result_p = r.out.result;
3807 return true;
3811 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3812 struct dcerpc_pipe *p,
3813 struct policy_handle *handle)
3815 uint32_t enum_index = 0;
3816 enum winreg_Type type;
3817 uint32_t value_needed;
3818 uint32_t data_needed;
3819 uint8_t *data;
3820 const char *value_name;
3821 WERROR result;
3823 torture_comment(tctx, "Testing EnumPrinterData\n");
3825 do {
3826 torture_assert(tctx,
3827 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3828 &type, &value_needed, &data_needed,
3829 &value_name, &data, &result),
3830 "EnumPrinterData failed");
3832 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3833 break;
3836 torture_assert(tctx,
3837 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3838 &type, &value_needed, &data_needed,
3839 &value_name, &data, &result),
3840 "EnumPrinterData failed");
3842 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3843 break;
3846 enum_index++;
3848 } while (W_ERROR_IS_OK(result));
3850 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3852 return true;
3855 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3856 struct dcerpc_binding_handle *b,
3857 struct policy_handle *handle,
3858 const char *key_name,
3859 uint32_t *count_p,
3860 struct spoolss_PrinterEnumValues **info_p)
3862 struct spoolss_EnumPrinterDataEx r;
3863 struct spoolss_PrinterEnumValues *info;
3864 uint32_t needed;
3865 uint32_t count;
3867 r.in.handle = handle;
3868 r.in.key_name = key_name;
3869 r.in.offered = 0;
3870 r.out.needed = &needed;
3871 r.out.count = &count;
3872 r.out.info = &info;
3874 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3876 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3877 "EnumPrinterDataEx failed");
3878 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3879 r.in.offered = needed;
3880 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3881 "EnumPrinterDataEx failed");
3884 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3886 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3888 if (count_p) {
3889 *count_p = count;
3891 if (info_p) {
3892 *info_p = info;
3895 return true;
3898 static bool test_SetPrinterData(struct torture_context *tctx,
3899 struct dcerpc_binding_handle *b,
3900 struct policy_handle *handle,
3901 const char *value_name,
3902 enum winreg_Type type,
3903 uint8_t *data,
3904 uint32_t offered);
3905 static bool test_DeletePrinterData(struct torture_context *tctx,
3906 struct dcerpc_binding_handle *b,
3907 struct policy_handle *handle,
3908 const char *value_name);
3910 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3911 struct dcerpc_pipe *p,
3912 struct policy_handle *handle)
3914 uint32_t count;
3915 struct spoolss_PrinterEnumValues *info;
3916 int i;
3917 uint32_t value_needed, data_needed;
3918 uint32_t value_offered, data_offered;
3919 WERROR result;
3920 struct dcerpc_binding_handle *b = p->binding_handle;
3922 enum winreg_Type type;
3923 DATA_BLOB blob;
3925 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3927 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3928 type = REG_SZ;
3930 torture_assert(tctx,
3931 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3932 "SetPrinterData failed");
3934 blob = data_blob_string_const("torture_data2");
3936 torture_assert(tctx,
3937 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3938 "SetPrinterData failed");
3940 blob = data_blob_talloc(tctx, NULL, 4);
3941 SIVAL(blob.data, 0, 0x11223344);
3943 torture_assert(tctx,
3944 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3945 "SetPrinterData failed");
3947 torture_assert(tctx,
3948 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3949 "failed to call EnumPrinterDataEx");
3951 /* get the max sizes for value and data */
3953 torture_assert(tctx,
3954 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3955 NULL, &value_needed, &data_needed,
3956 NULL, NULL, &result),
3957 "EnumPrinterData failed");
3958 torture_assert_werr_ok(tctx, result, "unexpected result");
3960 /* check if the reply from the EnumPrinterData really matches max values */
3962 for (i=0; i < count; i++) {
3963 if (info[i].value_name_len > value_needed) {
3964 torture_fail(tctx,
3965 talloc_asprintf(tctx,
3966 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3967 info[i].value_name_len, value_needed));
3969 if (info[i].data_length > data_needed) {
3970 torture_fail(tctx,
3971 talloc_asprintf(tctx,
3972 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3973 info[i].data_length, data_needed));
3977 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3978 * sort or not sort the replies by value name, we should be able to do
3979 * the following entry comparison */
3981 data_offered = data_needed;
3982 value_offered = value_needed;
3984 for (i=0; i < count; i++) {
3986 const char *value_name;
3987 uint8_t *data;
3989 torture_assert(tctx,
3990 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3991 &type, &value_needed, &data_needed,
3992 &value_name, &data, &result),
3993 "EnumPrinterData failed");
3995 if (i -1 == count) {
3996 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3997 "unexpected result");
3998 break;
3999 } else {
4000 torture_assert_werr_ok(tctx, result, "unexpected result");
4003 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4004 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4005 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4006 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4007 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4010 torture_assert(tctx,
4011 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4012 "DeletePrinterData failed");
4013 torture_assert(tctx,
4014 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4015 "DeletePrinterData failed");
4016 torture_assert(tctx,
4017 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4018 "DeletePrinterData failed");
4020 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4022 return true;
4025 static bool test_DeletePrinterData(struct torture_context *tctx,
4026 struct dcerpc_binding_handle *b,
4027 struct policy_handle *handle,
4028 const char *value_name)
4030 NTSTATUS status;
4031 struct spoolss_DeletePrinterData r;
4033 r.in.handle = handle;
4034 r.in.value_name = value_name;
4036 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4037 r.in.value_name);
4039 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4041 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4042 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4044 return true;
4047 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4048 struct dcerpc_binding_handle *b,
4049 struct policy_handle *handle,
4050 const char *key_name,
4051 const char *value_name)
4053 struct spoolss_DeletePrinterDataEx r;
4055 r.in.handle = handle;
4056 r.in.key_name = key_name;
4057 r.in.value_name = value_name;
4059 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4060 r.in.key_name, r.in.value_name);
4062 torture_assert_ntstatus_ok(tctx,
4063 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4064 "DeletePrinterDataEx failed");
4065 torture_assert_werr_ok(tctx, r.out.result,
4066 "DeletePrinterDataEx failed");
4068 return true;
4071 static bool test_DeletePrinterKey(struct torture_context *tctx,
4072 struct dcerpc_binding_handle *b,
4073 struct policy_handle *handle,
4074 const char *key_name)
4076 struct spoolss_DeletePrinterKey r;
4078 r.in.handle = handle;
4079 r.in.key_name = key_name;
4081 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4083 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4084 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4085 return true;
4088 torture_assert_ntstatus_ok(tctx,
4089 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4090 "DeletePrinterKey failed");
4091 torture_assert_werr_ok(tctx, r.out.result,
4092 "DeletePrinterKey failed");
4094 return true;
4097 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4098 struct dcerpc_binding_handle *b,
4099 struct policy_handle *handle)
4101 struct winreg_OpenHKLM r;
4103 r.in.system_name = NULL;
4104 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4105 r.out.handle = handle;
4107 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4109 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4110 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4112 return true;
4115 static void init_winreg_String(struct winreg_String *name, const char *s)
4117 name->name = s;
4118 if (s) {
4119 name->name_len = 2 * (strlen_m(s) + 1);
4120 name->name_size = name->name_len;
4121 } else {
4122 name->name_len = 0;
4123 name->name_size = 0;
4127 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4128 struct dcerpc_binding_handle *b,
4129 struct policy_handle *hive_handle,
4130 const char *keyname,
4131 uint32_t options,
4132 struct policy_handle *key_handle)
4134 struct winreg_OpenKey r;
4136 r.in.parent_handle = hive_handle;
4137 init_winreg_String(&r.in.keyname, keyname);
4138 r.in.options = options;
4139 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4140 r.out.handle = key_handle;
4142 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4144 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4145 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4147 return true;
4150 static bool test_winreg_OpenKey(struct torture_context *tctx,
4151 struct dcerpc_binding_handle *b,
4152 struct policy_handle *hive_handle,
4153 const char *keyname,
4154 struct policy_handle *key_handle)
4156 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4157 REG_OPTION_NON_VOLATILE, key_handle);
4160 static bool test_winreg_CloseKey(struct torture_context *tctx,
4161 struct dcerpc_binding_handle *b,
4162 struct policy_handle *handle)
4164 struct winreg_CloseKey r;
4166 r.in.handle = handle;
4167 r.out.handle = handle;
4169 torture_comment(tctx, "Testing winreg_CloseKey\n");
4171 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4172 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4174 return true;
4177 bool test_winreg_QueryValue(struct torture_context *tctx,
4178 struct dcerpc_binding_handle *b,
4179 struct policy_handle *handle,
4180 const char *value_name,
4181 enum winreg_Type *type_p,
4182 uint32_t *data_size_p,
4183 uint32_t *data_length_p,
4184 uint8_t **data_p)
4186 struct winreg_QueryValue r;
4187 enum winreg_Type type = REG_NONE;
4188 uint32_t data_size = 0;
4189 uint32_t data_length = 0;
4190 struct winreg_String valuename;
4191 uint8_t *data = NULL;
4193 init_winreg_String(&valuename, value_name);
4195 data = talloc_zero_array(tctx, uint8_t, 0);
4197 r.in.handle = handle;
4198 r.in.value_name = &valuename;
4199 r.in.type = &type;
4200 r.in.data_size = &data_size;
4201 r.in.data_length = &data_length;
4202 r.in.data = data;
4203 r.out.type = &type;
4204 r.out.data = data;
4205 r.out.data_size = &data_size;
4206 r.out.data_length = &data_length;
4208 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4210 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4211 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4212 *r.in.data_size = *r.out.data_size;
4213 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4214 r.in.data = data;
4215 r.out.data = data;
4216 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4218 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4220 if (type_p) {
4221 *type_p = *r.out.type;
4223 if (data_size_p) {
4224 *data_size_p = *r.out.data_size;
4226 if (data_length_p) {
4227 *data_length_p = *r.out.data_length;
4229 if (data_p) {
4230 *data_p = r.out.data;
4233 return true;
4236 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4237 struct dcerpc_binding_handle *b,
4238 struct policy_handle *handle,
4239 const char *printer_name,
4240 const char *key_name,
4241 const char *value_name,
4242 enum winreg_Type *w_type,
4243 uint32_t *w_size,
4244 uint32_t *w_length,
4245 uint8_t **w_data)
4247 const char *printer_key;
4248 struct policy_handle key_handle;
4250 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4251 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4253 torture_assert(tctx,
4254 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4256 torture_assert(tctx,
4257 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4259 torture_assert(tctx,
4260 test_winreg_CloseKey(tctx, b, &key_handle), "");
4262 return true;
4265 static bool test_GetForm_winreg(struct torture_context *tctx,
4266 struct dcerpc_binding_handle *b,
4267 struct policy_handle *handle,
4268 const char *key_name,
4269 const char *form_name,
4270 enum winreg_Type *w_type,
4271 uint32_t *w_size,
4272 uint32_t *w_length,
4273 uint8_t **w_data)
4275 struct policy_handle key_handle;
4277 torture_assert(tctx,
4278 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4280 torture_assert(tctx,
4281 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4283 torture_assert(tctx,
4284 test_winreg_CloseKey(tctx, b, &key_handle), "");
4286 return true;
4289 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4290 struct dcerpc_binding_handle *b,
4291 struct policy_handle *handle,
4292 const char *symlink_keyname,
4293 const char *symlink_destination)
4295 /* check if the first key is a symlink to the second key */
4297 enum winreg_Type w_type;
4298 uint32_t w_size;
4299 uint32_t w_length;
4300 uint8_t *w_data;
4301 struct policy_handle key_handle;
4302 DATA_BLOB blob;
4303 const char *str;
4305 if (torture_setting_bool(tctx, "samba3", false)) {
4306 torture_skip(tctx, "skip winreg symlink test against samba");
4309 torture_assert(tctx,
4310 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4311 "failed to open key link");
4313 torture_assert(tctx,
4314 test_winreg_QueryValue(tctx, b, &key_handle,
4315 "SymbolicLinkValue",
4316 &w_type, &w_size, &w_length, &w_data),
4317 "failed to query for 'SymbolicLinkValue' attribute");
4319 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4321 blob = data_blob(w_data, w_size);
4322 str = reg_val_data_string(tctx, REG_SZ, blob);
4324 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4326 torture_assert(tctx,
4327 test_winreg_CloseKey(tctx, b, &key_handle),
4328 "failed to close key link");
4330 return true;
4333 static const char *strip_unc(const char *unc)
4335 char *name;
4337 if (!unc) {
4338 return NULL;
4341 if (unc[0] == '\\' && unc[1] == '\\') {
4342 unc +=2;
4345 name = strchr(unc, '\\');
4346 if (name) {
4347 return name+1;
4350 return unc;
4353 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4354 struct dcerpc_binding_handle *b,
4355 struct policy_handle *handle,
4356 const char *printer_name,
4357 struct dcerpc_binding_handle *winreg_handle,
4358 struct policy_handle *hive_handle)
4360 union spoolss_PrinterInfo info;
4361 const char *keys[] = {
4362 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4363 TOP_LEVEL_PRINT_PRINTERS_KEY
4365 int i;
4366 const char *printername, *sharename;
4368 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4370 torture_assert(tctx,
4371 test_GetPrinter_level(tctx, b, handle, 2, &info),
4372 "failed to get printer info level 2");
4374 printername = strip_unc(info.info2.printername);
4375 sharename = strip_unc(info.info2.sharename);
4377 #define test_sz(wname, iname) \
4378 do {\
4379 DATA_BLOB blob;\
4380 const char *str;\
4381 enum winreg_Type w_type;\
4382 uint32_t w_size;\
4383 uint32_t w_length;\
4384 uint8_t *w_data;\
4385 torture_assert(tctx,\
4386 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4387 &w_type, &w_size, &w_length, &w_data),\
4388 "failed to query winreg");\
4389 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4390 blob = data_blob(w_data, w_size);\
4391 str = reg_val_data_string(tctx, REG_SZ, blob);\
4392 if (w_size == 2 && iname == NULL) {\
4393 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4394 } else {\
4395 torture_assert_str_equal(tctx, str, iname,\
4396 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4398 } while(0);
4400 #define test_dword(wname, iname) \
4401 do {\
4402 uint32_t value;\
4403 enum winreg_Type w_type;\
4404 uint32_t w_size;\
4405 uint32_t w_length;\
4406 uint8_t *w_data;\
4407 torture_assert(tctx,\
4408 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4409 &w_type, &w_size, &w_length, &w_data),\
4410 "failed to query winreg");\
4411 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4412 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4413 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4414 value = IVAL(w_data, 0);\
4415 torture_assert_int_equal(tctx, value, iname,\
4416 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4417 } while(0);
4419 #define test_binary(wname, iname) \
4420 do {\
4421 enum winreg_Type w_type;\
4422 uint32_t w_size;\
4423 uint32_t w_length;\
4424 uint8_t *w_data;\
4425 torture_assert(tctx,\
4426 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4427 &w_type, &w_size, &w_length, &w_data),\
4428 "failed to query winreg");\
4429 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4430 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4431 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4432 "binary unequal");\
4433 } while(0);
4436 #define test_dm(wname, iname) \
4437 do {\
4438 DATA_BLOB blob;\
4439 struct spoolss_DeviceMode dm;\
4440 enum ndr_err_code ndr_err;\
4441 enum winreg_Type w_type;\
4442 uint32_t w_size;\
4443 uint32_t w_length;\
4444 uint8_t *w_data;\
4445 torture_assert(tctx,\
4446 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4447 &w_type, &w_size, &w_length, &w_data),\
4448 "failed to query winreg");\
4449 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4450 blob = data_blob(w_data, w_size);\
4451 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4452 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4453 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4454 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4455 "dm unequal");\
4456 } while(0);
4458 #define test_sd(wname, iname) \
4459 do {\
4460 DATA_BLOB blob;\
4461 struct security_descriptor sd;\
4462 enum ndr_err_code ndr_err;\
4463 enum winreg_Type w_type;\
4464 uint32_t w_size;\
4465 uint32_t w_length;\
4466 uint8_t *w_data;\
4467 torture_assert(tctx,\
4468 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4469 &w_type, &w_size, &w_length, &w_data),\
4470 "failed to query winreg");\
4471 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4472 blob = data_blob(w_data, w_size);\
4473 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4474 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4475 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4476 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4477 "sd unequal");\
4478 } while(0);
4480 #define test_multi_sz(wname, iname) \
4481 do {\
4482 DATA_BLOB blob;\
4483 const char **array;\
4484 enum winreg_Type w_type;\
4485 uint32_t w_size;\
4486 uint32_t w_length;\
4487 uint8_t *w_data;\
4488 int i;\
4489 torture_assert(tctx,\
4490 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4491 &w_type, &w_size, &w_length, &w_data),\
4492 "failed to query winreg");\
4493 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4494 blob = data_blob(w_data, w_size);\
4495 torture_assert(tctx, \
4496 pull_reg_multi_sz(tctx, &blob, &array),\
4497 "failed to pull multi sz");\
4498 for (i=0; array[i] != NULL; i++) {\
4499 torture_assert_str_equal(tctx, array[i], iname[i],\
4500 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4502 } while(0);
4504 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4505 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4506 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4508 torture_warning(tctx, "failed to check for winreg symlink");
4511 for (i=0; i < ARRAY_SIZE(keys); i++) {
4513 const char *printer_key;
4514 struct policy_handle key_handle;
4516 printer_key = talloc_asprintf(tctx, "%s\\%s",
4517 keys[i], printer_name);
4519 torture_assert(tctx,
4520 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4522 test_sz("Name", printername);
4523 test_sz("Share Name", sharename);
4524 test_sz("Port", info.info2.portname);
4525 test_sz("Printer Driver", info.info2.drivername);
4526 test_sz("Description", info.info2.comment);
4527 test_sz("Location", info.info2.location);
4528 test_sz("Separator File", info.info2.sepfile);
4529 test_sz("Print Processor", info.info2.printprocessor);
4530 test_sz("Datatype", info.info2.datatype);
4531 test_sz("Parameters", info.info2.parameters);
4532 /* winreg: 0, spoolss not */
4533 /* test_dword("Attributes", info.info2.attributes); */
4534 test_dword("Priority", info.info2.priority);
4535 test_dword("Default Priority", info.info2.defaultpriority);
4536 /* winreg: 60, spoolss: 0 */
4537 /* test_dword("StartTime", info.info2.starttime); */
4538 /* test_dword("UntilTime", info.info2.untiltime); */
4539 /* winreg != spoolss */
4540 /* test_dword("Status", info.info2.status); */
4541 test_dm("Default DevMode", info.info2.devmode);
4542 test_sd("Security", info.info2.secdesc);
4544 torture_assert(tctx,
4545 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4548 #undef test_dm
4549 #undef test_sd
4551 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4553 return true;
4556 static bool test_PrintProcessors(struct torture_context *tctx,
4557 struct dcerpc_binding_handle *b,
4558 const char *environment,
4559 struct dcerpc_binding_handle *winreg_handle,
4560 struct policy_handle *hive_handle)
4562 union spoolss_PrintProcessorInfo *info;
4563 uint32_t count;
4564 int i;
4566 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4568 torture_assert(tctx,
4569 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4570 "failed to enum print processors level 1");
4572 for (i=0; i < count; i++) {
4574 const char *processor_key;
4575 struct policy_handle key_handle;
4577 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4578 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4579 environment,
4580 info[i].info1.print_processor_name);
4582 torture_assert(tctx,
4583 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4585 /* nothing to check in there so far */
4587 torture_assert(tctx,
4588 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4591 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4593 return true;
4596 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4597 struct dcerpc_binding_handle *b,
4598 struct policy_handle *handle,
4599 const char *driver_name,
4600 const char *architecture,
4601 uint32_t level,
4602 uint32_t client_major_version,
4603 uint32_t client_minor_version,
4604 union spoolss_DriverInfo *info_p,
4605 WERROR *result);
4607 static const char *strip_path(const char *path)
4609 char *p;
4611 if (path == NULL) {
4612 return NULL;
4615 p = strrchr(path, '\\');
4616 if (p) {
4617 return p+1;
4620 return path;
4623 static const char **strip_paths(const char **path_array)
4625 int i;
4627 if (path_array == NULL) {
4628 return NULL;
4631 for (i=0; path_array[i] != NULL; i++) {
4632 path_array[i] = strip_path(path_array[i]);
4635 return path_array;
4638 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4640 time_t t;
4641 struct tm *tm;
4643 if (nt == 0) {
4644 return talloc_strdup(mem_ctx, "01/01/1601");
4647 t = nt_time_to_unix(nt);
4648 tm = localtime(&t);
4650 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4651 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4654 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4656 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4657 (unsigned)((v >> 48) & 0xFFFF),
4658 (unsigned)((v >> 32) & 0xFFFF),
4659 (unsigned)((v >> 16) & 0xFFFF),
4660 (unsigned)(v & 0xFFFF));
4663 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4664 struct dcerpc_binding_handle *b,
4665 struct policy_handle *handle,
4666 const char *printer_name,
4667 const char *driver_name,
4668 const char *environment,
4669 enum spoolss_DriverOSVersion version,
4670 struct dcerpc_binding_handle *winreg_handle,
4671 struct policy_handle *hive_handle,
4672 const char *server_name_slash)
4674 WERROR result;
4675 union spoolss_DriverInfo info;
4676 const char *driver_key;
4677 struct policy_handle key_handle;
4679 const char *driver_path;
4680 const char *data_file;
4681 const char *config_file;
4682 const char *help_file;
4683 const char **dependent_files;
4685 const char *driver_date;
4686 const char *inbox_driver_date;
4688 const char *driver_version;
4689 const char *inbox_driver_version;
4691 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4693 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4694 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4695 environment,
4696 version,
4697 driver_name);
4699 torture_assert(tctx,
4700 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4701 "failed to open driver key");
4703 if (torture_setting_bool(tctx, "samba3", false) ||
4704 torture_setting_bool(tctx, "w2k3", false)) {
4705 goto try_level6;
4708 if (handle) {
4709 torture_assert(tctx,
4710 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4711 "failed to get driver info level 8");
4712 } else {
4713 torture_assert(tctx,
4714 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4715 "failed to get driver info level 8");
4718 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4719 goto try_level6;
4722 driver_path = strip_path(info.info8.driver_path);
4723 data_file = strip_path(info.info8.data_file);
4724 config_file = strip_path(info.info8.config_file);
4725 help_file = strip_path(info.info8.help_file);
4726 dependent_files = strip_paths(info.info8.dependent_files);
4728 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4729 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4731 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4732 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4734 test_sz("Configuration File", config_file);
4735 test_sz("Data File", data_file);
4736 test_sz("Datatype", info.info8.default_datatype);
4737 test_sz("Driver", driver_path);
4738 test_sz("DriverDate", driver_date);
4739 test_sz("DriverVersion", driver_version);
4740 test_sz("HardwareID", info.info8.hardware_id);
4741 test_sz("Help File", help_file);
4742 test_sz("InfPath", info.info8.inf_path);
4743 test_sz("Manufacturer", info.info8.manufacturer_name);
4744 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4745 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4746 test_sz("Monitor", info.info8.monitor_name);
4747 test_sz("OEM URL", info.info8.manufacturer_url);
4748 test_sz("Print Processor", info.info8.print_processor);
4749 test_sz("Provider", info.info8.provider);
4750 test_sz("VendorSetup", info.info8.vendor_setup);
4751 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4752 test_multi_sz("Dependent Files", dependent_files);
4753 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4754 test_multi_sz("Previous Names", info.info8.previous_names);
4755 /* test_dword("Attributes", ?); */
4756 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4757 test_dword("Version", info.info8.version);
4758 /* test_dword("TempDir", ?); */
4760 try_level6:
4762 if (handle) {
4763 torture_assert(tctx,
4764 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4765 "failed to get driver info level 6");
4766 } else {
4767 torture_assert(tctx,
4768 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4769 "failed to get driver info level 6");
4772 driver_path = strip_path(info.info6.driver_path);
4773 data_file = strip_path(info.info6.data_file);
4774 config_file = strip_path(info.info6.config_file);
4775 help_file = strip_path(info.info6.help_file);
4776 dependent_files = strip_paths(info.info6.dependent_files);
4778 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4780 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4782 test_sz("Configuration File", config_file);
4783 test_sz("Data File", data_file);
4784 test_sz("Datatype", info.info6.default_datatype);
4785 test_sz("Driver", driver_path);
4786 if (torture_setting_bool(tctx, "w2k3", false)) {
4787 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4788 push_nttime(blob.data, 0, info.info6.driver_date);
4789 test_binary("DriverDate", blob);
4790 SBVAL(blob.data, 0, info.info6.driver_version);
4791 test_binary("DriverVersion", blob);
4792 } else {
4793 test_sz("DriverDate", driver_date);
4794 test_sz("DriverVersion", driver_version);
4796 test_sz("HardwareID", info.info6.hardware_id);
4797 test_sz("Help File", help_file);
4798 test_sz("Manufacturer", info.info6.manufacturer_name);
4799 test_sz("Monitor", info.info6.monitor_name);
4800 test_sz("OEM URL", info.info6.manufacturer_url);
4801 test_sz("Provider", info.info6.provider);
4802 test_multi_sz("Dependent Files", dependent_files);
4803 test_multi_sz("Previous Names", info.info6.previous_names);
4804 /* test_dword("Attributes", ?); */
4805 test_dword("Version", info.info6.version);
4806 /* test_dword("TempDir", ?); */
4808 if (handle) {
4809 torture_assert(tctx,
4810 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4811 "failed to get driver info level 3");
4812 } else {
4813 torture_assert(tctx,
4814 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4815 "failed to get driver info level 3");
4818 driver_path = strip_path(info.info3.driver_path);
4819 data_file = strip_path(info.info3.data_file);
4820 config_file = strip_path(info.info3.config_file);
4821 help_file = strip_path(info.info3.help_file);
4822 dependent_files = strip_paths(info.info3.dependent_files);
4824 test_sz("Configuration File", config_file);
4825 test_sz("Data File", data_file);
4826 test_sz("Datatype", info.info3.default_datatype);
4827 test_sz("Driver", driver_path);
4828 test_sz("Help File", help_file);
4829 test_sz("Monitor", info.info3.monitor_name);
4830 test_multi_sz("Dependent Files", dependent_files);
4831 /* test_dword("Attributes", ?); */
4832 test_dword("Version", info.info3.version);
4833 /* test_dword("TempDir", ?); */
4836 torture_assert(tctx,
4837 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4839 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4841 return true;
4844 #undef test_sz
4845 #undef test_dword
4847 static bool test_SetPrinterData(struct torture_context *tctx,
4848 struct dcerpc_binding_handle *b,
4849 struct policy_handle *handle,
4850 const char *value_name,
4851 enum winreg_Type type,
4852 uint8_t *data,
4853 uint32_t offered)
4855 struct spoolss_SetPrinterData r;
4857 r.in.handle = handle;
4858 r.in.value_name = value_name;
4859 r.in.type = type;
4860 r.in.data = data;
4861 r.in.offered = offered;
4863 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4864 r.in.value_name);
4866 torture_assert_ntstatus_ok(tctx,
4867 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4868 "SetPrinterData failed");
4869 torture_assert_werr_ok(tctx, r.out.result,
4870 "SetPrinterData failed");
4872 return true;
4875 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4876 struct dcerpc_binding_handle *b,
4877 struct policy_handle *handle,
4878 const char *printer_name,
4879 struct dcerpc_binding_handle *winreg_handle,
4880 struct policy_handle *hive_handle)
4882 const char *values[] = {
4883 "spootyfoot",
4884 "spooty\\foot",
4885 #if 0
4886 /* FIXME: not working with s3 atm. */
4887 "spooty,foot",
4888 "spooty,fo,ot",
4889 #endif
4890 "spooty foot",
4891 #if 0
4892 /* FIXME: not working with s3 atm. */
4893 "spooty\\fo,ot",
4894 "spooty,fo\\ot"
4895 #endif
4897 int i;
4899 for (i=0; i < ARRAY_SIZE(values); i++) {
4901 enum winreg_Type type, expected_type = REG_SZ;
4902 DATA_BLOB blob;
4903 uint8_t *data;
4904 uint32_t needed;
4906 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4907 type = REG_SZ;
4909 torture_assert(tctx,
4910 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4911 "SetPrinterData failed");
4913 torture_assert(tctx,
4914 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4915 "GetPrinterData failed");
4917 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4918 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4919 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4921 if (winreg_handle && hive_handle) {
4923 enum winreg_Type w_type;
4924 uint32_t w_size;
4925 uint32_t w_length;
4926 uint8_t *w_data;
4928 torture_assert(tctx,
4929 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4930 printer_name, "PrinterDriverData", values[i],
4931 &w_type, &w_size, &w_length, &w_data), "");
4933 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4934 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4935 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4936 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4939 torture_assert(tctx,
4940 test_DeletePrinterData(tctx, b, handle, values[i]),
4941 "DeletePrinterData failed");
4944 return true;
4948 static bool test_EnumPrinterKey(struct torture_context *tctx,
4949 struct dcerpc_binding_handle *b,
4950 struct policy_handle *handle,
4951 const char *key_name,
4952 const char ***array);
4954 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4955 struct dcerpc_binding_handle *b,
4956 struct policy_handle *handle,
4957 const char *key_name,
4958 const char *value_name,
4959 enum winreg_Type type,
4960 uint8_t *data,
4961 uint32_t offered)
4963 NTSTATUS status;
4964 struct spoolss_SetPrinterDataEx r;
4966 r.in.handle = handle;
4967 r.in.key_name = key_name;
4968 r.in.value_name = value_name;
4969 r.in.type = type;
4970 r.in.data = data;
4971 r.in.offered = offered;
4973 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4974 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4976 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4978 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4979 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4981 return true;
4984 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4985 struct dcerpc_pipe *p,
4986 struct policy_handle *handle)
4988 struct dcerpc_binding_handle *b = p->binding_handle;
4989 const char *value_name = "dog";
4990 const char *keys[] = {
4991 "torturedataex",
4992 "torture data ex",
4993 "torturedataex_with_subkey\\subkey",
4994 "torturedataex_with_subkey\\subkey:0",
4995 "torturedataex_with_subkey\\subkey:1",
4996 "torturedataex_with_subkey\\subkey\\subsubkey",
4997 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4998 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4999 "torture,data",
5000 "torture,data,ex",
5001 "torture,data\\ex",
5002 "torture\\data,ex",
5003 "torture/data",
5004 "torture/data ex",
5005 "torture/data ex/sub",
5006 "torture//data",
5007 "torture//data ex",
5008 "torture//data ex/sub",
5009 "torture//data ex//sub",
5011 int i;
5013 for (i=0; i < ARRAY_SIZE(keys); i++) {
5015 char *c;
5016 const char *key;
5017 enum winreg_Type type;
5018 DATA_BLOB blob_in, blob_out;
5019 const char **subkeys;
5020 uint32_t ecount;
5021 struct spoolss_PrinterEnumValues *einfo;
5022 uint32_t needed;
5024 blob_in = data_blob_talloc(tctx, NULL, 42);
5026 generate_random_buffer(blob_in.data, blob_in.length);
5028 torture_assert(tctx,
5029 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5030 "failed to call SetPrinterDataEx");
5032 torture_assert(tctx,
5033 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5034 "failed to call GetPrinterDataEx");
5036 blob_out.length = needed;
5037 torture_assert(tctx,
5038 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5039 "failed to call EnumPrinterDataEx");
5041 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5042 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5043 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5045 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5046 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5047 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5048 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5049 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5050 if (einfo[0].data_length > 0) {
5051 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5054 key = talloc_strdup(tctx, keys[i]);
5056 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5057 return false;
5060 c = strchr(key, '\\');
5061 if (c) {
5062 int k;
5064 /* we have subkeys */
5066 *c = 0;
5068 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5069 return false;
5072 for (k=0; subkeys && subkeys[k]; k++) {
5074 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5076 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5077 return false;
5081 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5082 return false;
5085 } else {
5086 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5087 return false;
5092 return true;
5095 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5096 struct dcerpc_pipe *p,
5097 struct policy_handle *handle)
5099 struct dcerpc_binding_handle *b = p->binding_handle;
5100 const char *key = "torturedataex";
5101 const char *values[] = {
5102 "torture_value",
5103 "torture value",
5104 "torture,value",
5105 "torture/value",
5106 "torture\\value",
5107 "torture\\\\value"
5109 int i;
5111 for (i=0; i < ARRAY_SIZE(values); i++) {
5113 enum winreg_Type type;
5114 DATA_BLOB blob_in, blob_out;
5115 uint32_t ecount;
5116 struct spoolss_PrinterEnumValues *einfo;
5117 uint32_t needed;
5119 if (torture_setting_bool(tctx, "samba3", false)) {
5120 char *q;
5121 q = strrchr(values[i], ',');
5122 if (q) {
5123 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5124 values[i]);
5125 continue;
5129 blob_in = data_blob_talloc(tctx, NULL, 42);
5131 generate_random_buffer(blob_in.data, blob_in.length);
5133 torture_assert(tctx,
5134 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5135 "failed to call SetPrinterDataEx");
5137 torture_assert(tctx,
5138 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5139 "failed to call GetPrinterDataEx");
5141 blob_out.length = needed;
5142 torture_assert(tctx,
5143 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5144 "failed to call EnumPrinterDataEx");
5146 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5147 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5148 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5150 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5151 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5152 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5153 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5154 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5155 if (einfo[0].data_length > 0) {
5156 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5159 torture_assert(tctx,
5160 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5161 "failed to call DeletePrinterDataEx");
5164 return true;
5168 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5169 struct dcerpc_pipe *p,
5170 struct policy_handle *handle,
5171 const char *printername,
5172 struct dcerpc_binding_handle *winreg_handle,
5173 struct policy_handle *hive_handle)
5175 struct dcerpc_binding_handle *b = p->binding_handle;
5176 const char *value_name = "dog";
5177 const char *key_name = "torturedataex";
5178 enum winreg_Type types[] = {
5179 REG_SZ,
5180 REG_MULTI_SZ,
5181 REG_DWORD,
5182 REG_BINARY
5184 const char *str = "abcdefghi";
5185 int t, s;
5187 for (t=0; t < ARRAY_SIZE(types); t++) {
5188 for (s=0; s < strlen(str); s++) {
5190 enum winreg_Type type;
5191 const char *string = talloc_strndup(tctx, str, s);
5192 const char *array[2];
5193 DATA_BLOB blob = data_blob_string_const(string);
5194 DATA_BLOB data;
5195 uint8_t *data_out;
5196 uint32_t needed, offered = 0;
5197 uint32_t ecount;
5198 struct spoolss_PrinterEnumValues *einfo;
5200 array[0] = talloc_strdup(tctx, string);
5201 array[1] = NULL;
5203 if (types[t] == REG_DWORD) {
5204 s = 0xffff;
5207 switch (types[t]) {
5208 case REG_BINARY:
5209 data = blob;
5210 offered = blob.length;
5211 break;
5212 case REG_DWORD:
5213 data = data_blob_talloc(tctx, NULL, 4);
5214 SIVAL(data.data, 0, 0x12345678);
5215 offered = 4;
5216 break;
5217 case REG_SZ:
5218 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5219 type = REG_SZ;
5220 offered = data.length;
5221 /*strlen_m_term(data.string)*2;*/
5222 break;
5223 case REG_MULTI_SZ:
5224 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5225 type = REG_MULTI_SZ;
5226 offered = data.length;
5227 break;
5228 default:
5229 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5232 torture_assert(tctx,
5233 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5234 "failed to call SetPrinterDataEx");
5236 torture_assert(tctx,
5237 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5238 "failed to call GetPrinterDataEx");
5240 torture_assert(tctx,
5241 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5242 "failed to call EnumPrinterDataEx");
5244 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5245 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5246 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5248 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5249 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5250 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5251 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5252 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5253 if (einfo[0].data_length > 0) {
5254 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5257 if (winreg_handle && hive_handle) {
5258 enum winreg_Type w_type;
5259 uint32_t w_size;
5260 uint32_t w_length;
5261 uint8_t *w_data;
5263 torture_assert(tctx,
5264 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5265 printername, key_name, value_name,
5266 &w_type, &w_size, &w_length, &w_data), "");
5268 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5269 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5270 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5271 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5274 torture_assert(tctx,
5275 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5276 "failed to call DeletePrinterDataEx");
5280 return true;
5283 static bool test_PrinterData_winreg(struct torture_context *tctx,
5284 struct dcerpc_pipe *p,
5285 struct policy_handle *handle,
5286 const char *printer_name)
5288 struct dcerpc_binding_handle *b = p->binding_handle;
5289 struct dcerpc_pipe *p2;
5290 bool ret = true;
5291 struct policy_handle hive_handle;
5292 struct dcerpc_binding_handle *b2;
5294 torture_assert_ntstatus_ok(tctx,
5295 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5296 "could not open winreg pipe");
5297 b2 = p2->binding_handle;
5299 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5301 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5302 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5304 test_winreg_CloseKey(tctx, b2, &hive_handle);
5306 talloc_free(p2);
5308 return ret;
5311 static bool test_Forms_winreg(struct torture_context *tctx,
5312 struct dcerpc_binding_handle *b,
5313 struct policy_handle *handle,
5314 bool print_server,
5315 const char *printer_name)
5317 struct dcerpc_pipe *p2;
5318 bool ret = true;
5319 struct policy_handle hive_handle;
5320 struct dcerpc_binding_handle *b2;
5322 torture_assert_ntstatus_ok(tctx,
5323 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5324 "could not open winreg pipe");
5325 b2 = p2->binding_handle;
5327 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5329 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5331 test_winreg_CloseKey(tctx, b2, &hive_handle);
5333 talloc_free(p2);
5335 return ret;
5338 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5339 struct dcerpc_pipe *p,
5340 struct policy_handle *handle,
5341 const char *printer_name)
5343 struct dcerpc_binding_handle *b = p->binding_handle;
5344 struct dcerpc_pipe *p2;
5345 bool ret = true;
5346 struct policy_handle hive_handle;
5347 struct dcerpc_binding_handle *b2;
5349 torture_assert_ntstatus_ok(tctx,
5350 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5351 "could not open winreg pipe");
5352 b2 = p2->binding_handle;
5354 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5356 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5358 test_winreg_CloseKey(tctx, b2, &hive_handle);
5360 talloc_free(p2);
5362 return ret;
5365 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5366 struct dcerpc_pipe *p,
5367 struct policy_handle *handle,
5368 const char *printer_name,
5369 const char *driver_name,
5370 const char *environment,
5371 enum spoolss_DriverOSVersion version)
5373 struct dcerpc_binding_handle *b = p->binding_handle;
5374 struct dcerpc_pipe *p2;
5375 bool ret = true;
5376 struct policy_handle hive_handle;
5377 struct dcerpc_binding_handle *b2;
5379 torture_assert_ntstatus_ok(tctx,
5380 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5381 "could not open winreg pipe");
5382 b2 = p2->binding_handle;
5384 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5386 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5388 test_winreg_CloseKey(tctx, b2, &hive_handle);
5390 talloc_free(p2);
5392 return ret;
5395 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5396 struct dcerpc_binding_handle *b,
5397 const char *environment)
5399 struct dcerpc_pipe *p2;
5400 bool ret = true;
5401 struct policy_handle hive_handle;
5402 struct dcerpc_binding_handle *b2;
5404 torture_assert_ntstatus_ok(tctx,
5405 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5406 "could not open winreg pipe");
5407 b2 = p2->binding_handle;
5409 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5411 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5413 test_winreg_CloseKey(tctx, b2, &hive_handle);
5415 talloc_free(p2);
5417 return ret;
5420 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5421 struct dcerpc_pipe *p,
5422 struct policy_handle *handle,
5423 const char *printer_name)
5425 struct spoolss_SetPrinterInfoCtr info_ctr;
5426 struct spoolss_DevmodeContainer devmode_ctr;
5427 struct sec_desc_buf secdesc_ctr;
5428 union spoolss_SetPrinterInfo sinfo;
5429 union spoolss_PrinterInfo info;
5430 struct dcerpc_binding_handle *b = p->binding_handle;
5431 const char *pname;
5433 ZERO_STRUCT(info_ctr);
5434 ZERO_STRUCT(devmode_ctr);
5435 ZERO_STRUCT(secdesc_ctr);
5437 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5439 torture_assert(tctx,
5440 test_GetPrinter_level(tctx, b, handle, 2, &info),
5441 "failed to query Printer level 2");
5443 torture_assert(tctx,
5444 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5445 "failed to convert");
5447 info_ctr.level = 2;
5448 info_ctr.info = sinfo;
5450 #define TEST_SZ(wname, iname) \
5451 do {\
5452 enum winreg_Type type;\
5453 uint8_t *data;\
5454 uint32_t needed;\
5455 DATA_BLOB blob;\
5456 const char *str;\
5457 torture_assert(tctx,\
5458 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5459 "failed to query");\
5460 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5461 blob = data_blob_const(data, needed);\
5462 torture_assert(tctx,\
5463 pull_reg_sz(tctx, &blob, &str),\
5464 "failed to pull REG_SZ");\
5465 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5466 } while(0);
5469 #define TEST_SET_SZ(wname, iname, val) \
5470 do {\
5471 enum winreg_Type type;\
5472 uint8_t *data;\
5473 uint32_t needed;\
5474 DATA_BLOB blob;\
5475 const char *str;\
5476 sinfo.info2->iname = val;\
5477 torture_assert(tctx,\
5478 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5479 "failed to call SetPrinter");\
5480 torture_assert(tctx,\
5481 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5482 "failed to query");\
5483 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5484 blob = data_blob_const(data, needed);\
5485 torture_assert(tctx,\
5486 pull_reg_sz(tctx, &blob, &str),\
5487 "failed to pull REG_SZ");\
5488 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5489 } while(0);
5491 #define TEST_SET_DWORD(wname, iname, val) \
5492 do {\
5493 enum winreg_Type type;\
5494 uint8_t *data;\
5495 uint32_t needed;\
5496 uint32_t value;\
5497 sinfo.info2->iname = val;\
5498 torture_assert(tctx,\
5499 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5500 "failed to call SetPrinter");\
5501 torture_assert(tctx,\
5502 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5503 "failed to query");\
5504 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5505 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5506 value = IVAL(data, 0); \
5507 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5508 } while(0);
5510 TEST_SET_SZ("description", comment, "newval");
5511 TEST_SET_SZ("location", location, "newval");
5512 TEST_SET_SZ("driverName", drivername, "newval");
5513 /* TEST_SET_DWORD("priority", priority, 25); */
5515 torture_assert(tctx,
5516 test_GetPrinter_level(tctx, b, handle, 2, &info),
5517 "failed to query Printer level 2");
5519 TEST_SZ("description", info.info2.comment);
5520 TEST_SZ("driverName", info.info2.drivername);
5521 TEST_SZ("location", info.info2.location);
5523 pname = strrchr(info.info2.printername, '\\');
5524 if (pname == NULL) {
5525 pname = info.info2.printername;
5526 } else {
5527 pname++;
5529 TEST_SZ("printerName", pname);
5530 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5531 /* TEST_SZ("printShareName", info.info2.sharename); */
5533 /* FIXME gd: complete the list */
5535 #undef TEST_SZ
5536 #undef TEST_SET_SZ
5537 #undef TEST_DWORD
5539 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5541 return true;
5544 static bool test_print_processors_winreg(struct torture_context *tctx,
5545 void *private_data)
5547 struct test_spoolss_context *ctx =
5548 talloc_get_type_abort(private_data, struct test_spoolss_context);
5549 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5550 struct dcerpc_binding_handle *b = p->binding_handle;
5552 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5555 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5556 struct dcerpc_binding_handle *b,
5557 struct policy_handle *handle,
5558 uint32_t *change_id)
5560 enum winreg_Type type;
5561 uint8_t *data;
5562 uint32_t needed;
5564 torture_assert(tctx,
5565 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5566 "failed to call GetPrinterData");
5568 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5569 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5571 *change_id = IVAL(data, 0);
5573 return true;
5576 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5577 struct dcerpc_pipe *p,
5578 struct policy_handle *handle,
5579 uint32_t *change_id)
5581 enum winreg_Type type;
5582 uint8_t *data;
5583 uint32_t needed;
5585 torture_assert(tctx,
5586 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5587 "failed to call GetPrinterData");
5589 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5590 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5592 *change_id = IVAL(data, 0);
5594 return true;
5597 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5598 struct dcerpc_binding_handle *b,
5599 struct policy_handle *handle,
5600 uint32_t *change_id)
5602 union spoolss_PrinterInfo info;
5604 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5605 "failed to query Printer level 0");
5607 *change_id = info.info0.change_id;
5609 return true;
5612 static bool test_ChangeID(struct torture_context *tctx,
5613 struct dcerpc_pipe *p,
5614 struct policy_handle *handle)
5616 uint32_t change_id, change_id_ex, change_id_info;
5617 uint32_t change_id2, change_id_ex2, change_id_info2;
5618 union spoolss_PrinterInfo info;
5619 const char *comment;
5620 struct dcerpc_binding_handle *b = p->binding_handle;
5622 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5624 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5625 "failed to query for ChangeID");
5626 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5627 "failed to query for ChangeID");
5628 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5629 "failed to query for ChangeID");
5631 torture_assert_int_equal(tctx, change_id, change_id_ex,
5632 "change_ids should all be equal");
5633 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5634 "change_ids should all be equal");
5637 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5639 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5640 "failed to query for ChangeID");
5641 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5642 "failed to query Printer level 2");
5643 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5644 "failed to query for ChangeID");
5645 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5646 "failed to query for ChangeID");
5647 torture_assert_int_equal(tctx, change_id, change_id_ex,
5648 "change_id should not have changed");
5649 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5650 "change_id should not have changed");
5653 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5655 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5656 "failed to query for ChangeID");
5657 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5658 "failed to query for ChangeID");
5659 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5660 "failed to query for ChangeID");
5661 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5662 "failed to query Printer level 2");
5663 comment = talloc_strdup(tctx, info.info2.comment);
5666 struct spoolss_SetPrinterInfoCtr info_ctr;
5667 struct spoolss_DevmodeContainer devmode_ctr;
5668 struct sec_desc_buf secdesc_ctr;
5669 union spoolss_SetPrinterInfo sinfo;
5671 ZERO_STRUCT(info_ctr);
5672 ZERO_STRUCT(devmode_ctr);
5673 ZERO_STRUCT(secdesc_ctr);
5676 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5677 sinfo.info2->comment = "torture_comment";
5679 info_ctr.level = 2;
5680 info_ctr.info = sinfo;
5682 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5683 "failed to call SetPrinter");
5685 sinfo.info2->comment = comment;
5687 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5688 "failed to call SetPrinter");
5692 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5693 "failed to query for ChangeID");
5694 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5695 "failed to query for ChangeID");
5696 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5697 "failed to query for ChangeID");
5699 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5700 "change_ids should all be equal");
5701 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5702 "change_ids should all be equal");
5704 torture_assert(tctx, (change_id < change_id2),
5705 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5706 change_id2, change_id));
5707 torture_assert(tctx, (change_id_ex < change_id_ex2),
5708 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5709 change_id_ex2, change_id_ex));
5710 torture_assert(tctx, (change_id_info < change_id_info2),
5711 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5712 change_id_info2, change_id_info));
5714 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5716 return true;
5719 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5720 struct dcerpc_pipe *p,
5721 struct policy_handle *handle)
5723 NTSTATUS status;
5724 struct dcerpc_binding *b;
5725 struct dcerpc_pipe *p2;
5726 struct spoolss_ClosePrinter cp;
5728 /* only makes sense on SMB */
5729 if (p->conn->transport.transport != NCACN_NP) {
5730 return true;
5733 torture_comment(tctx, "Testing close on secondary pipe\n");
5735 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5736 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5738 status = dcerpc_secondary_connection(p, &p2, b);
5739 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5741 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5742 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5744 cp.in.handle = handle;
5745 cp.out.handle = handle;
5747 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5748 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5749 "ERROR: Allowed close on secondary connection");
5751 talloc_free(p2);
5753 return true;
5756 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5757 struct dcerpc_binding_handle *b, const char *name)
5759 NTSTATUS status;
5760 struct spoolss_OpenPrinter op;
5761 struct spoolss_OpenPrinterEx opEx;
5762 struct policy_handle handle;
5763 bool ret = true;
5765 op.in.printername = name;
5766 op.in.datatype = NULL;
5767 op.in.devmode_ctr.devmode= NULL;
5768 op.in.access_mask = 0;
5769 op.out.handle = &handle;
5771 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5773 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5774 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5775 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5776 "unexpected result");
5778 if (W_ERROR_IS_OK(op.out.result)) {
5779 ret &=test_ClosePrinter(tctx, b, &handle);
5782 opEx.in.printername = name;
5783 opEx.in.datatype = NULL;
5784 opEx.in.devmode_ctr.devmode = NULL;
5785 opEx.in.access_mask = 0;
5786 opEx.in.userlevel_ctr.level = 1;
5787 opEx.in.userlevel_ctr.user_info.level1 = NULL;
5788 opEx.out.handle = &handle;
5790 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5792 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5793 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5794 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5795 "unexpected result");
5797 if (W_ERROR_IS_OK(opEx.out.result)) {
5798 ret &=test_ClosePrinter(tctx, b, &handle);
5801 return ret;
5804 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5805 void *private_data)
5807 struct test_spoolss_context *ctx =
5808 talloc_get_type_abort(private_data, struct test_spoolss_context);
5810 const char *badnames[] = {
5811 "__INVALID_PRINTER__",
5812 "\\\\__INVALID_HOST__",
5814 "\\\\\\",
5815 "\\\\\\__INVALID_PRINTER__"
5817 const char *badname;
5818 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5819 const char *server_name = dcerpc_server_name(p);
5820 struct dcerpc_binding_handle *b = p->binding_handle;
5821 int i;
5823 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5824 torture_assert(tctx,
5825 test_OpenPrinter_badname(tctx, b, badnames[i]),
5826 "");
5829 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5830 torture_assert(tctx,
5831 test_OpenPrinter_badname(tctx, b, badname),
5832 "");
5834 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5835 torture_assert(tctx,
5836 test_OpenPrinter_badname(tctx, b, badname),
5837 "");
5839 return true;
5842 static bool test_OpenPrinter(struct torture_context *tctx,
5843 struct dcerpc_pipe *p,
5844 const char *name,
5845 const char *environment,
5846 bool open_only)
5848 NTSTATUS status;
5849 struct spoolss_OpenPrinter r;
5850 struct policy_handle handle;
5851 bool ret = true;
5852 struct dcerpc_binding_handle *b = p->binding_handle;
5854 r.in.printername = name;
5855 r.in.datatype = NULL;
5856 r.in.devmode_ctr.devmode= NULL;
5857 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5858 r.out.handle = &handle;
5860 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5862 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5864 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5866 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5868 if (open_only) {
5869 goto close_printer;
5872 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5873 ret = false;
5876 if (!torture_setting_bool(tctx, "samba3", false)) {
5877 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5878 ret = false;
5882 close_printer:
5883 if (!test_ClosePrinter(tctx, b, &handle)) {
5884 ret = false;
5887 return ret;
5890 static bool test_OpenPrinterEx(struct torture_context *tctx,
5891 struct dcerpc_binding_handle *b,
5892 const char *printername,
5893 const char *datatype,
5894 struct spoolss_DeviceMode *devmode,
5895 uint32_t access_mask,
5896 struct spoolss_UserLevelCtr *userlevel_ctr,
5897 struct policy_handle *handle,
5898 WERROR expected_result)
5900 struct spoolss_OpenPrinterEx r;
5902 r.in.printername = printername;
5903 r.in.datatype = datatype;
5904 r.in.devmode_ctr.devmode= devmode;
5905 r.in.access_mask = access_mask;
5906 r.in.userlevel_ctr = *userlevel_ctr;
5907 r.out.handle = handle;
5909 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5911 torture_assert_ntstatus_ok(tctx,
5912 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5913 "OpenPrinterEx failed");
5915 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5916 "OpenPrinterEx failed");
5918 return true;
5921 static bool call_OpenPrinterEx(struct torture_context *tctx,
5922 struct dcerpc_pipe *p,
5923 const char *name,
5924 struct spoolss_DeviceMode *devmode,
5925 struct policy_handle *handle)
5927 struct spoolss_UserLevelCtr userlevel_ctr;
5928 struct spoolss_UserLevel1 userlevel1;
5929 struct dcerpc_binding_handle *b = p->binding_handle;
5931 userlevel1.size = 1234;
5932 userlevel1.client = "hello";
5933 userlevel1.user = "spottyfoot!";
5934 userlevel1.build = 1;
5935 userlevel1.major = 2;
5936 userlevel1.minor = 3;
5937 userlevel1.processor = 4;
5939 userlevel_ctr.level = 1;
5940 userlevel_ctr.user_info.level1 = &userlevel1;
5942 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5943 SEC_FLAG_MAXIMUM_ALLOWED,
5944 &userlevel_ctr,
5945 handle,
5946 WERR_OK);
5949 static bool test_printer_rename(struct torture_context *tctx,
5950 void *private_data)
5952 struct torture_printer_context *t =
5953 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5954 struct dcerpc_pipe *p = t->spoolss_pipe;
5956 bool ret = true;
5957 union spoolss_PrinterInfo info;
5958 union spoolss_SetPrinterInfo sinfo;
5959 struct spoolss_SetPrinterInfoCtr info_ctr;
5960 struct spoolss_DevmodeContainer devmode_ctr;
5961 struct sec_desc_buf secdesc_ctr;
5962 const char *printer_name;
5963 const char *printer_name_orig;
5964 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5965 struct policy_handle new_handle;
5966 const char *q;
5967 struct dcerpc_binding_handle *b = p->binding_handle;
5969 ZERO_STRUCT(devmode_ctr);
5970 ZERO_STRUCT(secdesc_ctr);
5972 torture_comment(tctx, "Testing Printer rename operations\n");
5974 torture_assert(tctx,
5975 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5976 "failed to call GetPrinter level 2");
5978 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5980 q = strrchr(info.info2.printername, '\\');
5981 if (q) {
5982 torture_warning(tctx,
5983 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5986 torture_assert(tctx,
5987 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5989 sinfo.info2->printername = printer_name_new;
5991 info_ctr.level = 2;
5992 info_ctr.info = sinfo;
5994 torture_assert(tctx,
5995 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5996 "failed to call SetPrinter level 2");
5998 torture_assert(tctx,
5999 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6000 "failed to call GetPrinter level 2");
6002 printer_name = talloc_strdup(tctx, info.info2.printername);
6004 q = strrchr(info.info2.printername, '\\');
6005 if (q) {
6006 torture_warning(tctx,
6007 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6008 q++;
6009 printer_name = q;
6012 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6013 "new printer name was not set");
6015 /* samba currently cannot fully rename printers */
6016 if (!torture_setting_bool(tctx, "samba3", false)) {
6017 torture_assert(tctx,
6018 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6019 "still can open printer with oldname after rename");
6020 } else {
6021 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6024 torture_assert(tctx,
6025 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6026 "failed to open printer with new name");
6028 torture_assert(tctx,
6029 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6030 "failed to call GetPrinter level 2");
6032 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6033 "new printer name was not set");
6035 torture_assert(tctx,
6036 test_ClosePrinter(tctx, b, &new_handle),
6037 "failed to close printer");
6039 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6041 return ret;
6044 static bool test_openprinter(struct torture_context *tctx,
6045 struct dcerpc_binding_handle *b,
6046 const char *real_printername)
6048 struct spoolss_UserLevelCtr userlevel_ctr;
6049 struct policy_handle handle;
6050 struct spoolss_UserLevel1 userlevel1;
6051 const char *printername = NULL;
6052 int i;
6054 struct {
6055 const char *suffix;
6056 WERROR expected_result;
6057 } tests[] = {
6059 .suffix = "rubbish",
6060 .expected_result = WERR_INVALID_PRINTER_NAME
6062 .suffix = ", LocalOnl",
6063 .expected_result = WERR_INVALID_PRINTER_NAME
6065 .suffix = ", localOnly",
6066 .expected_result = WERR_INVALID_PRINTER_NAME
6068 .suffix = ", localonl",
6069 .expected_result = WERR_INVALID_PRINTER_NAME
6071 .suffix = ",LocalOnl",
6072 .expected_result = WERR_INVALID_PRINTER_NAME
6074 .suffix = ",localOnl2",
6075 .expected_result = WERR_INVALID_PRINTER_NAME
6077 .suffix = ", DrvConver2t",
6078 .expected_result = WERR_INVALID_PRINTER_NAME
6080 .suffix = ", drvconvert",
6081 .expected_result = WERR_INVALID_PRINTER_NAME
6083 .suffix = ",drvconvert",
6084 .expected_result = WERR_INVALID_PRINTER_NAME
6086 .suffix = ", DrvConvert",
6087 .expected_result = WERR_OK
6089 .suffix = " , DrvConvert",
6090 .expected_result = WERR_INVALID_PRINTER_NAME
6092 .suffix = ",DrvConvert",
6093 .expected_result = WERR_OK
6095 .suffix = ", DrvConvertsadfasdf",
6096 .expected_result = WERR_OK
6098 .suffix = ",DrvConvertasdfasd",
6099 .expected_result = WERR_OK
6101 .suffix = ", LocalOnly",
6102 .expected_result = WERR_OK
6104 .suffix = " , LocalOnly",
6105 .expected_result = WERR_INVALID_PRINTER_NAME
6107 .suffix = ",LocalOnly",
6108 .expected_result = WERR_OK
6110 .suffix = ", LocalOnlysagi4gjfkd",
6111 .expected_result = WERR_OK
6113 .suffix = ",LocalOnlysagi4gjfkd",
6114 .expected_result = WERR_OK
6118 userlevel1.size = 1234;
6119 userlevel1.client = "hello";
6120 userlevel1.user = "spottyfoot!";
6121 userlevel1.build = 1;
6122 userlevel1.major = 2;
6123 userlevel1.minor = 3;
6124 userlevel1.processor = 4;
6126 userlevel_ctr.level = 1;
6127 userlevel_ctr.user_info.level1 = &userlevel1;
6129 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6131 torture_assert(tctx,
6132 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6133 &userlevel_ctr, &handle,
6134 WERR_OK),
6135 "OpenPrinterEx failed");
6136 test_ClosePrinter(tctx, b, &handle);
6138 for (i=0; i < ARRAY_SIZE(tests); i++) {
6140 printername = talloc_asprintf(tctx, "%s%s",
6141 real_printername,
6142 tests[i].suffix);
6144 torture_assert(tctx,
6145 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6146 &userlevel_ctr, &handle,
6147 tests[i].expected_result),
6148 "OpenPrinterEx failed");
6149 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6150 test_ClosePrinter(tctx, b, &handle);
6154 return true;
6158 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6159 struct dcerpc_pipe *p,
6160 const char *name,
6161 const char *environment)
6163 struct policy_handle handle;
6164 bool ret = true;
6165 struct dcerpc_binding_handle *b = p->binding_handle;
6167 if (!test_openprinter(tctx, b, name)) {
6168 return false;
6171 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6172 return false;
6175 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6176 ret = false;
6179 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6180 ret = false;
6183 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6184 ret = false;
6187 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6188 ret = false;
6191 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6192 ret = false;
6195 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6196 ret = false;
6199 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6200 ret = false;
6203 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6204 ret = false;
6207 if (!test_printer_all_keys(tctx, b, &handle)) {
6208 ret = false;
6211 if (!test_PausePrinter(tctx, b, &handle)) {
6212 ret = false;
6215 if (!test_DoPrintTest(tctx, b, &handle)) {
6216 ret = false;
6219 if (!test_ResumePrinter(tctx, b, &handle)) {
6220 ret = false;
6223 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6224 ret = false;
6227 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6228 ret = false;
6231 if (!torture_setting_bool(tctx, "samba3", false)) {
6232 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6233 ret = false;
6237 if (!test_ClosePrinter(tctx, b, &handle)) {
6238 ret = false;
6241 return ret;
6244 static bool test_EnumPrinters_old(struct torture_context *tctx,
6245 void *private_data)
6247 struct test_spoolss_context *ctx =
6248 talloc_get_type_abort(private_data, struct test_spoolss_context);
6249 struct spoolss_EnumPrinters r;
6250 NTSTATUS status;
6251 uint16_t levels[] = {1, 2, 4, 5};
6252 int i;
6253 bool ret = true;
6254 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6255 struct dcerpc_binding_handle *b = p->binding_handle;
6257 for (i=0;i<ARRAY_SIZE(levels);i++) {
6258 union spoolss_PrinterInfo *info;
6259 int j;
6260 uint32_t needed;
6261 uint32_t count;
6263 r.in.flags = PRINTER_ENUM_LOCAL;
6264 r.in.server = "";
6265 r.in.level = levels[i];
6266 r.in.buffer = NULL;
6267 r.in.offered = 0;
6268 r.out.needed = &needed;
6269 r.out.count = &count;
6270 r.out.info = &info;
6272 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6274 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6275 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6277 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6278 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6279 r.in.buffer = &blob;
6280 r.in.offered = needed;
6281 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6284 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6286 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6288 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6290 if (!info) {
6291 torture_comment(tctx, "No printers returned\n");
6292 return true;
6295 for (j=0;j<count;j++) {
6296 if (r.in.level == 1) {
6297 char *unc = talloc_strdup(tctx, info[j].info1.name);
6298 char *slash, *name, *full_name;
6299 name = unc;
6300 if (unc[0] == '\\' && unc[1] == '\\') {
6301 unc +=2;
6303 slash = strchr(unc, '\\');
6304 if (slash) {
6305 slash++;
6306 name = slash;
6308 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6309 dcerpc_server_name(p), name);
6310 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6311 ret = false;
6313 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6314 ret = false;
6316 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6317 ret = false;
6319 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6320 ret = false;
6326 return ret;
6329 static bool test_EnumPrinters_level(struct torture_context *tctx,
6330 struct dcerpc_binding_handle *b,
6331 uint32_t flags,
6332 const char *servername,
6333 uint32_t level,
6334 uint32_t *count_p,
6335 union spoolss_PrinterInfo **info_p)
6337 struct spoolss_EnumPrinters r;
6338 union spoolss_PrinterInfo *info;
6339 uint32_t needed;
6340 uint32_t count;
6342 r.in.flags = flags;
6343 r.in.server = servername;
6344 r.in.level = level;
6345 r.in.buffer = NULL;
6346 r.in.offered = 0;
6347 r.out.needed = &needed;
6348 r.out.count = &count;
6349 r.out.info = &info;
6351 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6352 r.in.server, r.in.level);
6354 torture_assert_ntstatus_ok(tctx,
6355 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6356 "EnumPrinters failed");
6357 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6358 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6359 r.in.buffer = &blob;
6360 r.in.offered = needed;
6361 torture_assert_ntstatus_ok(tctx,
6362 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6363 "EnumPrinters failed");
6366 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6368 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6370 if (count_p) {
6371 *count_p = count;
6373 if (info_p) {
6374 *info_p = info;
6377 return true;
6380 static const char *get_short_printername(struct torture_context *tctx,
6381 const char *name)
6383 const char *short_name;
6385 if (name[0] == '\\' && name[1] == '\\') {
6386 name += 2;
6387 short_name = strchr(name, '\\');
6388 if (short_name) {
6389 return talloc_strdup(tctx, short_name+1);
6393 return name;
6396 static const char *get_full_printername(struct torture_context *tctx,
6397 const char *name)
6399 const char *full_name = talloc_strdup(tctx, name);
6400 char *p;
6402 if (name && name[0] == '\\' && name[1] == '\\') {
6403 name += 2;
6404 p = strchr(name, '\\');
6405 if (p) {
6406 return full_name;
6410 return NULL;
6413 static bool test_OnePrinter_servername(struct torture_context *tctx,
6414 struct dcerpc_pipe *p,
6415 struct dcerpc_binding_handle *b,
6416 const char *servername,
6417 const char *printername)
6419 union spoolss_PrinterInfo info;
6420 const char *short_name = get_short_printername(tctx, printername);
6421 const char *full_name = get_full_printername(tctx, printername);
6423 if (short_name) {
6424 struct policy_handle handle;
6425 torture_assert(tctx,
6426 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6427 "failed to open printer");
6429 torture_assert(tctx,
6430 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6431 "failed to get printer info");
6433 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6434 "unexpected servername");
6435 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6436 "unexpected printername");
6438 if (info.info2.devmode) {
6439 const char *expected_devicename;
6440 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6441 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6442 "unexpected devicemode devicename");
6445 torture_assert(tctx,
6446 test_ClosePrinter(tctx, b, &handle),
6447 "failed to close printer");
6450 if (full_name) {
6451 struct policy_handle handle;
6453 torture_assert(tctx,
6454 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6455 "failed to open printer");
6457 torture_assert(tctx,
6458 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6459 "failed to get printer info");
6461 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6462 "unexpected servername");
6463 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6464 "unexpected printername");
6466 if (info.info2.devmode) {
6467 const char *expected_devicename;
6468 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6469 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6470 "unexpected devicemode devicename");
6473 torture_assert(tctx,
6474 test_ClosePrinter(tctx, b, &handle),
6475 "failed to close printer");
6478 return true;
6481 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6482 void *private_data)
6484 struct test_spoolss_context *ctx =
6485 talloc_get_type_abort(private_data, struct test_spoolss_context);
6486 int i;
6487 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6488 struct dcerpc_binding_handle *b = p->binding_handle;
6489 uint32_t count;
6490 union spoolss_PrinterInfo *info;
6491 const char *servername;
6492 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6494 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6496 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6498 torture_assert(tctx,
6499 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6500 "failed to enumerate printers");
6502 for (i=0; i < count; i++) {
6504 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6505 "unexpected servername");
6507 torture_assert(tctx,
6508 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6509 "failed to check printer");
6512 servername = "";
6514 torture_assert(tctx,
6515 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6516 "failed to enumerate printers");
6518 for (i=0; i < count; i++) {
6520 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6521 "unexpected servername");
6523 torture_assert(tctx,
6524 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6525 "failed to check printer");
6529 return true;
6533 static bool test_GetPrinterDriver(struct torture_context *tctx,
6534 struct dcerpc_binding_handle *b,
6535 struct policy_handle *handle,
6536 const char *driver_name)
6538 struct spoolss_GetPrinterDriver r;
6539 uint32_t needed;
6541 r.in.handle = handle;
6542 r.in.architecture = "W32X86";
6543 r.in.level = 1;
6544 r.in.buffer = NULL;
6545 r.in.offered = 0;
6546 r.out.needed = &needed;
6548 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6550 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6551 "failed to call GetPrinterDriver");
6552 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6553 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6554 r.in.buffer = &blob;
6555 r.in.offered = needed;
6556 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6557 "failed to call GetPrinterDriver");
6560 torture_assert_werr_ok(tctx, r.out.result,
6561 "failed to call GetPrinterDriver");
6563 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6565 return true;
6568 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6569 struct dcerpc_binding_handle *b,
6570 struct policy_handle *handle,
6571 const char *driver_name,
6572 const char *architecture,
6573 uint32_t level,
6574 uint32_t client_major_version,
6575 uint32_t client_minor_version,
6576 union spoolss_DriverInfo *info_p,
6577 WERROR *result_p)
6580 struct spoolss_GetPrinterDriver2 r;
6581 uint32_t needed;
6582 uint32_t server_major_version;
6583 uint32_t server_minor_version;
6585 r.in.handle = handle;
6586 r.in.architecture = architecture;
6587 r.in.client_major_version = client_major_version;
6588 r.in.client_minor_version = client_minor_version;
6589 r.in.buffer = NULL;
6590 r.in.offered = 0;
6591 r.in.level = level;
6592 r.out.needed = &needed;
6593 r.out.server_major_version = &server_major_version;
6594 r.out.server_minor_version = &server_minor_version;
6596 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6597 driver_name, r.in.level);
6599 torture_assert_ntstatus_ok(tctx,
6600 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6601 "failed to call GetPrinterDriver2");
6602 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6603 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6604 r.in.buffer = &blob;
6605 r.in.offered = needed;
6606 torture_assert_ntstatus_ok(tctx,
6607 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6608 "failed to call GetPrinterDriver2");
6611 if (result_p) {
6612 *result_p = r.out.result;
6615 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6616 switch (r.in.level) {
6617 case 101:
6618 case 8:
6619 torture_comment(tctx,
6620 "level %d not implemented, not considering as an error\n",
6621 r.in.level);
6622 return true;
6623 default:
6624 break;
6628 torture_assert_werr_ok(tctx, r.out.result,
6629 "failed to call GetPrinterDriver2");
6631 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6633 if (info_p) {
6634 *info_p = *r.out.info;
6637 return true;
6640 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6641 struct dcerpc_binding_handle *b,
6642 struct policy_handle *handle,
6643 const char *driver_name,
6644 const char *architecture)
6646 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6647 int i;
6650 for (i=0;i<ARRAY_SIZE(levels);i++) {
6652 torture_assert(tctx,
6653 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6654 "");
6657 return true;
6660 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6661 void *private_data)
6663 struct test_spoolss_context *ctx =
6664 talloc_get_type_abort(private_data, struct test_spoolss_context);
6665 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6666 int i;
6667 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6668 struct dcerpc_binding_handle *b = p->binding_handle;
6669 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6671 for (i=0;i<ARRAY_SIZE(levels);i++) {
6673 uint32_t count;
6674 union spoolss_DriverInfo *info;
6676 torture_assert(tctx,
6677 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6678 "failed to enumerate drivers");
6680 if (!info) {
6681 torture_comment(tctx, "No printer drivers returned\n");
6682 break;
6686 return true;
6689 static bool test_DeletePrinter(struct torture_context *tctx,
6690 struct dcerpc_binding_handle *b,
6691 struct policy_handle *handle)
6693 struct spoolss_DeletePrinter r;
6695 torture_comment(tctx, "Testing DeletePrinter\n");
6697 r.in.handle = handle;
6699 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6700 "failed to delete printer");
6701 torture_assert_werr_ok(tctx, r.out.result,
6702 "failed to delete printer");
6704 return true;
6707 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6708 struct dcerpc_binding_handle *b,
6709 uint32_t flags,
6710 uint32_t level,
6711 const char *name,
6712 bool *found)
6714 struct spoolss_EnumPrinters e;
6715 uint32_t count;
6716 union spoolss_PrinterInfo *info;
6717 uint32_t needed;
6718 int i;
6720 *found = false;
6722 e.in.flags = flags;
6723 e.in.server = NULL;
6724 e.in.level = level;
6725 e.in.buffer = NULL;
6726 e.in.offered = 0;
6727 e.out.count = &count;
6728 e.out.info = &info;
6729 e.out.needed = &needed;
6731 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6732 "failed to enum printers");
6734 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6735 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6736 e.in.buffer = &blob;
6737 e.in.offered = needed;
6739 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6740 "failed to enum printers");
6743 torture_assert_werr_ok(tctx, e.out.result,
6744 "failed to enum printers");
6746 for (i=0; i < count; i++) {
6748 const char *current = NULL;
6749 const char *q;
6751 switch (level) {
6752 case 1:
6753 current = info[i].info1.name;
6754 break;
6757 if (strequal(current, name)) {
6758 *found = true;
6759 break;
6762 q = strrchr(current, '\\');
6763 if (q) {
6764 if (!e.in.server) {
6765 torture_warning(tctx,
6766 "server returns printername %s incl. servername although we did not set servername", current);
6768 q++;
6769 if (strequal(q, name)) {
6770 *found = true;
6771 break;
6776 return true;
6779 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6780 struct dcerpc_pipe *p,
6781 const char *printername,
6782 bool ex)
6784 WERROR result;
6785 struct spoolss_AddPrinter r;
6786 struct spoolss_AddPrinterEx rex;
6787 struct spoolss_SetPrinterInfoCtr info_ctr;
6788 struct spoolss_SetPrinterInfo1 info1;
6789 struct spoolss_DevmodeContainer devmode_ctr;
6790 struct sec_desc_buf secdesc_ctr;
6791 struct spoolss_UserLevelCtr userlevel_ctr;
6792 struct policy_handle handle;
6793 bool found = false;
6794 struct dcerpc_binding_handle *b = p->binding_handle;
6796 ZERO_STRUCT(devmode_ctr);
6797 ZERO_STRUCT(secdesc_ctr);
6798 ZERO_STRUCT(userlevel_ctr);
6799 ZERO_STRUCT(info1);
6801 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6802 ex ? "Ex":"", printername);
6804 /* try to add printer to wellknown printer list (level 1) */
6806 userlevel_ctr.level = 1;
6808 info_ctr.info.info1 = &info1;
6809 info_ctr.level = 1;
6811 rex.in.server = NULL;
6812 rex.in.info_ctr = &info_ctr;
6813 rex.in.devmode_ctr = &devmode_ctr;
6814 rex.in.secdesc_ctr = &secdesc_ctr;
6815 rex.in.userlevel_ctr = &userlevel_ctr;
6816 rex.out.handle = &handle;
6818 r.in.server = NULL;
6819 r.in.info_ctr = &info_ctr;
6820 r.in.devmode_ctr = &devmode_ctr;
6821 r.in.secdesc_ctr = &secdesc_ctr;
6822 r.out.handle = &handle;
6824 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6825 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6826 "failed to add printer");
6827 result = ex ? rex.out.result : r.out.result;
6828 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6829 "unexpected result code");
6831 info1.name = printername;
6832 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6834 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6835 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6836 "failed to add printer");
6837 result = ex ? rex.out.result : r.out.result;
6838 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6839 "unexpected result code");
6841 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6842 better do a real check to see the printer is really there */
6844 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6845 PRINTER_ENUM_NETWORK, 1,
6846 printername,
6847 &found),
6848 "failed to enum printers");
6850 torture_assert(tctx, found, "failed to find newly added printer");
6852 info1.flags = 0;
6854 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6855 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6856 "failed to add printer");
6857 result = ex ? rex.out.result : r.out.result;
6858 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6859 "unexpected result code");
6861 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6862 better do a real check to see the printer has really been removed
6863 from the well known printer list */
6865 found = false;
6867 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6868 PRINTER_ENUM_NETWORK, 1,
6869 printername,
6870 &found),
6871 "failed to enum printers");
6872 #if 0
6873 torture_assert(tctx, !found, "printer still in well known printer list");
6874 #endif
6875 return true;
6878 static bool test_AddPrinter_normal(struct torture_context *tctx,
6879 struct dcerpc_pipe *p,
6880 struct policy_handle *handle_p,
6881 const char *printername,
6882 const char *drivername,
6883 const char *portname,
6884 struct spoolss_DeviceMode *devmode,
6885 bool ex)
6887 WERROR result;
6888 struct spoolss_AddPrinter r;
6889 struct spoolss_AddPrinterEx rex;
6890 struct spoolss_SetPrinterInfoCtr info_ctr;
6891 struct spoolss_SetPrinterInfo2 info2;
6892 struct spoolss_DevmodeContainer devmode_ctr;
6893 struct sec_desc_buf secdesc_ctr;
6894 struct spoolss_UserLevelCtr userlevel_ctr;
6895 struct policy_handle handle;
6896 bool found = false;
6897 bool existing_printer_deleted = false;
6898 struct dcerpc_binding_handle *b = p->binding_handle;
6900 ZERO_STRUCT(devmode_ctr);
6901 ZERO_STRUCT(secdesc_ctr);
6902 ZERO_STRUCT(userlevel_ctr);
6904 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6905 ex ? "Ex":"", printername);
6907 devmode_ctr.devmode = devmode;
6909 userlevel_ctr.level = 1;
6911 rex.in.server = NULL;
6912 rex.in.info_ctr = &info_ctr;
6913 rex.in.devmode_ctr = &devmode_ctr;
6914 rex.in.secdesc_ctr = &secdesc_ctr;
6915 rex.in.userlevel_ctr = &userlevel_ctr;
6916 rex.out.handle = &handle;
6918 r.in.server = NULL;
6919 r.in.info_ctr = &info_ctr;
6920 r.in.devmode_ctr = &devmode_ctr;
6921 r.in.secdesc_ctr = &secdesc_ctr;
6922 r.out.handle = &handle;
6924 again:
6926 /* try to add printer to printer list (level 2) */
6928 ZERO_STRUCT(info2);
6930 info_ctr.info.info2 = &info2;
6931 info_ctr.level = 2;
6933 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6934 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6935 "failed to add printer");
6936 result = ex ? rex.out.result : r.out.result;
6937 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6938 "unexpected result code");
6940 info2.printername = printername;
6942 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6943 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6944 "failed to add printer");
6945 result = ex ? rex.out.result : r.out.result;
6947 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6948 struct policy_handle printer_handle;
6950 if (existing_printer_deleted) {
6951 torture_fail(tctx, "already deleted printer still existing?");
6954 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6955 "failed to open printer handle");
6957 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6958 "failed to delete printer");
6960 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6961 "failed to close server handle");
6963 existing_printer_deleted = true;
6965 goto again;
6968 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6969 "unexpected result code");
6971 info2.portname = portname;
6973 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6974 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6975 "failed to add printer");
6976 result = ex ? rex.out.result : r.out.result;
6977 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6978 "unexpected result code");
6980 info2.drivername = drivername;
6982 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6983 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6984 "failed to add printer");
6985 result = ex ? rex.out.result : r.out.result;
6987 /* w2k8r2 allows to add printer w/o defining printprocessor */
6989 if (!W_ERROR_IS_OK(result)) {
6990 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6991 "unexpected result code");
6993 info2.printprocessor = "winprint";
6995 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6996 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6997 "failed to add printer");
6998 result = ex ? rex.out.result : r.out.result;
6999 torture_assert_werr_ok(tctx, result,
7000 "failed to add printer");
7003 *handle_p = handle;
7005 /* we are paranoid, really check if the printer is there now */
7007 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7008 PRINTER_ENUM_LOCAL, 1,
7009 printername,
7010 &found),
7011 "failed to enum printers");
7012 torture_assert(tctx, found, "failed to find newly added printer");
7014 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7015 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7016 "failed to add printer");
7017 result = ex ? rex.out.result : r.out.result;
7018 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7019 "unexpected result code");
7021 return true;
7024 static bool test_printer_info(struct torture_context *tctx,
7025 void *private_data)
7027 struct torture_printer_context *t =
7028 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7029 struct dcerpc_pipe *p = t->spoolss_pipe;
7030 struct dcerpc_binding_handle *b = p->binding_handle;
7032 bool ret = true;
7034 if (torture_setting_bool(tctx, "samba3", false)) {
7035 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7038 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7039 ret = false;
7042 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7043 ret = false;
7046 return ret;
7049 static bool test_EnumPrinterKey(struct torture_context *tctx,
7050 struct dcerpc_binding_handle *b,
7051 struct policy_handle *handle,
7052 const char *key_name,
7053 const char ***array)
7055 struct spoolss_EnumPrinterKey r;
7056 uint32_t needed = 0;
7057 union spoolss_KeyNames key_buffer;
7058 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7059 uint32_t _ndr_size;
7060 int i;
7062 r.in.handle = handle;
7063 r.in.key_name = key_name;
7064 r.out.key_buffer = &key_buffer;
7065 r.out.needed = &needed;
7066 r.out._ndr_size = &_ndr_size;
7068 for (i=0; i < ARRAY_SIZE(offered); i++) {
7070 if (offered[i] < 0 && needed) {
7071 if (needed <= 4) {
7072 continue;
7074 r.in.offered = needed + offered[i];
7075 } else {
7076 r.in.offered = offered[i];
7079 ZERO_STRUCT(key_buffer);
7081 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7083 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7084 "failed to call EnumPrinterKey");
7085 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7087 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7088 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7089 _ndr_size, r.in.offered/2));
7091 r.in.offered = needed;
7092 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7093 "failed to call EnumPrinterKey");
7096 if (offered[i] > 0) {
7097 torture_assert_werr_ok(tctx, r.out.result,
7098 "failed to call EnumPrinterKey");
7101 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7102 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7103 _ndr_size, r.in.offered/2));
7105 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7106 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7108 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7109 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7111 if (key_buffer.string_array) {
7112 uint32_t calc_needed = 0;
7113 int s;
7114 for (s=0; key_buffer.string_array[s]; s++) {
7115 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7117 if (!key_buffer.string_array[0]) {
7118 calc_needed += 2;
7120 calc_needed += 2;
7122 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7123 "EnumPrinterKey unexpected size");
7127 if (array) {
7128 *array = key_buffer.string_array;
7131 return true;
7134 bool test_printer_all_keys(struct torture_context *tctx,
7135 struct dcerpc_binding_handle *b,
7136 struct policy_handle *handle)
7138 const char **key_array = NULL;
7139 int i;
7141 torture_comment(tctx, "Testing Printer Keys\n");
7143 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7144 "failed to call test_EnumPrinterKey");
7146 for (i=0; key_array && key_array[i]; i++) {
7147 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7148 "failed to call test_EnumPrinterKey");
7150 for (i=0; key_array && key_array[i]; i++) {
7151 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7152 "failed to call test_EnumPrinterDataEx");
7155 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7157 return true;
7160 static bool test_openprinter_wrap(struct torture_context *tctx,
7161 void *private_data)
7163 struct torture_printer_context *t =
7164 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7165 struct dcerpc_pipe *p = t->spoolss_pipe;
7166 struct dcerpc_binding_handle *b = p->binding_handle;
7167 const char *printername = t->info2.printername;
7169 return test_openprinter(tctx, b, printername);
7172 static bool test_csetprinter(struct torture_context *tctx,
7173 void *private_data)
7175 struct torture_printer_context *t =
7176 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7177 struct dcerpc_pipe *p = t->spoolss_pipe;
7179 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7180 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7181 const char *portname = t->info2.portname;
7183 union spoolss_PrinterInfo info;
7184 struct policy_handle new_handle, new_handle2;
7185 struct dcerpc_binding_handle *b = p->binding_handle;
7187 torture_comment(tctx, "Testing c_setprinter\n");
7189 torture_assert(tctx,
7190 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7191 "failed to get level 0 printer info");
7192 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7193 info.info0.c_setprinter);
7195 /* check if c_setprinter on 1st handle increases after a printer has
7196 * been added */
7198 torture_assert(tctx,
7199 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7200 "failed to add new printer");
7201 torture_assert(tctx,
7202 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7203 "failed to get level 0 printer info");
7204 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7205 info.info0.c_setprinter);
7207 /* check if c_setprinter on new handle increases after a printer has
7208 * been added */
7210 torture_assert(tctx,
7211 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7212 "failed to get level 0 printer info");
7213 torture_comment(tctx, "csetprinter on created handle: %d\n",
7214 info.info0.c_setprinter);
7216 /* open the new printer and check if c_setprinter increases */
7218 torture_assert(tctx,
7219 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7220 "failed to open created printer");
7221 torture_assert(tctx,
7222 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7223 "failed to get level 0 printer info");
7224 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7225 info.info0.c_setprinter);
7227 /* cleanup */
7229 torture_assert(tctx,
7230 test_ClosePrinter(tctx, b, &new_handle2),
7231 "failed to close printer");
7232 torture_assert(tctx,
7233 test_DeletePrinter(tctx, b, &new_handle),
7234 "failed to delete new printer");
7236 return true;
7239 static bool compose_local_driver_directory(struct torture_context *tctx,
7240 const char *environment,
7241 const char *local_dir,
7242 const char **path)
7244 char *p;
7246 p = strrchr(local_dir, '/');
7247 if (!p) {
7248 return NULL;
7250 p++;
7252 if (strequal(environment, "Windows x64")) {
7253 if (!strequal(p, "x64")) {
7254 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7256 } else if (strequal(environment, "Windows NT x86")) {
7257 if (!strequal(p, "i386")) {
7258 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7260 } else {
7261 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7264 return true;
7267 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7268 const char *devicename)
7270 struct spoolss_DeviceMode *r;
7272 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7273 if (r == NULL) {
7274 return NULL;
7277 r->devicename = talloc_strdup(r, devicename);
7278 r->specversion = DMSPEC_NT4_AND_ABOVE;
7279 r->driverversion = 0x0600;
7280 r->size = 0x00dc;
7281 r->__driverextra_length = 0;
7282 r->fields = DEVMODE_FORMNAME |
7283 DEVMODE_TTOPTION |
7284 DEVMODE_PRINTQUALITY |
7285 DEVMODE_DEFAULTSOURCE |
7286 DEVMODE_COPIES |
7287 DEVMODE_SCALE |
7288 DEVMODE_PAPERSIZE |
7289 DEVMODE_ORIENTATION;
7290 r->orientation = DMORIENT_PORTRAIT;
7291 r->papersize = DMPAPER_LETTER;
7292 r->paperlength = 0;
7293 r->paperwidth = 0;
7294 r->scale = 100;
7295 r->copies = 55;
7296 r->defaultsource = DMBIN_FORMSOURCE;
7297 r->printquality = DMRES_HIGH;
7298 r->color = DMRES_MONOCHROME;
7299 r->duplex = DMDUP_SIMPLEX;
7300 r->yresolution = 0;
7301 r->ttoption = DMTT_SUBDEV;
7302 r->collate = DMCOLLATE_FALSE;
7303 r->formname = talloc_strdup(r, "Letter");
7305 return r;
7308 static bool test_architecture_buffer(struct torture_context *tctx,
7309 void *private_data)
7311 struct test_spoolss_context *ctx =
7312 talloc_get_type_abort(private_data, struct test_spoolss_context);
7314 struct spoolss_OpenPrinterEx r;
7315 struct spoolss_UserLevel1 u1;
7316 struct policy_handle handle;
7317 uint32_t architectures[] = {
7318 PROCESSOR_ARCHITECTURE_INTEL,
7319 PROCESSOR_ARCHITECTURE_IA64,
7320 PROCESSOR_ARCHITECTURE_AMD64
7322 uint32_t needed[3];
7323 int i;
7324 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7325 struct dcerpc_binding_handle *b = p->binding_handle;
7327 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7329 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7331 u1.size = 0;
7332 u1.client = NULL;
7333 u1.user = NULL;
7334 u1.build = 0;
7335 u1.major = 3;
7336 u1.minor = 0;
7337 u1.processor = architectures[i];
7339 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7340 r.in.datatype = NULL;
7341 r.in.devmode_ctr.devmode= NULL;
7342 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7343 r.in.userlevel_ctr.level = 1;
7344 r.in.userlevel_ctr.user_info.level1 = &u1;
7345 r.out.handle = &handle;
7347 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7348 torture_assert_werr_ok(tctx, r.out.result, "");
7351 struct spoolss_EnumPrinters e;
7352 uint32_t count;
7353 union spoolss_PrinterInfo *info;
7355 e.in.flags = PRINTER_ENUM_LOCAL;
7356 e.in.server = NULL;
7357 e.in.level = 2;
7358 e.in.buffer = NULL;
7359 e.in.offered = 0;
7360 e.out.count = &count;
7361 e.out.info = &info;
7362 e.out.needed = &needed[i];
7364 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7365 #if 0
7366 torture_comment(tctx, "needed was %d\n", needed[i]);
7367 #endif
7370 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7373 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7374 if (needed[i-1] != needed[i]) {
7375 torture_fail(tctx,
7376 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7377 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7381 return true;
7384 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7385 void *private_data)
7387 struct test_spoolss_context *ctx =
7388 talloc_get_type_abort(private_data, struct test_spoolss_context);
7389 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7390 struct dcerpc_binding_handle *b = p->binding_handle;
7392 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7395 static bool test_PrintServer_Forms(struct torture_context *tctx,
7396 void *private_data)
7398 struct test_spoolss_context *ctx =
7399 talloc_get_type_abort(private_data, struct test_spoolss_context);
7400 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7401 struct dcerpc_binding_handle *b = p->binding_handle;
7403 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7406 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7407 void *private_data)
7409 struct test_spoolss_context *ctx =
7410 talloc_get_type_abort(private_data, struct test_spoolss_context);
7411 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7412 struct dcerpc_binding_handle *b = p->binding_handle;
7414 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7417 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7419 NTSTATUS status;
7421 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7423 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7425 torture_assert(tctx,
7426 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7427 "failed to open printserver");
7428 torture_assert(tctx,
7429 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7430 "failed to get environment");
7432 return true;
7435 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7437 struct test_spoolss_context *t;
7439 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7441 return torture_rpc_spoolss_setup_common(tctx, t);
7444 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7446 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7448 return true;
7451 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7453 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7454 bool ret;
7456 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7457 talloc_free(t);
7459 return ret;
7462 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7464 struct dcerpc_pipe *p;
7465 struct dcerpc_binding_handle *b;
7466 const char *server_name_slash;
7467 const char *driver_name;
7468 const char *printer_name;
7469 const char *port_name;
7471 torture_assert_ntstatus_ok(tctx,
7472 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7473 "Error connecting to server");
7475 p = t->spoolss_pipe;
7476 b = p->binding_handle;
7477 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7479 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7480 t->driver.info8.driver_name = TORTURE_DRIVER;
7481 t->driver.info8.driver_path = "pscript5.dll";
7482 t->driver.info8.data_file = "cups6.ppd";
7483 t->driver.info8.config_file = "ps5ui.dll";
7484 t->driver.info8.help_file = "pscript.hlp";
7485 t->driver.info8.default_datatype = "RAW";
7486 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7487 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7488 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7489 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7490 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7491 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7492 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7493 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7494 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7495 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7497 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7499 t->info2.drivername = "Microsoft XPS Document Writer";
7500 t->info2.portname = "LPT1:";
7502 printer_name = t->info2.printername;
7503 port_name = t->info2.portname;
7505 torture_assert(tctx,
7506 fillup_printserver_info(tctx, p, &t->driver),
7507 "failed to fillup printserver info");
7509 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7511 torture_assert(tctx,
7512 compose_local_driver_directory(tctx, t->driver.remote.environment,
7513 t->driver.local.driver_directory,
7514 &t->driver.local.driver_directory),
7515 "failed to compose local driver directory");
7517 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7518 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7519 t->info2.drivername, t->driver.remote.environment);
7520 t->have_driver = true;
7521 goto try_add;
7524 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7525 t->info2.drivername, t->driver.remote.environment);
7526 torture_comment(tctx, "trying to upload own driver\n");
7528 if (!directory_exist(t->driver.local.driver_directory)) {
7529 torture_warning(tctx, "no local driver is available!");
7530 t->have_driver = false;
7531 goto try_add;
7534 torture_assert(tctx,
7535 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7536 "failed to upload printer driver");
7538 torture_assert(tctx,
7539 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7540 "failed to add driver");
7542 t->added_driver = true;
7543 t->have_driver = true;
7545 try_add:
7546 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7548 if (t->wellknown) {
7549 torture_assert(tctx,
7550 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7551 "failed to add wellknown printer");
7552 } else {
7553 torture_assert(tctx,
7554 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7555 "failed to add printer");
7558 return true;
7561 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7563 struct torture_printer_context *t;
7565 *data = t = talloc_zero(tctx, struct torture_printer_context);
7567 t->ex = false;
7568 t->wellknown = false;
7569 t->info2.printername = TORTURE_PRINTER;
7570 t->devmode = NULL;
7572 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7575 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7577 struct torture_printer_context *t;
7579 *data = t = talloc_zero(tctx, struct torture_printer_context);
7581 t->ex = true;
7582 t->wellknown = false;
7583 t->info2.printername = TORTURE_PRINTER_EX;
7584 t->devmode = NULL;
7586 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7589 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7591 struct torture_printer_context *t;
7593 *data = t = talloc_zero(tctx, struct torture_printer_context);
7595 t->ex = false;
7596 t->wellknown = true;
7597 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7598 t->devmode = NULL;
7600 /* FIXME */
7601 if (t->wellknown) {
7602 torture_skip(tctx, "skipping AddPrinter level 1");
7605 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7608 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7610 struct torture_printer_context *t;
7612 *data = t = talloc_zero(tctx, struct torture_printer_context);
7614 t->ex = true;
7615 t->wellknown = true;
7616 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7617 t->devmode = NULL;
7619 /* FIXME */
7620 if (t->wellknown) {
7621 torture_skip(tctx, "skipping AddPrinterEx level 1");
7624 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7627 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7629 struct torture_printer_context *t;
7631 *data = t = talloc_zero(tctx, struct torture_printer_context);
7633 t->ex = true;
7634 t->wellknown = false;
7635 t->info2.printername = TORTURE_PRINTER_EX;
7636 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7638 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7641 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7643 bool found = false;
7644 struct dcerpc_pipe *p = t->spoolss_pipe;
7645 struct dcerpc_binding_handle *b;
7646 const char *printer_name = t->info2.printername;
7648 if (t->added_driver) {
7649 torture_assert(tctx,
7650 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7651 "failed to remove printer driver");
7654 if (p && !t->wellknown) {
7655 b = p->binding_handle;
7657 torture_assert(tctx,
7658 test_DeletePrinter(tctx, b, &t->handle),
7659 "failed to delete printer");
7661 torture_assert(tctx,
7662 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7663 printer_name, &found),
7664 "failed to enumerate printers");
7666 torture_assert(tctx, !found, "deleted printer still there");
7669 return true;
7672 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7674 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7675 bool ret;
7677 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7678 talloc_free(t);
7680 return ret;
7683 static bool test_print_test(struct torture_context *tctx,
7684 void *private_data)
7686 struct torture_printer_context *t =
7687 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7688 struct dcerpc_pipe *p = t->spoolss_pipe;
7689 struct dcerpc_binding_handle *b = p->binding_handle;
7691 torture_assert(tctx,
7692 test_PausePrinter(tctx, b, &t->handle),
7693 "failed to pause printer");
7695 torture_assert(tctx,
7696 test_DoPrintTest(tctx, b, &t->handle),
7697 "failed to do print test");
7699 torture_assert(tctx,
7700 test_ResumePrinter(tctx, b, &t->handle),
7701 "failed to resume printer");
7703 return true;
7706 static bool test_print_test_extended(struct torture_context *tctx,
7707 void *private_data)
7709 struct torture_printer_context *t =
7710 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7711 struct dcerpc_pipe *p = t->spoolss_pipe;
7712 struct dcerpc_binding_handle *b = p->binding_handle;
7713 bool ret = true;
7715 torture_assert(tctx,
7716 test_PausePrinter(tctx, b, &t->handle),
7717 "failed to pause printer");
7719 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7720 if (ret == false) {
7721 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7722 if (torture_setting_bool(tctx, "samba3", false)) {
7723 torture_comment(tctx, "non-critical for samba3\n");
7724 ret = true;
7725 tctx->last_result = TORTURE_SKIP;
7729 torture_assert(tctx,
7730 test_ResumePrinter(tctx, b, &t->handle),
7731 "failed to resume printer");
7733 return ret;
7736 /* use smbd file IO to spool a print job */
7737 static bool test_print_test_smbd(struct torture_context *tctx,
7738 void *private_data)
7740 struct torture_printer_context *t =
7741 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7742 struct dcerpc_pipe *p = t->spoolss_pipe;
7743 struct dcerpc_binding_handle *b = p->binding_handle;
7744 NTSTATUS status;
7745 uint32_t count;
7746 union spoolss_JobInfo *info = NULL;
7747 int i;
7749 struct smb2_tree *tree;
7750 struct smb2_handle job_h;
7751 struct cli_credentials *credentials = cmdline_credentials;
7752 struct smbcli_options options;
7753 TALLOC_CTX *mem_ctx = talloc_new(tctx);
7755 * Do not test against the dynamically added printers, printing via
7756 * smbd means that a different spoolss process may handle the
7757 * OpenPrinter request to the one that handled the AddPrinter request.
7758 * This currently leads to an ugly race condition where one process
7759 * sees the new printer and one doesn't.
7761 const char *share = TORTURE_PRINTER_STATIC1;
7763 torture_comment(tctx, "Testing smbd job spooling\n");
7764 lpcfg_smbcli_options(tctx->lp_ctx, &options);
7766 status = smb2_connect_ext(mem_ctx,
7767 torture_setting_string(tctx, "host", NULL),
7768 lpcfg_smb_ports(tctx->lp_ctx),
7769 share,
7770 lpcfg_resolve_context(tctx->lp_ctx),
7771 credentials,
7773 &tree,
7774 tctx->ev,
7775 &options,
7776 lpcfg_socket_options(tctx->lp_ctx),
7777 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
7778 if (!NT_STATUS_IS_OK(status)) {
7779 printf("Failed to connect to SMB2 printer %s - %s\n",
7780 share, nt_errstr(status));
7781 return false;
7784 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
7785 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
7787 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
7788 sizeof("exciting print job data"));
7789 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
7791 /* check back end spoolss job was created */
7792 torture_assert(tctx,
7793 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
7794 "EnumJobs level 1 failed");
7796 for (i = 0; i < count; i++) {
7797 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
7798 break;
7801 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
7803 status = smb2_util_close(tree, job_h);
7804 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
7806 /* disconnect from printer share */
7807 talloc_free(mem_ctx);
7809 return true;
7812 static bool test_printer_sd(struct torture_context *tctx,
7813 void *private_data)
7815 struct torture_printer_context *t =
7816 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7817 struct dcerpc_pipe *p = t->spoolss_pipe;
7818 struct dcerpc_binding_handle *b = p->binding_handle;
7820 torture_assert(tctx,
7821 test_PrinterInfo_SD(tctx, b, &t->handle),
7822 "failed to test security descriptors");
7824 return true;
7827 static bool test_printer_dm(struct torture_context *tctx,
7828 void *private_data)
7830 struct torture_printer_context *t =
7831 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7832 struct dcerpc_pipe *p = t->spoolss_pipe;
7834 torture_assert(tctx,
7835 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7836 "failed to test devicemodes");
7838 return true;
7841 static bool test_printer_info_winreg(struct torture_context *tctx,
7842 void *private_data)
7844 struct torture_printer_context *t =
7845 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7846 struct dcerpc_pipe *p = t->spoolss_pipe;
7848 torture_assert(tctx,
7849 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7850 "failed to test printer info winreg");
7852 return true;
7855 static bool test_printer_change_id(struct torture_context *tctx,
7856 void *private_data)
7858 struct torture_printer_context *t =
7859 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7860 struct dcerpc_pipe *p = t->spoolss_pipe;
7862 torture_assert(tctx,
7863 test_ChangeID(tctx, p, &t->handle),
7864 "failed to test change id");
7866 return true;
7869 static bool test_printer_keys(struct torture_context *tctx,
7870 void *private_data)
7872 struct torture_printer_context *t =
7873 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7874 struct dcerpc_pipe *p = t->spoolss_pipe;
7875 struct dcerpc_binding_handle *b = p->binding_handle;
7877 torture_assert(tctx,
7878 test_printer_all_keys(tctx, b, &t->handle),
7879 "failed to test printer keys");
7881 return true;
7884 static bool test_printer_data_consistency(struct torture_context *tctx,
7885 void *private_data)
7887 struct torture_printer_context *t =
7888 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7889 struct dcerpc_pipe *p = t->spoolss_pipe;
7891 torture_assert(tctx,
7892 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7893 "failed to test printer data consistency");
7895 return true;
7898 static bool test_printer_data_keys(struct torture_context *tctx,
7899 void *private_data)
7901 struct torture_printer_context *t =
7902 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7903 struct dcerpc_pipe *p = t->spoolss_pipe;
7905 torture_assert(tctx,
7906 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7907 "failed to test printer data keys");
7909 return true;
7912 static bool test_printer_data_values(struct torture_context *tctx,
7913 void *private_data)
7915 struct torture_printer_context *t =
7916 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7917 struct dcerpc_pipe *p = t->spoolss_pipe;
7919 torture_assert(tctx,
7920 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7921 "failed to test printer data values");
7923 return true;
7926 static bool test_printer_data_set(struct torture_context *tctx,
7927 void *private_data)
7929 struct torture_printer_context *t =
7930 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7931 struct dcerpc_pipe *p = t->spoolss_pipe;
7933 torture_assert(tctx,
7934 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7935 "failed to test printer data set");
7937 return true;
7940 static bool test_printer_data_winreg(struct torture_context *tctx,
7941 void *private_data)
7943 struct torture_printer_context *t =
7944 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7945 struct dcerpc_pipe *p = t->spoolss_pipe;
7947 torture_assert(tctx,
7948 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7949 "failed to test printer data winreg");
7951 return true;
7954 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7955 void *private_data)
7957 struct torture_printer_context *t =
7958 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7959 struct dcerpc_pipe *p = t->spoolss_pipe;
7961 torture_assert(tctx,
7962 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7963 "failed to test printer data winreg dsspooler");
7965 return true;
7968 static bool test_driver_info_winreg(struct torture_context *tctx,
7969 void *private_data)
7971 struct torture_printer_context *t =
7972 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7973 struct dcerpc_pipe *p = t->spoolss_pipe;
7974 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7976 if (!t->have_driver) {
7977 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7980 torture_assert(tctx,
7981 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7982 "failed to test driver info winreg");
7984 return true;
7987 void torture_tcase_printer(struct torture_tcase *tcase)
7989 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7990 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7991 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7992 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7993 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
7994 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7995 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7996 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7997 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7998 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7999 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8000 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8001 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8002 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8003 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8004 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8005 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8006 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8007 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8010 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8012 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8013 struct torture_tcase *tcase;
8015 tcase = torture_suite_add_tcase(suite, "addprinter");
8017 torture_tcase_set_fixture(tcase,
8018 torture_rpc_spoolss_printer_setup,
8019 torture_rpc_spoolss_printer_teardown);
8021 torture_tcase_printer(tcase);
8023 tcase = torture_suite_add_tcase(suite, "addprinterex");
8025 torture_tcase_set_fixture(tcase,
8026 torture_rpc_spoolss_printerex_setup,
8027 torture_rpc_spoolss_printer_teardown);
8029 torture_tcase_printer(tcase);
8031 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8033 torture_tcase_set_fixture(tcase,
8034 torture_rpc_spoolss_printerwkn_setup,
8035 torture_rpc_spoolss_printer_teardown);
8037 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8039 torture_tcase_set_fixture(tcase,
8040 torture_rpc_spoolss_printerexwkn_setup,
8041 torture_rpc_spoolss_printer_teardown);
8043 #if 0
8044 /* test is not correct */
8045 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8047 torture_tcase_set_fixture(tcase,
8048 torture_rpc_spoolss_printerdm_setup,
8049 torture_rpc_spoolss_printer_teardown);
8051 torture_tcase_printer(tcase);
8052 #endif
8053 return suite;
8056 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8058 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8059 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8061 torture_tcase_set_fixture(tcase,
8062 torture_rpc_spoolss_setup,
8063 torture_rpc_spoolss_teardown);
8065 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8066 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8067 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8068 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8069 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8070 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8071 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8072 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8073 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8074 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8075 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8076 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8077 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8078 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8079 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8080 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8081 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8082 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8083 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8084 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8086 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8088 return suite;
8091 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8092 struct dcerpc_binding_handle *b,
8093 const char *server,
8094 const char *environment,
8095 const char **dir_p)
8097 struct spoolss_GetPrinterDriverDirectory r;
8098 uint32_t needed;
8100 r.in.server = server;
8101 r.in.environment = environment;
8102 r.in.level = 1;
8103 r.in.buffer = NULL;
8104 r.in.offered = 0;
8105 r.out.needed = &needed;
8107 torture_assert_ntstatus_ok(tctx,
8108 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8109 "failed to query driver directory");
8111 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8112 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8113 r.in.buffer = &blob;
8114 r.in.offered = needed;
8116 torture_assert_ntstatus_ok(tctx,
8117 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8118 "failed to query driver directory");
8121 torture_assert_werr_ok(tctx, r.out.result,
8122 "failed to query driver directory");
8124 if (dir_p) {
8125 *dir_p = r.out.info->info1.directory_name;
8128 return true;
8131 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8133 if (info_ctr == NULL) {
8134 return NULL;
8137 switch (info_ctr->level) {
8138 case 1:
8139 return info_ctr->info.info1->driver_name;
8140 case 2:
8141 return info_ctr->info.info2->driver_name;
8142 case 3:
8143 return info_ctr->info.info3->driver_name;
8144 case 4:
8145 return info_ctr->info.info4->driver_name;
8146 case 6:
8147 return info_ctr->info.info6->driver_name;
8148 case 8:
8149 return info_ctr->info.info8->driver_name;
8150 default:
8151 return NULL;
8155 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8157 if (info_ctr == NULL) {
8158 return NULL;
8161 switch (info_ctr->level) {
8162 case 2:
8163 return info_ctr->info.info2->architecture;
8164 case 3:
8165 return info_ctr->info.info3->architecture;
8166 case 4:
8167 return info_ctr->info.info4->architecture;
8168 case 6:
8169 return info_ctr->info.info6->architecture;
8170 case 8:
8171 return info_ctr->info.info8->architecture;
8172 default:
8173 return NULL;
8178 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8179 struct dcerpc_binding_handle *b,
8180 const char *servername,
8181 struct spoolss_AddDriverInfoCtr *info_ctr,
8182 WERROR expected_result)
8184 struct spoolss_AddPrinterDriver r;
8185 const char *drivername = get_driver_from_info(info_ctr);
8186 const char *environment = get_environment_from_info(info_ctr);
8188 r.in.servername = servername;
8189 r.in.info_ctr = info_ctr;
8191 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8192 drivername, info_ctr->level, environment);
8194 torture_assert_ntstatus_ok(tctx,
8195 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8196 "spoolss_AddPrinterDriver failed");
8197 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8198 "spoolss_AddPrinterDriver failed with unexpected result");
8200 return true;
8204 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8205 struct dcerpc_binding_handle *b,
8206 const char *servername,
8207 struct spoolss_AddDriverInfoCtr *info_ctr,
8208 uint32_t flags,
8209 WERROR expected_result)
8211 struct spoolss_AddPrinterDriverEx r;
8212 const char *drivername = get_driver_from_info(info_ctr);
8213 const char *environment = get_environment_from_info(info_ctr);
8215 r.in.servername = servername;
8216 r.in.info_ctr = info_ctr;
8217 r.in.flags = flags;
8219 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8220 drivername, info_ctr->level, environment);
8222 torture_assert_ntstatus_ok(tctx,
8223 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8224 "AddPrinterDriverEx failed");
8225 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8226 "AddPrinterDriverEx failed with unexpected result");
8228 return true;
8231 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8232 if (path && strlen(path)) {\
8233 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8236 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8237 struct dcerpc_binding_handle *b,
8238 const char *server_name,
8239 struct spoolss_AddDriverInfo8 *r,
8240 uint32_t flags,
8241 bool ex,
8242 const char *remote_driver_dir)
8244 struct spoolss_AddDriverInfoCtr info_ctr;
8245 struct spoolss_AddDriverInfo1 info1;
8247 ZERO_STRUCT(info1);
8249 info_ctr.level = 1;
8250 info_ctr.info.info1 = &info1;
8252 if (ex) {
8253 torture_assert(tctx,
8254 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8255 "failed to test AddPrinterDriverEx level 1");
8256 } else {
8257 torture_assert(tctx,
8258 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8259 "failed to test AddPrinterDriver level 1");
8262 info1.driver_name = r->driver_name;
8264 if (ex) {
8265 torture_assert(tctx,
8266 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8267 "failed to test AddPrinterDriverEx level 1");
8268 } else {
8269 torture_assert(tctx,
8270 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8271 "failed to test AddPrinterDriver level 1");
8274 return true;
8277 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8278 struct dcerpc_binding_handle *b,
8279 const char *server_name,
8280 struct spoolss_AddDriverInfo8 *r,
8281 uint32_t flags,
8282 bool ex,
8283 const char *remote_driver_dir)
8285 struct spoolss_AddDriverInfoCtr info_ctr;
8286 struct spoolss_AddDriverInfo2 info2;
8287 union spoolss_DriverInfo info;
8289 ZERO_STRUCT(info2);
8291 info_ctr.level = 2;
8292 info_ctr.info.info2 = &info2;
8294 if (ex) {
8295 torture_assert(tctx,
8296 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8297 "failed to test AddPrinterDriverEx level 2");
8298 } else {
8299 torture_assert(tctx,
8300 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8301 "failed to test AddPrinterDriver level 2");
8304 info2.driver_name = r->driver_name;
8306 if (ex) {
8307 torture_assert(tctx,
8308 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8309 "failed to test AddPrinterDriverEx level 2");
8310 } else {
8311 torture_assert(tctx,
8312 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8313 "failed to test AddPrinterDriver level 2");
8316 info2.version = r->version;
8318 if (ex) {
8319 torture_assert(tctx,
8320 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8321 "failed to test AddPrinterDriverEx level 2");
8322 } else {
8323 torture_assert(tctx,
8324 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8325 "failed to test AddPrinterDriver level 2");
8328 info2.architecture = r->architecture;
8330 if (ex) {
8331 torture_assert(tctx,
8332 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8333 "failed to test AddPrinterDriverEx level 2");
8334 } else {
8335 torture_assert(tctx,
8336 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8337 "failed to test AddPrinterDriver level 2");
8340 info2.driver_path = r->driver_path;
8342 if (ex) {
8343 torture_assert(tctx,
8344 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8345 "failed to test AddPrinterDriverEx level 2");
8346 } else {
8347 torture_assert(tctx,
8348 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8349 "failed to test AddPrinterDriver level 2");
8352 info2.data_file = r->data_file;
8354 if (ex) {
8355 torture_assert(tctx,
8356 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8357 "failed to test AddPrinterDriverEx level 2");
8358 } else {
8359 torture_assert(tctx,
8360 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8361 "failed to test AddPrinterDriver level 2");
8364 info2.config_file = r->config_file;
8366 if (ex) {
8367 torture_assert(tctx,
8368 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8369 "failed to test AddPrinterDriverEx");
8372 if (ex) {
8373 torture_assert(tctx,
8374 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8375 "failed to test AddPrinterDriverEx level 2");
8376 } else {
8377 torture_assert(tctx,
8378 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8379 "failed to test AddPrinterDriver level 2");
8382 torture_assert(tctx,
8383 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8384 "failed to find added printer driver");
8386 if (remote_driver_dir) {
8387 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8388 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8389 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8392 return true;
8395 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8396 struct dcerpc_binding_handle *b,
8397 const char *server_name,
8398 struct spoolss_AddDriverInfo8 *r,
8399 uint32_t flags,
8400 bool ex,
8401 const char *remote_driver_dir)
8403 struct spoolss_AddDriverInfoCtr info_ctr;
8404 struct spoolss_AddDriverInfo3 info3;
8405 union spoolss_DriverInfo info;
8407 info3.driver_name = r->driver_name;
8408 info3.version = r->version;
8409 info3.architecture = r->architecture;
8410 info3.driver_path = r->driver_path;
8411 info3.data_file = r->data_file;
8412 info3.config_file = r->config_file;
8413 info3.help_file = r->help_file;
8414 info3.monitor_name = r->monitor_name;
8415 info3.default_datatype = r->default_datatype;
8416 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8417 info3.dependent_files = r->dependent_files;
8419 info_ctr.level = 3;
8420 info_ctr.info.info3 = &info3;
8422 if (ex) {
8423 torture_assert(tctx,
8424 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8425 "failed to test AddPrinterDriverEx level 3");
8426 } else {
8427 torture_assert(tctx,
8428 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8429 "failed to test AddPrinterDriver level 3");
8432 torture_assert(tctx,
8433 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8434 "failed to find added printer driver");
8436 if (remote_driver_dir) {
8437 int i;
8438 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8439 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8440 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8441 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8442 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8443 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8447 return true;
8450 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8451 struct dcerpc_binding_handle *b,
8452 const char *server_name,
8453 struct spoolss_AddDriverInfo8 *r,
8454 uint32_t flags,
8455 bool ex,
8456 const char *remote_driver_dir)
8458 struct spoolss_AddDriverInfoCtr info_ctr;
8459 struct spoolss_AddDriverInfo4 info4;
8460 union spoolss_DriverInfo info;
8462 info4.version = r->version;
8463 info4.driver_name = r->driver_name;
8464 info4.architecture = r->architecture;
8465 info4.driver_path = r->driver_path;
8466 info4.data_file = r->data_file;
8467 info4.config_file = r->config_file;
8468 info4.help_file = r->help_file;
8469 info4.monitor_name = r->monitor_name;
8470 info4.default_datatype = r->default_datatype;
8471 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8472 info4.dependent_files = r->dependent_files;
8473 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8474 info4.previous_names = r->previous_names;
8476 info_ctr.level = 4;
8477 info_ctr.info.info4 = &info4;
8479 if (ex) {
8480 torture_assert(tctx,
8481 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8482 "failed to test AddPrinterDriverEx level 4");
8483 } else {
8484 torture_assert(tctx,
8485 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8486 "failed to test AddPrinterDriver level 4");
8489 torture_assert(tctx,
8490 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8491 "failed to find added printer driver");
8493 if (remote_driver_dir) {
8494 int i;
8495 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8496 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8497 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8498 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8499 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8500 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8504 return true;
8507 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8508 struct dcerpc_binding_handle *b,
8509 const char *server_name,
8510 struct spoolss_AddDriverInfo8 *r,
8511 uint32_t flags,
8512 bool ex,
8513 const char *remote_driver_dir)
8515 struct spoolss_AddDriverInfoCtr info_ctr;
8516 struct spoolss_AddDriverInfo6 info6;
8517 union spoolss_DriverInfo info;
8519 info6.version = r->version;
8520 info6.driver_name = r->driver_name;
8521 info6.architecture = r->architecture;
8522 info6.driver_path = r->driver_path;
8523 info6.data_file = r->data_file;
8524 info6.config_file = r->config_file;
8525 info6.help_file = r->help_file;
8526 info6.monitor_name = r->monitor_name;
8527 info6.default_datatype = r->default_datatype;
8528 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8529 info6.dependent_files = r->dependent_files;
8530 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8531 info6.previous_names = r->previous_names;
8532 info6.driver_date = r->driver_date;
8533 info6.driver_version = r->driver_version;
8534 info6.manufacturer_name = r->manufacturer_name;
8535 info6.manufacturer_url = r->manufacturer_url;
8536 info6.hardware_id = r->hardware_id;
8537 info6.provider = r->provider;
8539 info_ctr.level = 6;
8540 info_ctr.info.info6 = &info6;
8542 if (ex) {
8543 torture_assert(tctx,
8544 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8545 "failed to test AddPrinterDriverEx level 6");
8546 } else {
8547 torture_assert(tctx,
8548 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8549 "failed to test AddPrinterDriver level 6");
8552 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8554 if (!ex) {
8555 return true;
8558 torture_assert(tctx,
8559 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8560 "failed to find added printer driver");
8562 if (remote_driver_dir) {
8563 int i;
8564 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8565 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8566 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8567 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8568 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8569 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8573 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8574 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8576 return true;
8579 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8580 struct dcerpc_binding_handle *b,
8581 const char *server_name,
8582 struct spoolss_AddDriverInfo8 *r,
8583 uint32_t flags,
8584 bool ex,
8585 const char *remote_driver_dir)
8587 struct spoolss_AddDriverInfoCtr info_ctr;
8588 union spoolss_DriverInfo info;
8590 info_ctr.level = 8;
8591 info_ctr.info.info8 = r;
8593 if (ex) {
8594 torture_assert(tctx,
8595 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8596 "failed to test AddPrinterDriverEx level 8");
8597 } else {
8598 torture_assert(tctx,
8599 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8600 "failed to test AddPrinterDriver level 8");
8603 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8605 if (!ex) {
8606 return true;
8609 torture_assert(tctx,
8610 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8611 "failed to find added printer driver");
8613 if (remote_driver_dir) {
8614 int i;
8615 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8616 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8617 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8618 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8619 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8620 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8624 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8625 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8627 return true;
8630 #undef ASSERT_DRIVER_PATH
8632 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8633 struct dcerpc_binding_handle *b,
8634 const char *server,
8635 const char *driver,
8636 const char *environment,
8637 WERROR expected_result)
8639 struct spoolss_DeletePrinterDriver r;
8641 r.in.server = server;
8642 r.in.architecture = environment;
8643 r.in.driver = driver;
8645 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8647 torture_assert_ntstatus_ok(tctx,
8648 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8649 "DeletePrinterDriver failed");
8650 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8651 "DeletePrinterDriver failed with unexpected result");
8653 return true;
8656 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8657 struct dcerpc_binding_handle *b,
8658 const char *server,
8659 const char *driver,
8660 const char *environment,
8661 uint32_t delete_flags,
8662 uint32_t version,
8663 WERROR expected_result)
8665 struct spoolss_DeletePrinterDriverEx r;
8667 r.in.server = server;
8668 r.in.architecture = environment;
8669 r.in.driver = driver;
8670 r.in.delete_flags = delete_flags;
8671 r.in.version = version;
8673 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8675 torture_assert_ntstatus_ok(tctx,
8676 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8677 "DeletePrinterDriverEx failed");
8678 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8679 "DeletePrinterDriverEx failed with unexpected result");
8681 return true;
8684 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8685 struct dcerpc_binding_handle *b,
8686 const char *server_name,
8687 const char *driver,
8688 const char *environment)
8690 torture_assert(tctx,
8691 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8692 "failed to delete driver");
8694 torture_assert(tctx,
8695 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8696 "failed to delete driver");
8698 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8699 torture_fail(tctx, "deleted driver still enumerated");
8702 torture_assert(tctx,
8703 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8704 "2nd delete failed");
8706 return true;
8709 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8710 struct dcerpc_binding_handle *b,
8711 const char *server_name,
8712 const char *driver,
8713 const char *environment,
8714 uint32_t delete_flags,
8715 uint32_t version)
8717 torture_assert(tctx,
8718 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8719 "failed to delete driver");
8721 torture_assert(tctx,
8722 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8723 "failed to delete driver");
8725 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8726 torture_fail(tctx, "deleted driver still enumerated");
8729 torture_assert(tctx,
8730 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8731 "2nd delete failed");
8733 return true;
8736 static bool test_PrinterDriver_args(struct torture_context *tctx,
8737 struct dcerpc_binding_handle *b,
8738 const char *server_name,
8739 uint32_t level,
8740 struct spoolss_AddDriverInfo8 *r,
8741 uint32_t add_flags,
8742 uint32_t delete_flags,
8743 uint32_t delete_version,
8744 bool ex,
8745 const char *remote_driver_dir)
8747 bool ret = true;
8749 switch (level) {
8750 case 1:
8751 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8752 break;
8753 case 2:
8754 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8755 break;
8756 case 3:
8757 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8758 break;
8759 case 4:
8760 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8761 break;
8762 case 6:
8763 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8764 break;
8765 case 8:
8766 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8767 break;
8768 default:
8769 return false;
8772 if (ret == false) {
8773 return ret;
8776 if (level == 1) {
8777 return ret;
8780 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8782 if (!ex && (level == 6 || level == 8)) {
8783 return ret;
8787 struct dcerpc_pipe *p2;
8788 struct policy_handle hive_handle;
8789 struct dcerpc_binding_handle *b2;
8791 torture_assert_ntstatus_ok(tctx,
8792 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8793 "could not open winreg pipe");
8794 b2 = p2->binding_handle;
8796 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8798 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8800 test_winreg_CloseKey(tctx, b2, &hive_handle);
8802 talloc_free(p2);
8805 if (ex) {
8806 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8807 } else {
8808 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8812 static bool fillup_printserver_info(struct torture_context *tctx,
8813 struct dcerpc_pipe *p,
8814 struct torture_driver_context *d)
8816 struct policy_handle server_handle;
8817 struct dcerpc_binding_handle *b = p->binding_handle;
8818 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8820 torture_assert(tctx,
8821 test_OpenPrinter_server(tctx, p, &server_handle),
8822 "failed to open printserver");
8823 torture_assert(tctx,
8824 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8825 "failed to get environment");
8826 torture_assert(tctx,
8827 test_ClosePrinter(tctx, b, &server_handle),
8828 "failed to close printserver");
8830 torture_assert(tctx,
8831 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8832 d->local.environment ? d->local.environment : d->remote.environment,
8833 &d->remote.driver_directory),
8834 "failed to get driver directory");
8836 return true;
8839 static const char *driver_directory_dir(const char *driver_directory)
8841 char *p;
8843 p = strrchr(driver_directory, '\\');
8844 if (p) {
8845 return p+1;
8848 return NULL;
8851 static const char *driver_directory_share(struct torture_context *tctx,
8852 const char *driver_directory)
8854 const char *p;
8855 char *tok;
8857 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8858 driver_directory += 2;
8861 p = talloc_strdup(tctx, driver_directory);
8863 torture_assert(tctx,
8864 next_token_talloc(tctx, &p, &tok, "\\"),
8865 "cannot explode uri");
8866 torture_assert(tctx,
8867 next_token_talloc(tctx, &p, &tok, "\\"),
8868 "cannot explode uri");
8870 return tok;
8873 static bool upload_printer_driver_file(struct torture_context *tctx,
8874 struct smbcli_state *cli,
8875 struct torture_driver_context *d,
8876 const char *file_name)
8878 XFILE *f;
8879 int fnum;
8880 uint8_t *buf;
8881 int maxwrite = 64512;
8882 off_t nread = 0;
8883 size_t start = 0;
8884 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8885 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8886 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8888 if (!file_name || strlen(file_name) == 0) {
8889 return true;
8892 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8894 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8895 if (fnum == -1) {
8896 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8899 f = x_fopen(local_name, O_RDONLY, 0);
8900 if (f == NULL) {
8901 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8904 buf = talloc_array(tctx, uint8_t, maxwrite);
8905 if (!buf) {
8906 return false;
8909 while (!x_feof(f)) {
8910 int n = maxwrite;
8911 int ret;
8913 if ((n = x_fread(buf, 1, n, f)) < 1) {
8914 if((n == 0) && x_feof(f))
8915 break; /* Empty local file. */
8917 torture_warning(tctx,
8918 "failed to read file: %s\n", strerror(errno));
8919 break;
8922 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8924 if (n != ret) {
8925 torture_warning(tctx,
8926 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8927 break;
8930 nread += n;
8933 x_fclose(f);
8935 torture_assert_ntstatus_ok(tctx,
8936 smbcli_close(cli->tree, fnum),
8937 "failed to close file");
8939 return true;
8942 static bool connect_printer_driver_share(struct torture_context *tctx,
8943 const char *server_name,
8944 const char *share_name,
8945 struct smbcli_state **cli)
8947 struct smbcli_options smb_options;
8948 struct smbcli_session_options smb_session_options;
8950 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8951 share_name, server_name);
8953 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8954 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8956 torture_assert_ntstatus_ok(tctx,
8957 smbcli_full_connection(tctx, cli, server_name,
8958 lpcfg_smb_ports(tctx->lp_ctx),
8959 share_name, NULL,
8960 lpcfg_socket_options(tctx->lp_ctx),
8961 cmdline_credentials,
8962 lpcfg_resolve_context(tctx->lp_ctx),
8963 tctx->ev,
8964 &smb_options,
8965 &smb_session_options,
8966 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8967 "failed to open driver share");
8969 return true;
8972 static bool upload_printer_driver(struct torture_context *tctx,
8973 const char *server_name,
8974 struct torture_driver_context *d)
8976 struct smbcli_state *cli;
8977 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8978 int i;
8980 torture_assert(tctx,
8981 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8982 "failed to connect to driver share");
8984 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8985 server_name, share_name);
8987 torture_assert(tctx,
8988 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8989 "failed to upload driver_path");
8990 torture_assert(tctx,
8991 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8992 "failed to upload data_file");
8993 torture_assert(tctx,
8994 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8995 "failed to upload config_file");
8996 torture_assert(tctx,
8997 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8998 "failed to upload help_file");
8999 if (d->info8.dependent_files) {
9000 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9001 torture_assert(tctx,
9002 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9003 "failed to upload dependent_files");
9007 talloc_free(cli);
9009 return true;
9012 static bool check_printer_driver_file(struct torture_context *tctx,
9013 struct smbcli_state *cli,
9014 struct torture_driver_context *d,
9015 const char *file_name)
9017 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9018 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9019 remote_arch_dir,
9020 d->info8.version,
9021 file_name);
9022 int fnum;
9024 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9026 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9028 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9029 if (fnum == -1) {
9030 return false;
9033 torture_assert_ntstatus_ok(tctx,
9034 smbcli_close(cli->tree, fnum),
9035 "failed to close driver file");
9037 return true;
9040 static bool check_printer_driver_files(struct torture_context *tctx,
9041 const char *server_name,
9042 struct torture_driver_context *d,
9043 bool expect_exist)
9045 struct smbcli_state *cli;
9046 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9047 int i;
9049 torture_assert(tctx,
9050 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9051 "failed to connect to driver share");
9053 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9054 (expect_exist ? "": "non-"),
9055 server_name, share_name);
9057 if (d->info8.driver_path && d->info8.driver_path[0]) {
9058 torture_assert(tctx,
9059 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9060 "failed driver_path check");
9062 if (d->info8.data_file && d->info8.data_file[0]) {
9063 torture_assert(tctx,
9064 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9065 "failed data_file check");
9067 if (d->info8.config_file && d->info8.config_file[0]) {
9068 torture_assert(tctx,
9069 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9070 "failed config_file check");
9072 if (d->info8.help_file && d->info8.help_file[0]) {
9073 torture_assert(tctx,
9074 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9075 "failed help_file check");
9077 if (d->info8.dependent_files) {
9078 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9079 torture_assert(tctx,
9080 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9081 "failed dependent_files check");
9085 talloc_free(cli);
9087 return true;
9090 static bool remove_printer_driver_file(struct torture_context *tctx,
9091 struct smbcli_state *cli,
9092 struct torture_driver_context *d,
9093 const char *file_name)
9095 const char *remote_name;
9096 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9098 if (!file_name || strlen(file_name) == 0) {
9099 return true;
9102 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9104 torture_comment(tctx, "Removing %s\n", remote_name);
9106 torture_assert_ntstatus_ok(tctx,
9107 smbcli_unlink(cli->tree, remote_name),
9108 "failed to unlink");
9110 return true;
9113 static bool remove_printer_driver(struct torture_context *tctx,
9114 const char *server_name,
9115 struct torture_driver_context *d)
9117 struct smbcli_state *cli;
9118 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9119 int i;
9121 torture_assert(tctx,
9122 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9123 "failed to connect to driver share");
9125 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9126 server_name, share_name);
9128 torture_assert(tctx,
9129 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9130 "failed to remove driver_path");
9131 torture_assert(tctx,
9132 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9133 "failed to remove data_file");
9134 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9135 torture_assert(tctx,
9136 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9137 "failed to remove config_file");
9139 torture_assert(tctx,
9140 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9141 "failed to remove help_file");
9142 if (d->info8.dependent_files) {
9143 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9144 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9145 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9146 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9147 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9148 continue;
9150 torture_assert(tctx,
9151 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9152 "failed to remove dependent_files");
9156 talloc_free(cli);
9158 return true;
9162 static bool test_add_driver_arg(struct torture_context *tctx,
9163 struct dcerpc_pipe *p,
9164 struct torture_driver_context *d)
9166 bool ret = true;
9167 struct dcerpc_binding_handle *b = p->binding_handle;
9168 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9169 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9170 int i;
9171 struct spoolss_AddDriverInfo8 info8;
9172 uint32_t add_flags = APD_COPY_NEW_FILES;
9173 uint32_t delete_flags = 0;
9175 ZERO_STRUCT(info8);
9177 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9178 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9180 torture_assert(tctx,
9181 fillup_printserver_info(tctx, p, d),
9182 "failed to fillup printserver info");
9184 if (!directory_exist(d->local.driver_directory)) {
9185 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9188 torture_assert(tctx,
9189 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9190 "failed to upload printer driver");
9192 info8 = d->info8;
9193 if (d->info8.dependent_files) {
9194 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9195 if (d->info8.dependent_files->string) {
9196 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9198 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9199 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9200 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9204 info8.architecture = d->local.environment;
9206 for (i=0; i < ARRAY_SIZE(levels); i++) {
9208 if (torture_setting_bool(tctx, "samba3", false)) {
9209 switch (levels[i]) {
9210 case 2:
9211 case 4:
9212 case 8:
9213 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9214 continue;
9215 default:
9216 break;
9219 if (torture_setting_bool(tctx, "w2k3", false)) {
9220 switch (levels[i]) {
9221 case 8:
9222 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9223 continue;
9224 default:
9225 break;
9229 torture_comment(tctx,
9230 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9231 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9233 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);
9236 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9237 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9238 if (d->info8.config_file) {
9239 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9241 if (d->info8.help_file) {
9242 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9244 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9245 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9246 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9250 for (i=0; i < ARRAY_SIZE(levels); i++) {
9252 if (torture_setting_bool(tctx, "samba3", false)) {
9253 switch (levels[i]) {
9254 case 2:
9255 case 4:
9256 case 8:
9257 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9258 continue;
9259 default:
9260 break;
9263 if (torture_setting_bool(tctx, "w2k3", false)) {
9264 switch (levels[i]) {
9265 case 8:
9266 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9267 continue;
9268 default:
9269 break;
9273 torture_comment(tctx,
9274 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9275 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9277 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);
9280 torture_assert(tctx,
9281 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9282 "failed to remove printer driver");
9284 torture_comment(tctx, "\n");
9286 return ret;
9289 static bool test_add_driver_ex_64(struct torture_context *tctx,
9290 struct dcerpc_pipe *p)
9292 struct torture_driver_context *d;
9294 d = talloc_zero(tctx, struct torture_driver_context);
9296 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9297 d->info8.driver_name = TORTURE_DRIVER_EX;
9298 d->info8.architecture = NULL;
9299 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9300 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9301 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9302 d->local.environment = talloc_strdup(d, "Windows x64");
9303 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9304 d->ex = true;
9306 return test_add_driver_arg(tctx, p, d);
9309 static bool test_add_driver_ex_32(struct torture_context *tctx,
9310 struct dcerpc_pipe *p)
9312 struct torture_driver_context *d;
9314 d = talloc_zero(tctx, struct torture_driver_context);
9316 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9317 d->info8.driver_name = TORTURE_DRIVER_EX;
9318 d->info8.architecture = NULL;
9319 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9320 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9321 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9322 d->local.environment = talloc_strdup(d, "Windows NT x86");
9323 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9324 d->ex = true;
9326 return test_add_driver_arg(tctx, p, d);
9329 static bool test_add_driver_64(struct torture_context *tctx,
9330 struct dcerpc_pipe *p)
9332 struct torture_driver_context *d;
9334 d = talloc_zero(tctx, struct torture_driver_context);
9336 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9337 d->info8.driver_name = TORTURE_DRIVER;
9338 d->info8.architecture = NULL;
9339 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9340 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9341 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9342 d->local.environment = talloc_strdup(d, "Windows x64");
9343 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9344 d->ex = false;
9346 return test_add_driver_arg(tctx, p, d);
9349 static bool test_add_driver_32(struct torture_context *tctx,
9350 struct dcerpc_pipe *p)
9352 struct torture_driver_context *d;
9354 d = talloc_zero(tctx, struct torture_driver_context);
9356 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9357 d->info8.driver_name = TORTURE_DRIVER;
9358 d->info8.architecture = NULL;
9359 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9360 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9361 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9362 d->local.environment = talloc_strdup(d, "Windows NT x86");
9363 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9364 d->ex = false;
9366 return test_add_driver_arg(tctx, p, d);
9369 static bool test_add_driver_adobe(struct torture_context *tctx,
9370 struct dcerpc_pipe *p)
9372 struct torture_driver_context *d;
9374 if (!torture_setting_bool(tctx, "samba3", false)) {
9375 torture_skip(tctx, "skipping adobe test which only works against samba3");
9378 d = talloc_zero(tctx, struct torture_driver_context);
9380 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9381 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9382 d->info8.architecture = NULL;
9383 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9384 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9385 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9386 #if 0
9387 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9388 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9389 #endif
9390 d->local.environment = talloc_strdup(d, "Windows 4.0");
9391 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9392 d->ex = false;
9394 return test_add_driver_arg(tctx, p, d);
9397 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9398 struct dcerpc_pipe *p)
9400 struct torture_driver_context *d;
9401 struct spoolss_StringArray *a;
9403 if (!torture_setting_bool(tctx, "samba3", false)) {
9404 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9407 d = talloc_zero(tctx, struct torture_driver_context);
9409 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9410 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9411 d->info8.architecture = NULL;
9412 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9413 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9414 d->info8.config_file = NULL;
9415 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9416 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9417 d->info8.default_datatype = talloc_strdup(d, "RAW");
9419 a = talloc_zero(d, struct spoolss_StringArray);
9420 a->string = talloc_zero_array(a, const char *, 7);
9421 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9422 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9423 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9424 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9425 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9426 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9428 d->info8.dependent_files = a;
9429 d->local.environment = talloc_strdup(d, "Windows 4.0");
9430 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9431 d->ex = false;
9433 return test_add_driver_arg(tctx, p, d);
9436 static bool test_add_driver_timestamps(struct torture_context *tctx,
9437 struct dcerpc_pipe *p)
9439 struct torture_driver_context *d;
9440 struct timeval t = timeval_current();
9442 d = talloc_zero(tctx, struct torture_driver_context);
9444 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9445 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9446 d->info8.architecture = NULL;
9447 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9448 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9449 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9450 d->info8.driver_date = timeval_to_nttime(&t);
9451 d->local.environment = talloc_strdup(d, "Windows NT x86");
9452 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9453 d->ex = true;
9455 torture_assert(tctx,
9456 test_add_driver_arg(tctx, p, d),
9457 "");
9459 unix_to_nt_time(&d->info8.driver_date, 1);
9461 torture_assert(tctx,
9462 test_add_driver_arg(tctx, p, d),
9463 "");
9465 return true;
9468 static bool test_multiple_drivers(struct torture_context *tctx,
9469 struct dcerpc_pipe *p)
9471 struct torture_driver_context *d;
9472 struct dcerpc_binding_handle *b = p->binding_handle;
9473 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9474 int i;
9475 struct spoolss_AddDriverInfo8 info8;
9476 uint32_t add_flags = APD_COPY_NEW_FILES;
9477 uint32_t delete_flags = 0;
9479 d = talloc_zero(tctx, struct torture_driver_context);
9481 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9482 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9483 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9484 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9485 d->local.environment = talloc_strdup(d, "Windows NT x86");
9486 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9487 d->ex = true;
9489 torture_assert(tctx,
9490 fillup_printserver_info(tctx, p, d),
9491 "failed to fillup printserver info");
9493 if (!directory_exist(d->local.driver_directory)) {
9494 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9497 torture_assert(tctx,
9498 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9499 "failed to upload printer driver");
9501 info8 = d->info8;
9502 info8.architecture = d->local.environment;
9504 for (i=0; i < 3; i++) {
9505 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9507 torture_assert(tctx,
9508 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9509 "failed to add driver");
9512 torture_assert(tctx,
9513 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9514 "failed to delete driver");
9516 torture_assert(tctx,
9517 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9518 "torture_test_driver_1 no longer on the server");
9520 torture_assert(tctx,
9521 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9522 "torture_test_driver_2 no longer on the server");
9524 torture_assert(tctx,
9525 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9526 "failed to delete driver");
9528 torture_assert(tctx,
9529 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9530 "torture_test_driver_2 no longer on the server");
9532 torture_assert(tctx,
9533 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9534 "failed to delete driver");
9536 torture_assert(tctx,
9537 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9538 "failed to remove printer driver");
9540 return true;
9543 static bool test_del_driver_all_files(struct torture_context *tctx,
9544 struct dcerpc_pipe *p)
9546 struct torture_driver_context *d;
9547 struct spoolss_StringArray *a;
9548 uint32_t add_flags = APD_COPY_NEW_FILES;
9549 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9550 struct dcerpc_binding_handle *b = p->binding_handle;
9551 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9553 d = talloc_zero(tctx, struct torture_driver_context);
9555 d->ex = true;
9556 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9557 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9558 d->info8.architecture = NULL;
9559 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9560 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9561 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9562 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9563 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9564 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9566 a = talloc_zero(d, struct spoolss_StringArray);
9567 a->string = talloc_zero_array(a, const char *, 3);
9568 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9569 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9571 d->info8.dependent_files = a;
9572 d->info8.architecture = d->local.environment;
9574 torture_assert(tctx,
9575 fillup_printserver_info(tctx, p, d),
9576 "failed to fillup printserver info");
9578 if (!directory_exist(d->local.driver_directory)) {
9579 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9582 torture_assert(tctx,
9583 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9584 "failed to upload printer driver");
9586 torture_assert(tctx,
9587 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9588 "failed to add driver");
9590 torture_assert(tctx,
9591 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9592 d->info8.driver_name,
9593 d->local.environment,
9594 delete_flags,
9595 d->info8.version),
9596 "failed to delete driver");
9598 torture_assert(tctx,
9599 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9600 "printer driver file check failed");
9602 talloc_free(d);
9603 return true;
9606 static bool test_del_driver_unused_files(struct torture_context *tctx,
9607 struct dcerpc_pipe *p)
9609 struct torture_driver_context *d1;
9610 struct torture_driver_context *d2;
9611 uint32_t add_flags = APD_COPY_NEW_FILES;
9612 struct dcerpc_binding_handle *b = p->binding_handle;
9613 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9615 d1 = talloc_zero(tctx, struct torture_driver_context);
9616 d1->ex = true;
9617 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9618 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9619 d1->info8.architecture = NULL;
9620 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9621 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9622 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9623 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9624 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9625 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9626 d1->info8.architecture = d1->local.environment;
9628 d2 = talloc_zero(tctx, struct torture_driver_context);
9629 d2->ex = true;
9630 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9631 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9632 d2->info8.architecture = NULL;
9633 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9634 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9635 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9636 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9637 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9638 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9639 d2->info8.architecture = d2->local.environment;
9641 torture_assert(tctx,
9642 fillup_printserver_info(tctx, p, d1),
9643 "failed to fillup printserver info");
9644 torture_assert(tctx,
9645 fillup_printserver_info(tctx, p, d2),
9646 "failed to fillup printserver info");
9648 if (!directory_exist(d1->local.driver_directory)) {
9649 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9652 torture_assert(tctx,
9653 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9654 "failed to upload printer driver");
9655 torture_assert(tctx,
9656 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9657 "failed to add driver");
9659 torture_assert(tctx,
9660 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9661 "failed to upload printer driver");
9662 torture_assert(tctx,
9663 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9664 "failed to add driver");
9666 /* some files are in use by a separate driver, should fail */
9667 torture_assert(tctx,
9668 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9669 d1->info8.driver_name,
9670 d1->local.environment,
9671 DPD_DELETE_ALL_FILES,
9672 d1->info8.version,
9673 WERR_PRINTER_DRIVER_IN_USE),
9674 "invalid delete driver response");
9676 /* should only delete files not in use by other driver */
9677 torture_assert(tctx,
9678 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9679 d1->info8.driver_name,
9680 d1->local.environment,
9681 DPD_DELETE_UNUSED_FILES,
9682 d1->info8.version,
9683 WERR_OK),
9684 "failed to delete driver (unused files)");
9686 /* check non-overlapping were deleted */
9687 d1->info8.driver_path = NULL;
9688 d1->info8.help_file = NULL;
9689 torture_assert(tctx,
9690 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9691 "printer driver file check failed");
9692 /* d2 files should be uneffected */
9693 torture_assert(tctx,
9694 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9695 "printer driver file check failed");
9697 torture_assert(tctx,
9698 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9699 d2->info8.driver_name,
9700 d2->local.environment,
9701 DPD_DELETE_ALL_FILES,
9702 d2->info8.version,
9703 WERR_OK),
9704 "failed to delete driver");
9706 torture_assert(tctx,
9707 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9708 "printer driver file check failed");
9710 talloc_free(d1);
9711 talloc_free(d2);
9712 return true;
9715 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9717 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9719 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9720 "driver", &ndr_table_spoolss);
9721 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9722 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9724 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9725 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9727 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9729 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9731 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9733 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9735 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9737 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9739 return suite;