spoolss: make spoolss deal with ndr64 StartDocPrinter by using proper container object.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / spoolss.c
blob509c61fd7e5c221621e2d27e33592ca85daba4e7
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_DocumentInfoCtr info_ctr;
3277 struct spoolss_DocumentInfo1 info1;
3278 struct spoolss_StartPagePrinter sp;
3279 struct spoolss_WritePrinter w;
3280 struct spoolss_EndPagePrinter ep;
3281 struct spoolss_EndDocPrinter e;
3282 int i;
3283 uint32_t num_written;
3285 torture_comment(tctx, "Testing StartDocPrinter\n");
3287 s.in.handle = handle;
3288 s.in.info_ctr = &info_ctr;
3289 s.out.job_id = job_id;
3291 info1.document_name = document_name;
3292 info1.output_file = NULL;
3293 info1.datatype = "RAW";
3295 info_ctr.level = 1;
3296 info_ctr.info.info1 = &info1;
3298 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3299 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3300 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3302 for (i=1; i < 4; i++) {
3303 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3305 sp.in.handle = handle;
3307 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3308 torture_assert_ntstatus_ok(tctx, status,
3309 "dcerpc_spoolss_StartPagePrinter failed");
3310 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3312 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3314 w.in.handle = handle;
3315 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3316 w.out.num_written = &num_written;
3318 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3319 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3320 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3322 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3324 ep.in.handle = handle;
3326 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3327 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3328 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3331 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3333 e.in.handle = handle;
3335 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3336 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3337 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3339 return true;
3342 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3343 struct dcerpc_binding_handle *b,
3344 struct policy_handle *handle,
3345 uint32_t num_jobs,
3346 uint32_t *job_ids)
3348 uint32_t count;
3349 union spoolss_JobInfo *info = NULL;
3350 int i;
3352 torture_assert(tctx,
3353 test_AddJob(tctx, b, handle),
3354 "AddJob failed");
3356 torture_assert(tctx,
3357 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3358 "EnumJobs level 1 failed");
3360 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3362 for (i=0; i < num_jobs; i++) {
3363 union spoolss_JobInfo ginfo;
3364 const char *document_name;
3365 const char *new_document_name = "any_other_docname";
3366 struct spoolss_JobInfoContainer ctr;
3367 struct spoolss_SetJobInfo1 info1;
3369 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3371 torture_assert(tctx,
3372 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3373 "failed to call test_GetJob");
3375 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3377 document_name = ginfo.info1.document_name;
3379 info1.job_id = ginfo.info1.job_id;
3380 info1.printer_name = ginfo.info1.printer_name;
3381 info1.server_name = ginfo.info1.server_name;
3382 info1.user_name = ginfo.info1.user_name;
3383 info1.document_name = new_document_name;
3384 info1.data_type = ginfo.info1.data_type;
3385 info1.text_status = ginfo.info1.text_status;
3386 info1.status = ginfo.info1.status;
3387 info1.priority = ginfo.info1.priority;
3388 info1.position = ginfo.info1.position;
3389 info1.total_pages = ginfo.info1.total_pages;
3390 info1.pages_printed = ginfo.info1.pages_printed;
3391 info1.submitted = ginfo.info1.submitted;
3393 ctr.level = 1;
3394 ctr.info.info1 = &info1;
3396 torture_assert(tctx,
3397 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3398 "failed to call test_SetJob level 1");
3400 torture_assert(tctx,
3401 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3402 "failed to call test_GetJob");
3404 if (strequal(ginfo.info1.document_name, document_name)) {
3405 torture_warning(tctx,
3406 "document_name did *NOT* change from '%s' to '%s'\n",
3407 document_name, new_document_name);
3411 for (i=0; i < num_jobs; i++) {
3412 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3413 torture_warning(tctx, "failed to pause printjob\n");
3415 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3416 torture_warning(tctx, "failed to resume printjob\n");
3420 return true;
3423 static bool test_DoPrintTest(struct torture_context *tctx,
3424 struct dcerpc_binding_handle *b,
3425 struct policy_handle *handle)
3427 bool ret = true;
3428 uint32_t num_jobs = 8;
3429 uint32_t *job_ids;
3430 int i;
3432 torture_comment(tctx, "Testing real print operations\n");
3434 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3436 for (i=0; i < num_jobs; i++) {
3437 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3440 for (i=0; i < num_jobs; i++) {
3441 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3444 if (ret == true) {
3445 torture_comment(tctx, "real print operations test succeeded\n\n");
3448 return ret;
3451 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3452 struct dcerpc_binding_handle *b,
3453 struct policy_handle *handle)
3455 bool ret = true;
3456 uint32_t num_jobs = 8;
3457 uint32_t *job_ids;
3458 int i;
3459 torture_comment(tctx, "Testing real print operations (extended)\n");
3461 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3463 for (i=0; i < num_jobs; i++) {
3464 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3467 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3469 for (i=0; i < num_jobs; i++) {
3470 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3473 if (ret == true) {
3474 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3477 return ret;
3480 static bool test_PausePrinter(struct torture_context *tctx,
3481 struct dcerpc_binding_handle *b,
3482 struct policy_handle *handle)
3484 NTSTATUS status;
3485 struct spoolss_SetPrinter r;
3486 struct spoolss_SetPrinterInfoCtr info_ctr;
3487 struct spoolss_DevmodeContainer devmode_ctr;
3488 struct sec_desc_buf secdesc_ctr;
3490 info_ctr.level = 0;
3491 info_ctr.info.info0 = NULL;
3493 ZERO_STRUCT(devmode_ctr);
3494 ZERO_STRUCT(secdesc_ctr);
3496 r.in.handle = handle;
3497 r.in.info_ctr = &info_ctr;
3498 r.in.devmode_ctr = &devmode_ctr;
3499 r.in.secdesc_ctr = &secdesc_ctr;
3500 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3502 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3504 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3506 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3508 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3510 return true;
3513 static bool test_ResumePrinter(struct torture_context *tctx,
3514 struct dcerpc_binding_handle *b,
3515 struct policy_handle *handle)
3517 NTSTATUS status;
3518 struct spoolss_SetPrinter r;
3519 struct spoolss_SetPrinterInfoCtr info_ctr;
3520 struct spoolss_DevmodeContainer devmode_ctr;
3521 struct sec_desc_buf secdesc_ctr;
3523 info_ctr.level = 0;
3524 info_ctr.info.info0 = NULL;
3526 ZERO_STRUCT(devmode_ctr);
3527 ZERO_STRUCT(secdesc_ctr);
3529 r.in.handle = handle;
3530 r.in.info_ctr = &info_ctr;
3531 r.in.devmode_ctr = &devmode_ctr;
3532 r.in.secdesc_ctr = &secdesc_ctr;
3533 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3535 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3537 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3539 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3541 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3543 return true;
3546 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3547 struct dcerpc_binding_handle *b,
3548 struct policy_handle *handle,
3549 const char *value_name,
3550 enum winreg_Type *expected_type,
3551 enum winreg_Type *type_p,
3552 uint8_t **data_p,
3553 uint32_t *needed_p)
3555 NTSTATUS status;
3556 struct spoolss_GetPrinterData r;
3557 uint32_t needed;
3558 enum winreg_Type type;
3559 union spoolss_PrinterData data;
3561 r.in.handle = handle;
3562 r.in.value_name = value_name;
3563 r.in.offered = 0;
3564 r.out.needed = &needed;
3565 r.out.type = &type;
3566 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3568 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3570 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3571 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3573 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3574 if (expected_type) {
3575 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3577 r.in.offered = needed;
3578 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3579 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3580 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3583 torture_assert_werr_ok(tctx, r.out.result,
3584 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3586 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3588 if (type_p) {
3589 *type_p = type;
3592 if (data_p) {
3593 *data_p = r.out.data;
3596 if (needed_p) {
3597 *needed_p = needed;
3600 return true;
3603 static bool test_GetPrinterData(struct torture_context *tctx,
3604 struct dcerpc_binding_handle *b,
3605 struct policy_handle *handle,
3606 const char *value_name,
3607 enum winreg_Type *type_p,
3608 uint8_t **data_p,
3609 uint32_t *needed_p)
3611 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3612 NULL, type_p, data_p, needed_p);
3615 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3616 struct dcerpc_pipe *p,
3617 struct policy_handle *handle,
3618 const char *key_name,
3619 const char *value_name,
3620 enum winreg_Type *expected_type,
3621 enum winreg_Type *type_p,
3622 uint8_t **data_p,
3623 uint32_t *needed_p)
3625 NTSTATUS status;
3626 struct spoolss_GetPrinterDataEx r;
3627 enum winreg_Type type;
3628 uint32_t needed;
3629 union spoolss_PrinterData data;
3630 struct dcerpc_binding_handle *b = p->binding_handle;
3632 r.in.handle = handle;
3633 r.in.key_name = key_name;
3634 r.in.value_name = value_name;
3635 r.in.offered = 0;
3636 r.out.type = &type;
3637 r.out.needed = &needed;
3638 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3640 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3641 r.in.key_name, r.in.value_name);
3643 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3646 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3648 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3651 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3652 if (expected_type) {
3653 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3655 r.in.offered = needed;
3656 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3657 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3658 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3661 torture_assert_werr_ok(tctx, r.out.result,
3662 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3664 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3666 if (type_p) {
3667 *type_p = type;
3670 if (data_p) {
3671 *data_p = r.out.data;
3674 if (needed_p) {
3675 *needed_p = needed;
3678 return true;
3681 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3682 struct dcerpc_pipe *p,
3683 struct policy_handle *handle,
3684 const char *key_name,
3685 const char *value_name,
3686 enum winreg_Type *type_p,
3687 uint8_t **data_p,
3688 uint32_t *needed_p)
3690 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3691 NULL, type_p, data_p, needed_p);
3694 static bool test_get_environment(struct torture_context *tctx,
3695 struct dcerpc_binding_handle *b,
3696 struct policy_handle *handle,
3697 const char **architecture)
3699 DATA_BLOB blob;
3700 enum winreg_Type type;
3701 uint8_t *data;
3702 uint32_t needed;
3704 torture_assert(tctx,
3705 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3706 "failed to get Architecture");
3708 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3710 blob = data_blob_const(data, needed);
3711 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3713 return true;
3716 static bool test_GetPrinterData_list(struct torture_context *tctx,
3717 void *private_data)
3719 struct test_spoolss_context *ctx =
3720 talloc_get_type_abort(private_data, struct test_spoolss_context);
3721 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3722 struct dcerpc_binding_handle *b = p->binding_handle;
3723 const char *list[] = {
3724 "W3SvcInstalled",
3725 "BeepEnabled",
3726 "EventLog",
3727 /* "NetPopup", not on w2k8 */
3728 /* "NetPopupToComputer", not on w2k8 */
3729 "MajorVersion",
3730 "MinorVersion",
3731 "DefaultSpoolDirectory",
3732 "Architecture",
3733 "DsPresent",
3734 "OSVersion",
3735 /* "OSVersionEx", not on s3 */
3736 "DNSMachineName"
3738 int i;
3740 for (i=0; i < ARRAY_SIZE(list); i++) {
3741 enum winreg_Type type, type_ex;
3742 uint8_t *data, *data_ex;
3743 uint32_t needed, needed_ex;
3745 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3746 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3747 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3748 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3749 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3750 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3751 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3754 return true;
3757 static bool test_EnumPrinterData(struct torture_context *tctx,
3758 struct dcerpc_pipe *p,
3759 struct policy_handle *handle,
3760 uint32_t enum_index,
3761 uint32_t value_offered,
3762 uint32_t data_offered,
3763 enum winreg_Type *type_p,
3764 uint32_t *value_needed_p,
3765 uint32_t *data_needed_p,
3766 const char **value_name_p,
3767 uint8_t **data_p,
3768 WERROR *result_p)
3770 struct spoolss_EnumPrinterData r;
3771 uint32_t data_needed;
3772 uint32_t value_needed;
3773 enum winreg_Type type;
3774 struct dcerpc_binding_handle *b = p->binding_handle;
3776 r.in.handle = handle;
3777 r.in.enum_index = enum_index;
3778 r.in.value_offered = value_offered;
3779 r.in.data_offered = data_offered;
3780 r.out.data_needed = &data_needed;
3781 r.out.value_needed = &value_needed;
3782 r.out.type = &type;
3783 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3784 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3786 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3788 torture_assert_ntstatus_ok(tctx,
3789 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3790 "EnumPrinterData failed");
3792 if (type_p) {
3793 *type_p = type;
3795 if (value_needed_p) {
3796 *value_needed_p = value_needed;
3798 if (data_needed_p) {
3799 *data_needed_p = data_needed;
3801 if (value_name_p) {
3802 *value_name_p = r.out.value_name;
3804 if (data_p) {
3805 *data_p = r.out.data;
3807 if (result_p) {
3808 *result_p = r.out.result;
3811 return true;
3815 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3816 struct dcerpc_pipe *p,
3817 struct policy_handle *handle)
3819 uint32_t enum_index = 0;
3820 enum winreg_Type type;
3821 uint32_t value_needed;
3822 uint32_t data_needed;
3823 uint8_t *data;
3824 const char *value_name;
3825 WERROR result;
3827 torture_comment(tctx, "Testing EnumPrinterData\n");
3829 do {
3830 torture_assert(tctx,
3831 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3832 &type, &value_needed, &data_needed,
3833 &value_name, &data, &result),
3834 "EnumPrinterData failed");
3836 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3837 break;
3840 torture_assert(tctx,
3841 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3842 &type, &value_needed, &data_needed,
3843 &value_name, &data, &result),
3844 "EnumPrinterData failed");
3846 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3847 break;
3850 enum_index++;
3852 } while (W_ERROR_IS_OK(result));
3854 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3856 return true;
3859 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3860 struct dcerpc_binding_handle *b,
3861 struct policy_handle *handle,
3862 const char *key_name,
3863 uint32_t *count_p,
3864 struct spoolss_PrinterEnumValues **info_p)
3866 struct spoolss_EnumPrinterDataEx r;
3867 struct spoolss_PrinterEnumValues *info;
3868 uint32_t needed;
3869 uint32_t count;
3871 r.in.handle = handle;
3872 r.in.key_name = key_name;
3873 r.in.offered = 0;
3874 r.out.needed = &needed;
3875 r.out.count = &count;
3876 r.out.info = &info;
3878 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3880 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3881 "EnumPrinterDataEx failed");
3882 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3883 r.in.offered = needed;
3884 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3885 "EnumPrinterDataEx failed");
3888 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3890 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3892 if (count_p) {
3893 *count_p = count;
3895 if (info_p) {
3896 *info_p = info;
3899 return true;
3902 static bool test_SetPrinterData(struct torture_context *tctx,
3903 struct dcerpc_binding_handle *b,
3904 struct policy_handle *handle,
3905 const char *value_name,
3906 enum winreg_Type type,
3907 uint8_t *data,
3908 uint32_t offered);
3909 static bool test_DeletePrinterData(struct torture_context *tctx,
3910 struct dcerpc_binding_handle *b,
3911 struct policy_handle *handle,
3912 const char *value_name);
3914 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3915 struct dcerpc_pipe *p,
3916 struct policy_handle *handle)
3918 uint32_t count;
3919 struct spoolss_PrinterEnumValues *info;
3920 int i;
3921 uint32_t value_needed, data_needed;
3922 uint32_t value_offered, data_offered;
3923 WERROR result;
3924 struct dcerpc_binding_handle *b = p->binding_handle;
3926 enum winreg_Type type;
3927 DATA_BLOB blob;
3929 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3931 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3932 type = REG_SZ;
3934 torture_assert(tctx,
3935 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3936 "SetPrinterData failed");
3938 blob = data_blob_string_const("torture_data2");
3940 torture_assert(tctx,
3941 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3942 "SetPrinterData failed");
3944 blob = data_blob_talloc(tctx, NULL, 4);
3945 SIVAL(blob.data, 0, 0x11223344);
3947 torture_assert(tctx,
3948 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3949 "SetPrinterData failed");
3951 torture_assert(tctx,
3952 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3953 "failed to call EnumPrinterDataEx");
3955 /* get the max sizes for value and data */
3957 torture_assert(tctx,
3958 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3959 NULL, &value_needed, &data_needed,
3960 NULL, NULL, &result),
3961 "EnumPrinterData failed");
3962 torture_assert_werr_ok(tctx, result, "unexpected result");
3964 /* check if the reply from the EnumPrinterData really matches max values */
3966 for (i=0; i < count; i++) {
3967 if (info[i].value_name_len > value_needed) {
3968 torture_fail(tctx,
3969 talloc_asprintf(tctx,
3970 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3971 info[i].value_name_len, value_needed));
3973 if (info[i].data_length > data_needed) {
3974 torture_fail(tctx,
3975 talloc_asprintf(tctx,
3976 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3977 info[i].data_length, data_needed));
3981 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3982 * sort or not sort the replies by value name, we should be able to do
3983 * the following entry comparison */
3985 data_offered = data_needed;
3986 value_offered = value_needed;
3988 for (i=0; i < count; i++) {
3990 const char *value_name;
3991 uint8_t *data;
3993 torture_assert(tctx,
3994 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3995 &type, &value_needed, &data_needed,
3996 &value_name, &data, &result),
3997 "EnumPrinterData failed");
3999 if (i -1 == count) {
4000 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4001 "unexpected result");
4002 break;
4003 } else {
4004 torture_assert_werr_ok(tctx, result, "unexpected result");
4007 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4008 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4009 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4010 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4011 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4014 torture_assert(tctx,
4015 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4016 "DeletePrinterData failed");
4017 torture_assert(tctx,
4018 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4019 "DeletePrinterData failed");
4020 torture_assert(tctx,
4021 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4022 "DeletePrinterData failed");
4024 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4026 return true;
4029 static bool test_DeletePrinterData(struct torture_context *tctx,
4030 struct dcerpc_binding_handle *b,
4031 struct policy_handle *handle,
4032 const char *value_name)
4034 NTSTATUS status;
4035 struct spoolss_DeletePrinterData r;
4037 r.in.handle = handle;
4038 r.in.value_name = value_name;
4040 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4041 r.in.value_name);
4043 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4045 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4046 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4048 return true;
4051 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4052 struct dcerpc_binding_handle *b,
4053 struct policy_handle *handle,
4054 const char *key_name,
4055 const char *value_name)
4057 struct spoolss_DeletePrinterDataEx r;
4059 r.in.handle = handle;
4060 r.in.key_name = key_name;
4061 r.in.value_name = value_name;
4063 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4064 r.in.key_name, r.in.value_name);
4066 torture_assert_ntstatus_ok(tctx,
4067 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4068 "DeletePrinterDataEx failed");
4069 torture_assert_werr_ok(tctx, r.out.result,
4070 "DeletePrinterDataEx failed");
4072 return true;
4075 static bool test_DeletePrinterKey(struct torture_context *tctx,
4076 struct dcerpc_binding_handle *b,
4077 struct policy_handle *handle,
4078 const char *key_name)
4080 struct spoolss_DeletePrinterKey r;
4082 r.in.handle = handle;
4083 r.in.key_name = key_name;
4085 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4087 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4088 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4089 return true;
4092 torture_assert_ntstatus_ok(tctx,
4093 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4094 "DeletePrinterKey failed");
4095 torture_assert_werr_ok(tctx, r.out.result,
4096 "DeletePrinterKey failed");
4098 return true;
4101 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4102 struct dcerpc_binding_handle *b,
4103 struct policy_handle *handle)
4105 struct winreg_OpenHKLM r;
4107 r.in.system_name = NULL;
4108 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4109 r.out.handle = handle;
4111 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4113 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4114 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4116 return true;
4119 static void init_winreg_String(struct winreg_String *name, const char *s)
4121 name->name = s;
4122 if (s) {
4123 name->name_len = 2 * (strlen_m(s) + 1);
4124 name->name_size = name->name_len;
4125 } else {
4126 name->name_len = 0;
4127 name->name_size = 0;
4131 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4132 struct dcerpc_binding_handle *b,
4133 struct policy_handle *hive_handle,
4134 const char *keyname,
4135 uint32_t options,
4136 struct policy_handle *key_handle)
4138 struct winreg_OpenKey r;
4140 r.in.parent_handle = hive_handle;
4141 init_winreg_String(&r.in.keyname, keyname);
4142 r.in.options = options;
4143 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4144 r.out.handle = key_handle;
4146 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4148 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4149 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4151 return true;
4154 static bool test_winreg_OpenKey(struct torture_context *tctx,
4155 struct dcerpc_binding_handle *b,
4156 struct policy_handle *hive_handle,
4157 const char *keyname,
4158 struct policy_handle *key_handle)
4160 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4161 REG_OPTION_NON_VOLATILE, key_handle);
4164 static bool test_winreg_CloseKey(struct torture_context *tctx,
4165 struct dcerpc_binding_handle *b,
4166 struct policy_handle *handle)
4168 struct winreg_CloseKey r;
4170 r.in.handle = handle;
4171 r.out.handle = handle;
4173 torture_comment(tctx, "Testing winreg_CloseKey\n");
4175 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4176 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4178 return true;
4181 bool test_winreg_QueryValue(struct torture_context *tctx,
4182 struct dcerpc_binding_handle *b,
4183 struct policy_handle *handle,
4184 const char *value_name,
4185 enum winreg_Type *type_p,
4186 uint32_t *data_size_p,
4187 uint32_t *data_length_p,
4188 uint8_t **data_p)
4190 struct winreg_QueryValue r;
4191 enum winreg_Type type = REG_NONE;
4192 uint32_t data_size = 0;
4193 uint32_t data_length = 0;
4194 struct winreg_String valuename;
4195 uint8_t *data = NULL;
4197 init_winreg_String(&valuename, value_name);
4199 data = talloc_zero_array(tctx, uint8_t, 0);
4201 r.in.handle = handle;
4202 r.in.value_name = &valuename;
4203 r.in.type = &type;
4204 r.in.data_size = &data_size;
4205 r.in.data_length = &data_length;
4206 r.in.data = data;
4207 r.out.type = &type;
4208 r.out.data = data;
4209 r.out.data_size = &data_size;
4210 r.out.data_length = &data_length;
4212 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4214 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4215 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4216 *r.in.data_size = *r.out.data_size;
4217 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4218 r.in.data = data;
4219 r.out.data = data;
4220 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4222 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4224 if (type_p) {
4225 *type_p = *r.out.type;
4227 if (data_size_p) {
4228 *data_size_p = *r.out.data_size;
4230 if (data_length_p) {
4231 *data_length_p = *r.out.data_length;
4233 if (data_p) {
4234 *data_p = r.out.data;
4237 return true;
4240 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4241 struct dcerpc_binding_handle *b,
4242 struct policy_handle *handle,
4243 const char *printer_name,
4244 const char *key_name,
4245 const char *value_name,
4246 enum winreg_Type *w_type,
4247 uint32_t *w_size,
4248 uint32_t *w_length,
4249 uint8_t **w_data)
4251 const char *printer_key;
4252 struct policy_handle key_handle;
4254 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4255 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4257 torture_assert(tctx,
4258 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4260 torture_assert(tctx,
4261 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4263 torture_assert(tctx,
4264 test_winreg_CloseKey(tctx, b, &key_handle), "");
4266 return true;
4269 static bool test_GetForm_winreg(struct torture_context *tctx,
4270 struct dcerpc_binding_handle *b,
4271 struct policy_handle *handle,
4272 const char *key_name,
4273 const char *form_name,
4274 enum winreg_Type *w_type,
4275 uint32_t *w_size,
4276 uint32_t *w_length,
4277 uint8_t **w_data)
4279 struct policy_handle key_handle;
4281 torture_assert(tctx,
4282 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4284 torture_assert(tctx,
4285 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4287 torture_assert(tctx,
4288 test_winreg_CloseKey(tctx, b, &key_handle), "");
4290 return true;
4293 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4294 struct dcerpc_binding_handle *b,
4295 struct policy_handle *handle,
4296 const char *symlink_keyname,
4297 const char *symlink_destination)
4299 /* check if the first key is a symlink to the second key */
4301 enum winreg_Type w_type;
4302 uint32_t w_size;
4303 uint32_t w_length;
4304 uint8_t *w_data;
4305 struct policy_handle key_handle;
4306 DATA_BLOB blob;
4307 const char *str;
4309 if (torture_setting_bool(tctx, "samba3", false)) {
4310 torture_skip(tctx, "skip winreg symlink test against samba");
4313 torture_assert(tctx,
4314 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4315 "failed to open key link");
4317 torture_assert(tctx,
4318 test_winreg_QueryValue(tctx, b, &key_handle,
4319 "SymbolicLinkValue",
4320 &w_type, &w_size, &w_length, &w_data),
4321 "failed to query for 'SymbolicLinkValue' attribute");
4323 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4325 blob = data_blob(w_data, w_size);
4326 str = reg_val_data_string(tctx, REG_SZ, blob);
4328 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4330 torture_assert(tctx,
4331 test_winreg_CloseKey(tctx, b, &key_handle),
4332 "failed to close key link");
4334 return true;
4337 static const char *strip_unc(const char *unc)
4339 char *name;
4341 if (!unc) {
4342 return NULL;
4345 if (unc[0] == '\\' && unc[1] == '\\') {
4346 unc +=2;
4349 name = strchr(unc, '\\');
4350 if (name) {
4351 return name+1;
4354 return unc;
4357 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4358 struct dcerpc_binding_handle *b,
4359 struct policy_handle *handle,
4360 const char *printer_name,
4361 struct dcerpc_binding_handle *winreg_handle,
4362 struct policy_handle *hive_handle)
4364 union spoolss_PrinterInfo info;
4365 const char *keys[] = {
4366 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4367 TOP_LEVEL_PRINT_PRINTERS_KEY
4369 int i;
4370 const char *printername, *sharename;
4372 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4374 torture_assert(tctx,
4375 test_GetPrinter_level(tctx, b, handle, 2, &info),
4376 "failed to get printer info level 2");
4378 printername = strip_unc(info.info2.printername);
4379 sharename = strip_unc(info.info2.sharename);
4381 #define test_sz(wname, iname) \
4382 do {\
4383 DATA_BLOB blob;\
4384 const char *str;\
4385 enum winreg_Type w_type;\
4386 uint32_t w_size;\
4387 uint32_t w_length;\
4388 uint8_t *w_data;\
4389 torture_assert(tctx,\
4390 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4391 &w_type, &w_size, &w_length, &w_data),\
4392 "failed to query winreg");\
4393 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4394 blob = data_blob(w_data, w_size);\
4395 str = reg_val_data_string(tctx, REG_SZ, blob);\
4396 if (w_size == 2 && iname == NULL) {\
4397 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4398 } else {\
4399 torture_assert_str_equal(tctx, str, iname,\
4400 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4402 } while(0);
4404 #define test_dword(wname, iname) \
4405 do {\
4406 uint32_t value;\
4407 enum winreg_Type w_type;\
4408 uint32_t w_size;\
4409 uint32_t w_length;\
4410 uint8_t *w_data;\
4411 torture_assert(tctx,\
4412 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4413 &w_type, &w_size, &w_length, &w_data),\
4414 "failed to query winreg");\
4415 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4416 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4417 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4418 value = IVAL(w_data, 0);\
4419 torture_assert_int_equal(tctx, value, iname,\
4420 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4421 } while(0);
4423 #define test_binary(wname, iname) \
4424 do {\
4425 enum winreg_Type w_type;\
4426 uint32_t w_size;\
4427 uint32_t w_length;\
4428 uint8_t *w_data;\
4429 torture_assert(tctx,\
4430 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4431 &w_type, &w_size, &w_length, &w_data),\
4432 "failed to query winreg");\
4433 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4434 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4435 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4436 "binary unequal");\
4437 } while(0);
4440 #define test_dm(wname, iname) \
4441 do {\
4442 DATA_BLOB blob;\
4443 struct spoolss_DeviceMode dm;\
4444 enum ndr_err_code ndr_err;\
4445 enum winreg_Type w_type;\
4446 uint32_t w_size;\
4447 uint32_t w_length;\
4448 uint8_t *w_data;\
4449 torture_assert(tctx,\
4450 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4451 &w_type, &w_size, &w_length, &w_data),\
4452 "failed to query winreg");\
4453 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4454 blob = data_blob(w_data, w_size);\
4455 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4456 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4457 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4458 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4459 "dm unequal");\
4460 } while(0);
4462 #define test_sd(wname, iname) \
4463 do {\
4464 DATA_BLOB blob;\
4465 struct security_descriptor sd;\
4466 enum ndr_err_code ndr_err;\
4467 enum winreg_Type w_type;\
4468 uint32_t w_size;\
4469 uint32_t w_length;\
4470 uint8_t *w_data;\
4471 torture_assert(tctx,\
4472 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4473 &w_type, &w_size, &w_length, &w_data),\
4474 "failed to query winreg");\
4475 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4476 blob = data_blob(w_data, w_size);\
4477 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4478 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4479 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4480 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4481 "sd unequal");\
4482 } while(0);
4484 #define test_multi_sz(wname, iname) \
4485 do {\
4486 DATA_BLOB blob;\
4487 const char **array;\
4488 enum winreg_Type w_type;\
4489 uint32_t w_size;\
4490 uint32_t w_length;\
4491 uint8_t *w_data;\
4492 int i;\
4493 torture_assert(tctx,\
4494 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4495 &w_type, &w_size, &w_length, &w_data),\
4496 "failed to query winreg");\
4497 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4498 blob = data_blob(w_data, w_size);\
4499 torture_assert(tctx, \
4500 pull_reg_multi_sz(tctx, &blob, &array),\
4501 "failed to pull multi sz");\
4502 for (i=0; array[i] != NULL; i++) {\
4503 torture_assert_str_equal(tctx, array[i], iname[i],\
4504 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4506 } while(0);
4508 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4509 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4510 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4512 torture_warning(tctx, "failed to check for winreg symlink");
4515 for (i=0; i < ARRAY_SIZE(keys); i++) {
4517 const char *printer_key;
4518 struct policy_handle key_handle;
4520 printer_key = talloc_asprintf(tctx, "%s\\%s",
4521 keys[i], printer_name);
4523 torture_assert(tctx,
4524 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4526 test_sz("Name", printername);
4527 test_sz("Share Name", sharename);
4528 test_sz("Port", info.info2.portname);
4529 test_sz("Printer Driver", info.info2.drivername);
4530 test_sz("Description", info.info2.comment);
4531 test_sz("Location", info.info2.location);
4532 test_sz("Separator File", info.info2.sepfile);
4533 test_sz("Print Processor", info.info2.printprocessor);
4534 test_sz("Datatype", info.info2.datatype);
4535 test_sz("Parameters", info.info2.parameters);
4536 /* winreg: 0, spoolss not */
4537 /* test_dword("Attributes", info.info2.attributes); */
4538 test_dword("Priority", info.info2.priority);
4539 test_dword("Default Priority", info.info2.defaultpriority);
4540 /* winreg: 60, spoolss: 0 */
4541 /* test_dword("StartTime", info.info2.starttime); */
4542 /* test_dword("UntilTime", info.info2.untiltime); */
4543 /* winreg != spoolss */
4544 /* test_dword("Status", info.info2.status); */
4545 test_dm("Default DevMode", info.info2.devmode);
4546 test_sd("Security", info.info2.secdesc);
4548 torture_assert(tctx,
4549 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4552 #undef test_dm
4553 #undef test_sd
4555 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4557 return true;
4560 static bool test_PrintProcessors(struct torture_context *tctx,
4561 struct dcerpc_binding_handle *b,
4562 const char *environment,
4563 struct dcerpc_binding_handle *winreg_handle,
4564 struct policy_handle *hive_handle)
4566 union spoolss_PrintProcessorInfo *info;
4567 uint32_t count;
4568 int i;
4570 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4572 torture_assert(tctx,
4573 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4574 "failed to enum print processors level 1");
4576 for (i=0; i < count; i++) {
4578 const char *processor_key;
4579 struct policy_handle key_handle;
4581 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4582 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4583 environment,
4584 info[i].info1.print_processor_name);
4586 torture_assert(tctx,
4587 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4589 /* nothing to check in there so far */
4591 torture_assert(tctx,
4592 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4595 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4597 return true;
4600 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4601 struct dcerpc_binding_handle *b,
4602 struct policy_handle *handle,
4603 const char *driver_name,
4604 const char *architecture,
4605 uint32_t level,
4606 uint32_t client_major_version,
4607 uint32_t client_minor_version,
4608 union spoolss_DriverInfo *info_p,
4609 WERROR *result);
4611 static const char *strip_path(const char *path)
4613 char *p;
4615 if (path == NULL) {
4616 return NULL;
4619 p = strrchr(path, '\\');
4620 if (p) {
4621 return p+1;
4624 return path;
4627 static const char **strip_paths(const char **path_array)
4629 int i;
4631 if (path_array == NULL) {
4632 return NULL;
4635 for (i=0; path_array[i] != NULL; i++) {
4636 path_array[i] = strip_path(path_array[i]);
4639 return path_array;
4642 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4644 time_t t;
4645 struct tm *tm;
4647 if (nt == 0) {
4648 return talloc_strdup(mem_ctx, "01/01/1601");
4651 t = nt_time_to_unix(nt);
4652 tm = localtime(&t);
4654 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4655 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4658 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4660 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4661 (unsigned)((v >> 48) & 0xFFFF),
4662 (unsigned)((v >> 32) & 0xFFFF),
4663 (unsigned)((v >> 16) & 0xFFFF),
4664 (unsigned)(v & 0xFFFF));
4667 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4668 struct dcerpc_binding_handle *b,
4669 struct policy_handle *handle,
4670 const char *printer_name,
4671 const char *driver_name,
4672 const char *environment,
4673 enum spoolss_DriverOSVersion version,
4674 struct dcerpc_binding_handle *winreg_handle,
4675 struct policy_handle *hive_handle,
4676 const char *server_name_slash)
4678 WERROR result;
4679 union spoolss_DriverInfo info;
4680 const char *driver_key;
4681 struct policy_handle key_handle;
4683 const char *driver_path;
4684 const char *data_file;
4685 const char *config_file;
4686 const char *help_file;
4687 const char **dependent_files;
4689 const char *driver_date;
4690 const char *inbox_driver_date;
4692 const char *driver_version;
4693 const char *inbox_driver_version;
4695 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4697 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4698 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4699 environment,
4700 version,
4701 driver_name);
4703 torture_assert(tctx,
4704 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4705 "failed to open driver key");
4707 if (torture_setting_bool(tctx, "samba3", false) ||
4708 torture_setting_bool(tctx, "w2k3", false)) {
4709 goto try_level6;
4712 if (handle) {
4713 torture_assert(tctx,
4714 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4715 "failed to get driver info level 8");
4716 } else {
4717 torture_assert(tctx,
4718 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4719 "failed to get driver info level 8");
4722 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4723 goto try_level6;
4726 driver_path = strip_path(info.info8.driver_path);
4727 data_file = strip_path(info.info8.data_file);
4728 config_file = strip_path(info.info8.config_file);
4729 help_file = strip_path(info.info8.help_file);
4730 dependent_files = strip_paths(info.info8.dependent_files);
4732 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4733 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4735 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4736 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4738 test_sz("Configuration File", config_file);
4739 test_sz("Data File", data_file);
4740 test_sz("Datatype", info.info8.default_datatype);
4741 test_sz("Driver", driver_path);
4742 test_sz("DriverDate", driver_date);
4743 test_sz("DriverVersion", driver_version);
4744 test_sz("HardwareID", info.info8.hardware_id);
4745 test_sz("Help File", help_file);
4746 test_sz("InfPath", info.info8.inf_path);
4747 test_sz("Manufacturer", info.info8.manufacturer_name);
4748 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4749 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4750 test_sz("Monitor", info.info8.monitor_name);
4751 test_sz("OEM URL", info.info8.manufacturer_url);
4752 test_sz("Print Processor", info.info8.print_processor);
4753 test_sz("Provider", info.info8.provider);
4754 test_sz("VendorSetup", info.info8.vendor_setup);
4755 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4756 test_multi_sz("Dependent Files", dependent_files);
4757 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4758 test_multi_sz("Previous Names", info.info8.previous_names);
4759 /* test_dword("Attributes", ?); */
4760 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4761 test_dword("Version", info.info8.version);
4762 /* test_dword("TempDir", ?); */
4764 try_level6:
4766 if (handle) {
4767 torture_assert(tctx,
4768 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4769 "failed to get driver info level 6");
4770 } else {
4771 torture_assert(tctx,
4772 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4773 "failed to get driver info level 6");
4776 driver_path = strip_path(info.info6.driver_path);
4777 data_file = strip_path(info.info6.data_file);
4778 config_file = strip_path(info.info6.config_file);
4779 help_file = strip_path(info.info6.help_file);
4780 dependent_files = strip_paths(info.info6.dependent_files);
4782 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4784 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4786 test_sz("Configuration File", config_file);
4787 test_sz("Data File", data_file);
4788 test_sz("Datatype", info.info6.default_datatype);
4789 test_sz("Driver", driver_path);
4790 if (torture_setting_bool(tctx, "w2k3", false)) {
4791 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4792 push_nttime(blob.data, 0, info.info6.driver_date);
4793 test_binary("DriverDate", blob);
4794 SBVAL(blob.data, 0, info.info6.driver_version);
4795 test_binary("DriverVersion", blob);
4796 } else {
4797 test_sz("DriverDate", driver_date);
4798 test_sz("DriverVersion", driver_version);
4800 test_sz("HardwareID", info.info6.hardware_id);
4801 test_sz("Help File", help_file);
4802 test_sz("Manufacturer", info.info6.manufacturer_name);
4803 test_sz("Monitor", info.info6.monitor_name);
4804 test_sz("OEM URL", info.info6.manufacturer_url);
4805 test_sz("Provider", info.info6.provider);
4806 test_multi_sz("Dependent Files", dependent_files);
4807 test_multi_sz("Previous Names", info.info6.previous_names);
4808 /* test_dword("Attributes", ?); */
4809 test_dword("Version", info.info6.version);
4810 /* test_dword("TempDir", ?); */
4812 if (handle) {
4813 torture_assert(tctx,
4814 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4815 "failed to get driver info level 3");
4816 } else {
4817 torture_assert(tctx,
4818 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4819 "failed to get driver info level 3");
4822 driver_path = strip_path(info.info3.driver_path);
4823 data_file = strip_path(info.info3.data_file);
4824 config_file = strip_path(info.info3.config_file);
4825 help_file = strip_path(info.info3.help_file);
4826 dependent_files = strip_paths(info.info3.dependent_files);
4828 test_sz("Configuration File", config_file);
4829 test_sz("Data File", data_file);
4830 test_sz("Datatype", info.info3.default_datatype);
4831 test_sz("Driver", driver_path);
4832 test_sz("Help File", help_file);
4833 test_sz("Monitor", info.info3.monitor_name);
4834 test_multi_sz("Dependent Files", dependent_files);
4835 /* test_dword("Attributes", ?); */
4836 test_dword("Version", info.info3.version);
4837 /* test_dword("TempDir", ?); */
4840 torture_assert(tctx,
4841 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4843 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4845 return true;
4848 #undef test_sz
4849 #undef test_dword
4851 static bool test_SetPrinterData(struct torture_context *tctx,
4852 struct dcerpc_binding_handle *b,
4853 struct policy_handle *handle,
4854 const char *value_name,
4855 enum winreg_Type type,
4856 uint8_t *data,
4857 uint32_t offered)
4859 struct spoolss_SetPrinterData r;
4861 r.in.handle = handle;
4862 r.in.value_name = value_name;
4863 r.in.type = type;
4864 r.in.data = data;
4865 r.in.offered = offered;
4867 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4868 r.in.value_name);
4870 torture_assert_ntstatus_ok(tctx,
4871 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4872 "SetPrinterData failed");
4873 torture_assert_werr_ok(tctx, r.out.result,
4874 "SetPrinterData failed");
4876 return true;
4879 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4880 struct dcerpc_binding_handle *b,
4881 struct policy_handle *handle,
4882 const char *printer_name,
4883 struct dcerpc_binding_handle *winreg_handle,
4884 struct policy_handle *hive_handle)
4886 const char *values[] = {
4887 "spootyfoot",
4888 "spooty\\foot",
4889 #if 0
4890 /* FIXME: not working with s3 atm. */
4891 "spooty,foot",
4892 "spooty,fo,ot",
4893 #endif
4894 "spooty foot",
4895 #if 0
4896 /* FIXME: not working with s3 atm. */
4897 "spooty\\fo,ot",
4898 "spooty,fo\\ot"
4899 #endif
4901 int i;
4903 for (i=0; i < ARRAY_SIZE(values); i++) {
4905 enum winreg_Type type, expected_type = REG_SZ;
4906 DATA_BLOB blob;
4907 uint8_t *data;
4908 uint32_t needed;
4910 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4911 type = REG_SZ;
4913 torture_assert(tctx,
4914 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4915 "SetPrinterData failed");
4917 torture_assert(tctx,
4918 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4919 "GetPrinterData failed");
4921 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4922 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4923 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4925 if (winreg_handle && hive_handle) {
4927 enum winreg_Type w_type;
4928 uint32_t w_size;
4929 uint32_t w_length;
4930 uint8_t *w_data;
4932 torture_assert(tctx,
4933 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4934 printer_name, "PrinterDriverData", values[i],
4935 &w_type, &w_size, &w_length, &w_data), "");
4937 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4938 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4939 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4940 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4943 torture_assert(tctx,
4944 test_DeletePrinterData(tctx, b, handle, values[i]),
4945 "DeletePrinterData failed");
4948 return true;
4952 static bool test_EnumPrinterKey(struct torture_context *tctx,
4953 struct dcerpc_binding_handle *b,
4954 struct policy_handle *handle,
4955 const char *key_name,
4956 const char ***array);
4958 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4959 struct dcerpc_binding_handle *b,
4960 struct policy_handle *handle,
4961 const char *key_name,
4962 const char *value_name,
4963 enum winreg_Type type,
4964 uint8_t *data,
4965 uint32_t offered)
4967 NTSTATUS status;
4968 struct spoolss_SetPrinterDataEx r;
4970 r.in.handle = handle;
4971 r.in.key_name = key_name;
4972 r.in.value_name = value_name;
4973 r.in.type = type;
4974 r.in.data = data;
4975 r.in.offered = offered;
4977 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4978 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4980 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4982 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4983 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4985 return true;
4988 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4989 struct dcerpc_pipe *p,
4990 struct policy_handle *handle)
4992 struct dcerpc_binding_handle *b = p->binding_handle;
4993 const char *value_name = "dog";
4994 const char *keys[] = {
4995 "torturedataex",
4996 "torture data ex",
4997 "torturedataex_with_subkey\\subkey",
4998 "torturedataex_with_subkey\\subkey:0",
4999 "torturedataex_with_subkey\\subkey:1",
5000 "torturedataex_with_subkey\\subkey\\subsubkey",
5001 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5002 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5003 "torture,data",
5004 "torture,data,ex",
5005 "torture,data\\ex",
5006 "torture\\data,ex",
5007 "torture/data",
5008 "torture/data ex",
5009 "torture/data ex/sub",
5010 "torture//data",
5011 "torture//data ex",
5012 "torture//data ex/sub",
5013 "torture//data ex//sub",
5015 int i;
5017 for (i=0; i < ARRAY_SIZE(keys); i++) {
5019 char *c;
5020 const char *key;
5021 enum winreg_Type type;
5022 DATA_BLOB blob_in, blob_out;
5023 const char **subkeys;
5024 uint32_t ecount;
5025 struct spoolss_PrinterEnumValues *einfo;
5026 uint32_t needed;
5028 blob_in = data_blob_talloc(tctx, NULL, 42);
5030 generate_random_buffer(blob_in.data, blob_in.length);
5032 torture_assert(tctx,
5033 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5034 "failed to call SetPrinterDataEx");
5036 torture_assert(tctx,
5037 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5038 "failed to call GetPrinterDataEx");
5040 blob_out.length = needed;
5041 torture_assert(tctx,
5042 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5043 "failed to call EnumPrinterDataEx");
5045 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5046 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5047 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5049 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5050 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5051 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5052 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5053 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5054 if (einfo[0].data_length > 0) {
5055 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5058 key = talloc_strdup(tctx, keys[i]);
5060 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5061 return false;
5064 c = strchr(key, '\\');
5065 if (c) {
5066 int k;
5068 /* we have subkeys */
5070 *c = 0;
5072 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5073 return false;
5076 for (k=0; subkeys && subkeys[k]; k++) {
5078 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5080 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5081 return false;
5085 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5086 return false;
5089 } else {
5090 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5091 return false;
5096 return true;
5099 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5100 struct dcerpc_pipe *p,
5101 struct policy_handle *handle)
5103 struct dcerpc_binding_handle *b = p->binding_handle;
5104 const char *key = "torturedataex";
5105 const char *values[] = {
5106 "torture_value",
5107 "torture value",
5108 "torture,value",
5109 "torture/value",
5110 "torture\\value",
5111 "torture\\\\value"
5113 int i;
5115 for (i=0; i < ARRAY_SIZE(values); i++) {
5117 enum winreg_Type type;
5118 DATA_BLOB blob_in, blob_out;
5119 uint32_t ecount;
5120 struct spoolss_PrinterEnumValues *einfo;
5121 uint32_t needed;
5123 if (torture_setting_bool(tctx, "samba3", false)) {
5124 char *q;
5125 q = strrchr(values[i], ',');
5126 if (q) {
5127 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5128 values[i]);
5129 continue;
5133 blob_in = data_blob_talloc(tctx, NULL, 42);
5135 generate_random_buffer(blob_in.data, blob_in.length);
5137 torture_assert(tctx,
5138 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5139 "failed to call SetPrinterDataEx");
5141 torture_assert(tctx,
5142 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5143 "failed to call GetPrinterDataEx");
5145 blob_out.length = needed;
5146 torture_assert(tctx,
5147 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5148 "failed to call EnumPrinterDataEx");
5150 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5151 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5152 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5154 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5155 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5156 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5157 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5158 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5159 if (einfo[0].data_length > 0) {
5160 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5163 torture_assert(tctx,
5164 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5165 "failed to call DeletePrinterDataEx");
5168 return true;
5172 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5173 struct dcerpc_pipe *p,
5174 struct policy_handle *handle,
5175 const char *printername,
5176 struct dcerpc_binding_handle *winreg_handle,
5177 struct policy_handle *hive_handle)
5179 struct dcerpc_binding_handle *b = p->binding_handle;
5180 const char *value_name = "dog";
5181 const char *key_name = "torturedataex";
5182 enum winreg_Type types[] = {
5183 REG_SZ,
5184 REG_MULTI_SZ,
5185 REG_DWORD,
5186 REG_BINARY
5188 const char *str = "abcdefghi";
5189 int t, s;
5191 for (t=0; t < ARRAY_SIZE(types); t++) {
5192 for (s=0; s < strlen(str); s++) {
5194 enum winreg_Type type;
5195 const char *string = talloc_strndup(tctx, str, s);
5196 const char *array[2];
5197 DATA_BLOB blob = data_blob_string_const(string);
5198 DATA_BLOB data;
5199 uint8_t *data_out;
5200 uint32_t needed, offered = 0;
5201 uint32_t ecount;
5202 struct spoolss_PrinterEnumValues *einfo;
5204 array[0] = talloc_strdup(tctx, string);
5205 array[1] = NULL;
5207 if (types[t] == REG_DWORD) {
5208 s = 0xffff;
5211 switch (types[t]) {
5212 case REG_BINARY:
5213 data = blob;
5214 offered = blob.length;
5215 break;
5216 case REG_DWORD:
5217 data = data_blob_talloc(tctx, NULL, 4);
5218 SIVAL(data.data, 0, 0x12345678);
5219 offered = 4;
5220 break;
5221 case REG_SZ:
5222 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5223 type = REG_SZ;
5224 offered = data.length;
5225 /*strlen_m_term(data.string)*2;*/
5226 break;
5227 case REG_MULTI_SZ:
5228 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5229 type = REG_MULTI_SZ;
5230 offered = data.length;
5231 break;
5232 default:
5233 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5236 torture_assert(tctx,
5237 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5238 "failed to call SetPrinterDataEx");
5240 torture_assert(tctx,
5241 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5242 "failed to call GetPrinterDataEx");
5244 torture_assert(tctx,
5245 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5246 "failed to call EnumPrinterDataEx");
5248 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5249 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5250 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5252 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5253 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5254 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5255 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5256 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5257 if (einfo[0].data_length > 0) {
5258 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5261 if (winreg_handle && hive_handle) {
5262 enum winreg_Type w_type;
5263 uint32_t w_size;
5264 uint32_t w_length;
5265 uint8_t *w_data;
5267 torture_assert(tctx,
5268 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5269 printername, key_name, value_name,
5270 &w_type, &w_size, &w_length, &w_data), "");
5272 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5273 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5274 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5275 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5278 torture_assert(tctx,
5279 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5280 "failed to call DeletePrinterDataEx");
5284 return true;
5287 static bool test_PrinterData_winreg(struct torture_context *tctx,
5288 struct dcerpc_pipe *p,
5289 struct policy_handle *handle,
5290 const char *printer_name)
5292 struct dcerpc_binding_handle *b = p->binding_handle;
5293 struct dcerpc_pipe *p2;
5294 bool ret = true;
5295 struct policy_handle hive_handle;
5296 struct dcerpc_binding_handle *b2;
5298 torture_assert_ntstatus_ok(tctx,
5299 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5300 "could not open winreg pipe");
5301 b2 = p2->binding_handle;
5303 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5305 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5306 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5308 test_winreg_CloseKey(tctx, b2, &hive_handle);
5310 talloc_free(p2);
5312 return ret;
5315 static bool test_Forms_winreg(struct torture_context *tctx,
5316 struct dcerpc_binding_handle *b,
5317 struct policy_handle *handle,
5318 bool print_server,
5319 const char *printer_name)
5321 struct dcerpc_pipe *p2;
5322 bool ret = true;
5323 struct policy_handle hive_handle;
5324 struct dcerpc_binding_handle *b2;
5326 torture_assert_ntstatus_ok(tctx,
5327 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5328 "could not open winreg pipe");
5329 b2 = p2->binding_handle;
5331 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5333 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5335 test_winreg_CloseKey(tctx, b2, &hive_handle);
5337 talloc_free(p2);
5339 return ret;
5342 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5343 struct dcerpc_pipe *p,
5344 struct policy_handle *handle,
5345 const char *printer_name)
5347 struct dcerpc_binding_handle *b = p->binding_handle;
5348 struct dcerpc_pipe *p2;
5349 bool ret = true;
5350 struct policy_handle hive_handle;
5351 struct dcerpc_binding_handle *b2;
5353 torture_assert_ntstatus_ok(tctx,
5354 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5355 "could not open winreg pipe");
5356 b2 = p2->binding_handle;
5358 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5360 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5362 test_winreg_CloseKey(tctx, b2, &hive_handle);
5364 talloc_free(p2);
5366 return ret;
5369 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5370 struct dcerpc_pipe *p,
5371 struct policy_handle *handle,
5372 const char *printer_name,
5373 const char *driver_name,
5374 const char *environment,
5375 enum spoolss_DriverOSVersion version)
5377 struct dcerpc_binding_handle *b = p->binding_handle;
5378 struct dcerpc_pipe *p2;
5379 bool ret = true;
5380 struct policy_handle hive_handle;
5381 struct dcerpc_binding_handle *b2;
5383 torture_assert_ntstatus_ok(tctx,
5384 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5385 "could not open winreg pipe");
5386 b2 = p2->binding_handle;
5388 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5390 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5392 test_winreg_CloseKey(tctx, b2, &hive_handle);
5394 talloc_free(p2);
5396 return ret;
5399 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5400 struct dcerpc_binding_handle *b,
5401 const char *environment)
5403 struct dcerpc_pipe *p2;
5404 bool ret = true;
5405 struct policy_handle hive_handle;
5406 struct dcerpc_binding_handle *b2;
5408 torture_assert_ntstatus_ok(tctx,
5409 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5410 "could not open winreg pipe");
5411 b2 = p2->binding_handle;
5413 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5415 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5417 test_winreg_CloseKey(tctx, b2, &hive_handle);
5419 talloc_free(p2);
5421 return ret;
5424 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5425 struct dcerpc_pipe *p,
5426 struct policy_handle *handle,
5427 const char *printer_name)
5429 struct spoolss_SetPrinterInfoCtr info_ctr;
5430 struct spoolss_DevmodeContainer devmode_ctr;
5431 struct sec_desc_buf secdesc_ctr;
5432 union spoolss_SetPrinterInfo sinfo;
5433 union spoolss_PrinterInfo info;
5434 struct dcerpc_binding_handle *b = p->binding_handle;
5435 const char *pname;
5437 ZERO_STRUCT(info_ctr);
5438 ZERO_STRUCT(devmode_ctr);
5439 ZERO_STRUCT(secdesc_ctr);
5441 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5443 torture_assert(tctx,
5444 test_GetPrinter_level(tctx, b, handle, 2, &info),
5445 "failed to query Printer level 2");
5447 torture_assert(tctx,
5448 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5449 "failed to convert");
5451 info_ctr.level = 2;
5452 info_ctr.info = sinfo;
5454 #define TEST_SZ(wname, iname) \
5455 do {\
5456 enum winreg_Type type;\
5457 uint8_t *data;\
5458 uint32_t needed;\
5459 DATA_BLOB blob;\
5460 const char *str;\
5461 torture_assert(tctx,\
5462 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5463 "failed to query");\
5464 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5465 blob = data_blob_const(data, needed);\
5466 torture_assert(tctx,\
5467 pull_reg_sz(tctx, &blob, &str),\
5468 "failed to pull REG_SZ");\
5469 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5470 } while(0);
5473 #define TEST_SET_SZ(wname, iname, val) \
5474 do {\
5475 enum winreg_Type type;\
5476 uint8_t *data;\
5477 uint32_t needed;\
5478 DATA_BLOB blob;\
5479 const char *str;\
5480 sinfo.info2->iname = val;\
5481 torture_assert(tctx,\
5482 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5483 "failed to call SetPrinter");\
5484 torture_assert(tctx,\
5485 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5486 "failed to query");\
5487 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5488 blob = data_blob_const(data, needed);\
5489 torture_assert(tctx,\
5490 pull_reg_sz(tctx, &blob, &str),\
5491 "failed to pull REG_SZ");\
5492 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5493 } while(0);
5495 #define TEST_SET_DWORD(wname, iname, val) \
5496 do {\
5497 enum winreg_Type type;\
5498 uint8_t *data;\
5499 uint32_t needed;\
5500 uint32_t value;\
5501 sinfo.info2->iname = val;\
5502 torture_assert(tctx,\
5503 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5504 "failed to call SetPrinter");\
5505 torture_assert(tctx,\
5506 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5507 "failed to query");\
5508 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5509 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5510 value = IVAL(data, 0); \
5511 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5512 } while(0);
5514 TEST_SET_SZ("description", comment, "newval");
5515 TEST_SET_SZ("location", location, "newval");
5516 TEST_SET_SZ("driverName", drivername, "newval");
5517 /* TEST_SET_DWORD("priority", priority, 25); */
5519 torture_assert(tctx,
5520 test_GetPrinter_level(tctx, b, handle, 2, &info),
5521 "failed to query Printer level 2");
5523 TEST_SZ("description", info.info2.comment);
5524 TEST_SZ("driverName", info.info2.drivername);
5525 TEST_SZ("location", info.info2.location);
5527 pname = strrchr(info.info2.printername, '\\');
5528 if (pname == NULL) {
5529 pname = info.info2.printername;
5530 } else {
5531 pname++;
5533 TEST_SZ("printerName", pname);
5534 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5535 /* TEST_SZ("printShareName", info.info2.sharename); */
5537 /* FIXME gd: complete the list */
5539 #undef TEST_SZ
5540 #undef TEST_SET_SZ
5541 #undef TEST_DWORD
5543 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5545 return true;
5548 static bool test_print_processors_winreg(struct torture_context *tctx,
5549 void *private_data)
5551 struct test_spoolss_context *ctx =
5552 talloc_get_type_abort(private_data, struct test_spoolss_context);
5553 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5554 struct dcerpc_binding_handle *b = p->binding_handle;
5556 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5559 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5560 struct dcerpc_binding_handle *b,
5561 struct policy_handle *handle,
5562 uint32_t *change_id)
5564 enum winreg_Type type;
5565 uint8_t *data;
5566 uint32_t needed;
5568 torture_assert(tctx,
5569 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5570 "failed to call GetPrinterData");
5572 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5573 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5575 *change_id = IVAL(data, 0);
5577 return true;
5580 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5581 struct dcerpc_pipe *p,
5582 struct policy_handle *handle,
5583 uint32_t *change_id)
5585 enum winreg_Type type;
5586 uint8_t *data;
5587 uint32_t needed;
5589 torture_assert(tctx,
5590 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5591 "failed to call GetPrinterData");
5593 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5594 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5596 *change_id = IVAL(data, 0);
5598 return true;
5601 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5602 struct dcerpc_binding_handle *b,
5603 struct policy_handle *handle,
5604 uint32_t *change_id)
5606 union spoolss_PrinterInfo info;
5608 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5609 "failed to query Printer level 0");
5611 *change_id = info.info0.change_id;
5613 return true;
5616 static bool test_ChangeID(struct torture_context *tctx,
5617 struct dcerpc_pipe *p,
5618 struct policy_handle *handle)
5620 uint32_t change_id, change_id_ex, change_id_info;
5621 uint32_t change_id2, change_id_ex2, change_id_info2;
5622 union spoolss_PrinterInfo info;
5623 const char *comment;
5624 struct dcerpc_binding_handle *b = p->binding_handle;
5626 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5628 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5629 "failed to query for ChangeID");
5630 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5631 "failed to query for ChangeID");
5632 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5633 "failed to query for ChangeID");
5635 torture_assert_int_equal(tctx, change_id, change_id_ex,
5636 "change_ids should all be equal");
5637 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5638 "change_ids should all be equal");
5641 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5643 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5644 "failed to query for ChangeID");
5645 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5646 "failed to query Printer level 2");
5647 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5648 "failed to query for ChangeID");
5649 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5650 "failed to query for ChangeID");
5651 torture_assert_int_equal(tctx, change_id, change_id_ex,
5652 "change_id should not have changed");
5653 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5654 "change_id should not have changed");
5657 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5659 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5660 "failed to query for ChangeID");
5661 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5662 "failed to query for ChangeID");
5663 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5664 "failed to query for ChangeID");
5665 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5666 "failed to query Printer level 2");
5667 comment = talloc_strdup(tctx, info.info2.comment);
5670 struct spoolss_SetPrinterInfoCtr info_ctr;
5671 struct spoolss_DevmodeContainer devmode_ctr;
5672 struct sec_desc_buf secdesc_ctr;
5673 union spoolss_SetPrinterInfo sinfo;
5675 ZERO_STRUCT(info_ctr);
5676 ZERO_STRUCT(devmode_ctr);
5677 ZERO_STRUCT(secdesc_ctr);
5680 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5681 sinfo.info2->comment = "torture_comment";
5683 info_ctr.level = 2;
5684 info_ctr.info = sinfo;
5686 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5687 "failed to call SetPrinter");
5689 sinfo.info2->comment = comment;
5691 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5692 "failed to call SetPrinter");
5696 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5697 "failed to query for ChangeID");
5698 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5699 "failed to query for ChangeID");
5700 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5701 "failed to query for ChangeID");
5703 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5704 "change_ids should all be equal");
5705 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5706 "change_ids should all be equal");
5708 torture_assert(tctx, (change_id < change_id2),
5709 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5710 change_id2, change_id));
5711 torture_assert(tctx, (change_id_ex < change_id_ex2),
5712 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5713 change_id_ex2, change_id_ex));
5714 torture_assert(tctx, (change_id_info < change_id_info2),
5715 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5716 change_id_info2, change_id_info));
5718 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5720 return true;
5723 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5724 struct dcerpc_pipe *p,
5725 struct policy_handle *handle)
5727 NTSTATUS status;
5728 struct dcerpc_binding *b;
5729 struct dcerpc_pipe *p2;
5730 struct spoolss_ClosePrinter cp;
5732 /* only makes sense on SMB */
5733 if (p->conn->transport.transport != NCACN_NP) {
5734 return true;
5737 torture_comment(tctx, "Testing close on secondary pipe\n");
5739 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5740 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5742 status = dcerpc_secondary_connection(p, &p2, b);
5743 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5745 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5746 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5748 cp.in.handle = handle;
5749 cp.out.handle = handle;
5751 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5752 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5753 "ERROR: Allowed close on secondary connection");
5755 talloc_free(p2);
5757 return true;
5760 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5761 struct dcerpc_binding_handle *b, const char *name)
5763 NTSTATUS status;
5764 struct spoolss_OpenPrinter op;
5765 struct spoolss_OpenPrinterEx opEx;
5766 struct policy_handle handle;
5767 bool ret = true;
5769 op.in.printername = name;
5770 op.in.datatype = NULL;
5771 op.in.devmode_ctr.devmode= NULL;
5772 op.in.access_mask = 0;
5773 op.out.handle = &handle;
5775 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5777 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5778 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5779 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5780 "unexpected result");
5782 if (W_ERROR_IS_OK(op.out.result)) {
5783 ret &=test_ClosePrinter(tctx, b, &handle);
5786 opEx.in.printername = name;
5787 opEx.in.datatype = NULL;
5788 opEx.in.devmode_ctr.devmode = NULL;
5789 opEx.in.access_mask = 0;
5790 opEx.in.userlevel_ctr.level = 1;
5791 opEx.in.userlevel_ctr.user_info.level1 = NULL;
5792 opEx.out.handle = &handle;
5794 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5796 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5797 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5798 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5799 "unexpected result");
5801 if (W_ERROR_IS_OK(opEx.out.result)) {
5802 ret &=test_ClosePrinter(tctx, b, &handle);
5805 return ret;
5808 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5809 void *private_data)
5811 struct test_spoolss_context *ctx =
5812 talloc_get_type_abort(private_data, struct test_spoolss_context);
5814 const char *badnames[] = {
5815 "__INVALID_PRINTER__",
5816 "\\\\__INVALID_HOST__",
5818 "\\\\\\",
5819 "\\\\\\__INVALID_PRINTER__"
5821 const char *badname;
5822 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5823 const char *server_name = dcerpc_server_name(p);
5824 struct dcerpc_binding_handle *b = p->binding_handle;
5825 int i;
5827 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5828 torture_assert(tctx,
5829 test_OpenPrinter_badname(tctx, b, badnames[i]),
5830 "");
5833 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5834 torture_assert(tctx,
5835 test_OpenPrinter_badname(tctx, b, badname),
5836 "");
5838 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5839 torture_assert(tctx,
5840 test_OpenPrinter_badname(tctx, b, badname),
5841 "");
5843 return true;
5846 static bool test_OpenPrinter(struct torture_context *tctx,
5847 struct dcerpc_pipe *p,
5848 const char *name,
5849 const char *environment,
5850 bool open_only)
5852 NTSTATUS status;
5853 struct spoolss_OpenPrinter r;
5854 struct policy_handle handle;
5855 bool ret = true;
5856 struct dcerpc_binding_handle *b = p->binding_handle;
5858 r.in.printername = name;
5859 r.in.datatype = NULL;
5860 r.in.devmode_ctr.devmode= NULL;
5861 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5862 r.out.handle = &handle;
5864 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5866 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5868 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5870 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5872 if (open_only) {
5873 goto close_printer;
5876 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5877 ret = false;
5880 if (!torture_setting_bool(tctx, "samba3", false)) {
5881 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5882 ret = false;
5886 close_printer:
5887 if (!test_ClosePrinter(tctx, b, &handle)) {
5888 ret = false;
5891 return ret;
5894 static bool test_OpenPrinterEx(struct torture_context *tctx,
5895 struct dcerpc_binding_handle *b,
5896 const char *printername,
5897 const char *datatype,
5898 struct spoolss_DeviceMode *devmode,
5899 uint32_t access_mask,
5900 struct spoolss_UserLevelCtr *userlevel_ctr,
5901 struct policy_handle *handle,
5902 WERROR expected_result)
5904 struct spoolss_OpenPrinterEx r;
5906 r.in.printername = printername;
5907 r.in.datatype = datatype;
5908 r.in.devmode_ctr.devmode= devmode;
5909 r.in.access_mask = access_mask;
5910 r.in.userlevel_ctr = *userlevel_ctr;
5911 r.out.handle = handle;
5913 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5915 torture_assert_ntstatus_ok(tctx,
5916 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5917 "OpenPrinterEx failed");
5919 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5920 "OpenPrinterEx failed");
5922 return true;
5925 static bool call_OpenPrinterEx(struct torture_context *tctx,
5926 struct dcerpc_pipe *p,
5927 const char *name,
5928 struct spoolss_DeviceMode *devmode,
5929 struct policy_handle *handle)
5931 struct spoolss_UserLevelCtr userlevel_ctr;
5932 struct spoolss_UserLevel1 userlevel1;
5933 struct dcerpc_binding_handle *b = p->binding_handle;
5935 userlevel1.size = 1234;
5936 userlevel1.client = "hello";
5937 userlevel1.user = "spottyfoot!";
5938 userlevel1.build = 1;
5939 userlevel1.major = 2;
5940 userlevel1.minor = 3;
5941 userlevel1.processor = 4;
5943 userlevel_ctr.level = 1;
5944 userlevel_ctr.user_info.level1 = &userlevel1;
5946 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5947 SEC_FLAG_MAXIMUM_ALLOWED,
5948 &userlevel_ctr,
5949 handle,
5950 WERR_OK);
5953 static bool test_printer_rename(struct torture_context *tctx,
5954 void *private_data)
5956 struct torture_printer_context *t =
5957 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5958 struct dcerpc_pipe *p = t->spoolss_pipe;
5960 bool ret = true;
5961 union spoolss_PrinterInfo info;
5962 union spoolss_SetPrinterInfo sinfo;
5963 struct spoolss_SetPrinterInfoCtr info_ctr;
5964 struct spoolss_DevmodeContainer devmode_ctr;
5965 struct sec_desc_buf secdesc_ctr;
5966 const char *printer_name;
5967 const char *printer_name_orig;
5968 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5969 struct policy_handle new_handle;
5970 const char *q;
5971 struct dcerpc_binding_handle *b = p->binding_handle;
5973 ZERO_STRUCT(devmode_ctr);
5974 ZERO_STRUCT(secdesc_ctr);
5976 torture_comment(tctx, "Testing Printer rename operations\n");
5978 torture_assert(tctx,
5979 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5980 "failed to call GetPrinter level 2");
5982 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5984 q = strrchr(info.info2.printername, '\\');
5985 if (q) {
5986 torture_warning(tctx,
5987 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5990 torture_assert(tctx,
5991 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5993 sinfo.info2->printername = printer_name_new;
5995 info_ctr.level = 2;
5996 info_ctr.info = sinfo;
5998 torture_assert(tctx,
5999 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6000 "failed to call SetPrinter level 2");
6002 torture_assert(tctx,
6003 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6004 "failed to call GetPrinter level 2");
6006 printer_name = talloc_strdup(tctx, info.info2.printername);
6008 q = strrchr(info.info2.printername, '\\');
6009 if (q) {
6010 torture_warning(tctx,
6011 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6012 q++;
6013 printer_name = q;
6016 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6017 "new printer name was not set");
6019 /* samba currently cannot fully rename printers */
6020 if (!torture_setting_bool(tctx, "samba3", false)) {
6021 torture_assert(tctx,
6022 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6023 "still can open printer with oldname after rename");
6024 } else {
6025 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6028 torture_assert(tctx,
6029 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6030 "failed to open printer with new name");
6032 torture_assert(tctx,
6033 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6034 "failed to call GetPrinter level 2");
6036 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6037 "new printer name was not set");
6039 torture_assert(tctx,
6040 test_ClosePrinter(tctx, b, &new_handle),
6041 "failed to close printer");
6043 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6045 return ret;
6048 static bool test_openprinter(struct torture_context *tctx,
6049 struct dcerpc_binding_handle *b,
6050 const char *real_printername)
6052 struct spoolss_UserLevelCtr userlevel_ctr;
6053 struct policy_handle handle;
6054 struct spoolss_UserLevel1 userlevel1;
6055 const char *printername = NULL;
6056 int i;
6058 struct {
6059 const char *suffix;
6060 WERROR expected_result;
6061 } tests[] = {
6063 .suffix = "rubbish",
6064 .expected_result = WERR_INVALID_PRINTER_NAME
6066 .suffix = ", LocalOnl",
6067 .expected_result = WERR_INVALID_PRINTER_NAME
6069 .suffix = ", localOnly",
6070 .expected_result = WERR_INVALID_PRINTER_NAME
6072 .suffix = ", localonl",
6073 .expected_result = WERR_INVALID_PRINTER_NAME
6075 .suffix = ",LocalOnl",
6076 .expected_result = WERR_INVALID_PRINTER_NAME
6078 .suffix = ",localOnl2",
6079 .expected_result = WERR_INVALID_PRINTER_NAME
6081 .suffix = ", DrvConver2t",
6082 .expected_result = WERR_INVALID_PRINTER_NAME
6084 .suffix = ", drvconvert",
6085 .expected_result = WERR_INVALID_PRINTER_NAME
6087 .suffix = ",drvconvert",
6088 .expected_result = WERR_INVALID_PRINTER_NAME
6090 .suffix = ", DrvConvert",
6091 .expected_result = WERR_OK
6093 .suffix = " , DrvConvert",
6094 .expected_result = WERR_INVALID_PRINTER_NAME
6096 .suffix = ",DrvConvert",
6097 .expected_result = WERR_OK
6099 .suffix = ", DrvConvertsadfasdf",
6100 .expected_result = WERR_OK
6102 .suffix = ",DrvConvertasdfasd",
6103 .expected_result = WERR_OK
6105 .suffix = ", LocalOnly",
6106 .expected_result = WERR_OK
6108 .suffix = " , LocalOnly",
6109 .expected_result = WERR_INVALID_PRINTER_NAME
6111 .suffix = ",LocalOnly",
6112 .expected_result = WERR_OK
6114 .suffix = ", LocalOnlysagi4gjfkd",
6115 .expected_result = WERR_OK
6117 .suffix = ",LocalOnlysagi4gjfkd",
6118 .expected_result = WERR_OK
6122 userlevel1.size = 1234;
6123 userlevel1.client = "hello";
6124 userlevel1.user = "spottyfoot!";
6125 userlevel1.build = 1;
6126 userlevel1.major = 2;
6127 userlevel1.minor = 3;
6128 userlevel1.processor = 4;
6130 userlevel_ctr.level = 1;
6131 userlevel_ctr.user_info.level1 = &userlevel1;
6133 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6135 torture_assert(tctx,
6136 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6137 &userlevel_ctr, &handle,
6138 WERR_OK),
6139 "OpenPrinterEx failed");
6140 test_ClosePrinter(tctx, b, &handle);
6142 for (i=0; i < ARRAY_SIZE(tests); i++) {
6144 printername = talloc_asprintf(tctx, "%s%s",
6145 real_printername,
6146 tests[i].suffix);
6148 torture_assert(tctx,
6149 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6150 &userlevel_ctr, &handle,
6151 tests[i].expected_result),
6152 "OpenPrinterEx failed");
6153 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6154 test_ClosePrinter(tctx, b, &handle);
6158 return true;
6162 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6163 struct dcerpc_pipe *p,
6164 const char *name,
6165 const char *environment)
6167 struct policy_handle handle;
6168 bool ret = true;
6169 struct dcerpc_binding_handle *b = p->binding_handle;
6171 if (!test_openprinter(tctx, b, name)) {
6172 return false;
6175 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6176 return false;
6179 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6180 ret = false;
6183 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6184 ret = false;
6187 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6188 ret = false;
6191 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6192 ret = false;
6195 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6196 ret = false;
6199 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6200 ret = false;
6203 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6204 ret = false;
6207 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6208 ret = false;
6211 if (!test_printer_all_keys(tctx, b, &handle)) {
6212 ret = false;
6215 if (!test_PausePrinter(tctx, b, &handle)) {
6216 ret = false;
6219 if (!test_DoPrintTest(tctx, b, &handle)) {
6220 ret = false;
6223 if (!test_ResumePrinter(tctx, b, &handle)) {
6224 ret = false;
6227 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6228 ret = false;
6231 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6232 ret = false;
6235 if (!torture_setting_bool(tctx, "samba3", false)) {
6236 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6237 ret = false;
6241 if (!test_ClosePrinter(tctx, b, &handle)) {
6242 ret = false;
6245 return ret;
6248 static bool test_EnumPrinters_old(struct torture_context *tctx,
6249 void *private_data)
6251 struct test_spoolss_context *ctx =
6252 talloc_get_type_abort(private_data, struct test_spoolss_context);
6253 struct spoolss_EnumPrinters r;
6254 NTSTATUS status;
6255 uint16_t levels[] = {1, 2, 4, 5};
6256 int i;
6257 bool ret = true;
6258 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6259 struct dcerpc_binding_handle *b = p->binding_handle;
6261 for (i=0;i<ARRAY_SIZE(levels);i++) {
6262 union spoolss_PrinterInfo *info;
6263 int j;
6264 uint32_t needed;
6265 uint32_t count;
6267 r.in.flags = PRINTER_ENUM_LOCAL;
6268 r.in.server = "";
6269 r.in.level = levels[i];
6270 r.in.buffer = NULL;
6271 r.in.offered = 0;
6272 r.out.needed = &needed;
6273 r.out.count = &count;
6274 r.out.info = &info;
6276 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6278 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6279 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6281 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6282 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6283 r.in.buffer = &blob;
6284 r.in.offered = needed;
6285 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6288 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6290 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6292 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6294 if (!info) {
6295 torture_comment(tctx, "No printers returned\n");
6296 return true;
6299 for (j=0;j<count;j++) {
6300 if (r.in.level == 1) {
6301 char *unc = talloc_strdup(tctx, info[j].info1.name);
6302 char *slash, *name, *full_name;
6303 name = unc;
6304 if (unc[0] == '\\' && unc[1] == '\\') {
6305 unc +=2;
6307 slash = strchr(unc, '\\');
6308 if (slash) {
6309 slash++;
6310 name = slash;
6312 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6313 dcerpc_server_name(p), name);
6314 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6315 ret = false;
6317 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6318 ret = false;
6320 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6321 ret = false;
6323 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6324 ret = false;
6330 return ret;
6333 static bool test_EnumPrinters_level(struct torture_context *tctx,
6334 struct dcerpc_binding_handle *b,
6335 uint32_t flags,
6336 const char *servername,
6337 uint32_t level,
6338 uint32_t *count_p,
6339 union spoolss_PrinterInfo **info_p)
6341 struct spoolss_EnumPrinters r;
6342 union spoolss_PrinterInfo *info;
6343 uint32_t needed;
6344 uint32_t count;
6346 r.in.flags = flags;
6347 r.in.server = servername;
6348 r.in.level = level;
6349 r.in.buffer = NULL;
6350 r.in.offered = 0;
6351 r.out.needed = &needed;
6352 r.out.count = &count;
6353 r.out.info = &info;
6355 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6356 r.in.server, r.in.level);
6358 torture_assert_ntstatus_ok(tctx,
6359 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6360 "EnumPrinters failed");
6361 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6362 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6363 r.in.buffer = &blob;
6364 r.in.offered = needed;
6365 torture_assert_ntstatus_ok(tctx,
6366 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6367 "EnumPrinters failed");
6370 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6372 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6374 if (count_p) {
6375 *count_p = count;
6377 if (info_p) {
6378 *info_p = info;
6381 return true;
6384 static const char *get_short_printername(struct torture_context *tctx,
6385 const char *name)
6387 const char *short_name;
6389 if (name[0] == '\\' && name[1] == '\\') {
6390 name += 2;
6391 short_name = strchr(name, '\\');
6392 if (short_name) {
6393 return talloc_strdup(tctx, short_name+1);
6397 return name;
6400 static const char *get_full_printername(struct torture_context *tctx,
6401 const char *name)
6403 const char *full_name = talloc_strdup(tctx, name);
6404 char *p;
6406 if (name && name[0] == '\\' && name[1] == '\\') {
6407 name += 2;
6408 p = strchr(name, '\\');
6409 if (p) {
6410 return full_name;
6414 return NULL;
6417 static bool test_OnePrinter_servername(struct torture_context *tctx,
6418 struct dcerpc_pipe *p,
6419 struct dcerpc_binding_handle *b,
6420 const char *servername,
6421 const char *printername)
6423 union spoolss_PrinterInfo info;
6424 const char *short_name = get_short_printername(tctx, printername);
6425 const char *full_name = get_full_printername(tctx, printername);
6427 if (short_name) {
6428 struct policy_handle handle;
6429 torture_assert(tctx,
6430 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6431 "failed to open printer");
6433 torture_assert(tctx,
6434 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6435 "failed to get printer info");
6437 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6438 "unexpected servername");
6439 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6440 "unexpected printername");
6442 if (info.info2.devmode) {
6443 const char *expected_devicename;
6444 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6445 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6446 "unexpected devicemode devicename");
6449 torture_assert(tctx,
6450 test_ClosePrinter(tctx, b, &handle),
6451 "failed to close printer");
6454 if (full_name) {
6455 struct policy_handle handle;
6457 torture_assert(tctx,
6458 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6459 "failed to open printer");
6461 torture_assert(tctx,
6462 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6463 "failed to get printer info");
6465 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6466 "unexpected servername");
6467 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6468 "unexpected printername");
6470 if (info.info2.devmode) {
6471 const char *expected_devicename;
6472 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6473 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6474 "unexpected devicemode devicename");
6477 torture_assert(tctx,
6478 test_ClosePrinter(tctx, b, &handle),
6479 "failed to close printer");
6482 return true;
6485 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6486 void *private_data)
6488 struct test_spoolss_context *ctx =
6489 talloc_get_type_abort(private_data, struct test_spoolss_context);
6490 int i;
6491 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6492 struct dcerpc_binding_handle *b = p->binding_handle;
6493 uint32_t count;
6494 union spoolss_PrinterInfo *info;
6495 const char *servername;
6496 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6498 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6500 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6502 torture_assert(tctx,
6503 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6504 "failed to enumerate printers");
6506 for (i=0; i < count; i++) {
6508 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6509 "unexpected servername");
6511 torture_assert(tctx,
6512 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6513 "failed to check printer");
6516 servername = "";
6518 torture_assert(tctx,
6519 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6520 "failed to enumerate printers");
6522 for (i=0; i < count; i++) {
6524 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6525 "unexpected servername");
6527 torture_assert(tctx,
6528 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6529 "failed to check printer");
6533 return true;
6537 static bool test_GetPrinterDriver(struct torture_context *tctx,
6538 struct dcerpc_binding_handle *b,
6539 struct policy_handle *handle,
6540 const char *driver_name)
6542 struct spoolss_GetPrinterDriver r;
6543 uint32_t needed;
6545 r.in.handle = handle;
6546 r.in.architecture = "W32X86";
6547 r.in.level = 1;
6548 r.in.buffer = NULL;
6549 r.in.offered = 0;
6550 r.out.needed = &needed;
6552 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6554 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6555 "failed to call GetPrinterDriver");
6556 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6557 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6558 r.in.buffer = &blob;
6559 r.in.offered = needed;
6560 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6561 "failed to call GetPrinterDriver");
6564 torture_assert_werr_ok(tctx, r.out.result,
6565 "failed to call GetPrinterDriver");
6567 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6569 return true;
6572 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6573 struct dcerpc_binding_handle *b,
6574 struct policy_handle *handle,
6575 const char *driver_name,
6576 const char *architecture,
6577 uint32_t level,
6578 uint32_t client_major_version,
6579 uint32_t client_minor_version,
6580 union spoolss_DriverInfo *info_p,
6581 WERROR *result_p)
6584 struct spoolss_GetPrinterDriver2 r;
6585 uint32_t needed;
6586 uint32_t server_major_version;
6587 uint32_t server_minor_version;
6589 r.in.handle = handle;
6590 r.in.architecture = architecture;
6591 r.in.client_major_version = client_major_version;
6592 r.in.client_minor_version = client_minor_version;
6593 r.in.buffer = NULL;
6594 r.in.offered = 0;
6595 r.in.level = level;
6596 r.out.needed = &needed;
6597 r.out.server_major_version = &server_major_version;
6598 r.out.server_minor_version = &server_minor_version;
6600 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6601 driver_name, r.in.level);
6603 torture_assert_ntstatus_ok(tctx,
6604 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6605 "failed to call GetPrinterDriver2");
6606 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6607 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6608 r.in.buffer = &blob;
6609 r.in.offered = needed;
6610 torture_assert_ntstatus_ok(tctx,
6611 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6612 "failed to call GetPrinterDriver2");
6615 if (result_p) {
6616 *result_p = r.out.result;
6619 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6620 switch (r.in.level) {
6621 case 101:
6622 case 8:
6623 torture_comment(tctx,
6624 "level %d not implemented, not considering as an error\n",
6625 r.in.level);
6626 return true;
6627 default:
6628 break;
6632 torture_assert_werr_ok(tctx, r.out.result,
6633 "failed to call GetPrinterDriver2");
6635 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6637 if (info_p) {
6638 *info_p = *r.out.info;
6641 return true;
6644 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6645 struct dcerpc_binding_handle *b,
6646 struct policy_handle *handle,
6647 const char *driver_name,
6648 const char *architecture)
6650 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6651 int i;
6654 for (i=0;i<ARRAY_SIZE(levels);i++) {
6656 torture_assert(tctx,
6657 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6658 "");
6661 return true;
6664 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6665 void *private_data)
6667 struct test_spoolss_context *ctx =
6668 talloc_get_type_abort(private_data, struct test_spoolss_context);
6669 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6670 int i;
6671 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6672 struct dcerpc_binding_handle *b = p->binding_handle;
6673 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6675 for (i=0;i<ARRAY_SIZE(levels);i++) {
6677 uint32_t count;
6678 union spoolss_DriverInfo *info;
6680 torture_assert(tctx,
6681 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6682 "failed to enumerate drivers");
6684 if (!info) {
6685 torture_comment(tctx, "No printer drivers returned\n");
6686 break;
6690 return true;
6693 static bool test_DeletePrinter(struct torture_context *tctx,
6694 struct dcerpc_binding_handle *b,
6695 struct policy_handle *handle)
6697 struct spoolss_DeletePrinter r;
6699 torture_comment(tctx, "Testing DeletePrinter\n");
6701 r.in.handle = handle;
6703 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6704 "failed to delete printer");
6705 torture_assert_werr_ok(tctx, r.out.result,
6706 "failed to delete printer");
6708 return true;
6711 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6712 struct dcerpc_binding_handle *b,
6713 uint32_t flags,
6714 uint32_t level,
6715 const char *name,
6716 bool *found)
6718 struct spoolss_EnumPrinters e;
6719 uint32_t count;
6720 union spoolss_PrinterInfo *info;
6721 uint32_t needed;
6722 int i;
6724 *found = false;
6726 e.in.flags = flags;
6727 e.in.server = NULL;
6728 e.in.level = level;
6729 e.in.buffer = NULL;
6730 e.in.offered = 0;
6731 e.out.count = &count;
6732 e.out.info = &info;
6733 e.out.needed = &needed;
6735 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6736 "failed to enum printers");
6738 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6739 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6740 e.in.buffer = &blob;
6741 e.in.offered = needed;
6743 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6744 "failed to enum printers");
6747 torture_assert_werr_ok(tctx, e.out.result,
6748 "failed to enum printers");
6750 for (i=0; i < count; i++) {
6752 const char *current = NULL;
6753 const char *q;
6755 switch (level) {
6756 case 1:
6757 current = info[i].info1.name;
6758 break;
6761 if (strequal(current, name)) {
6762 *found = true;
6763 break;
6766 q = strrchr(current, '\\');
6767 if (q) {
6768 if (!e.in.server) {
6769 torture_warning(tctx,
6770 "server returns printername %s incl. servername although we did not set servername", current);
6772 q++;
6773 if (strequal(q, name)) {
6774 *found = true;
6775 break;
6780 return true;
6783 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6784 struct dcerpc_pipe *p,
6785 const char *printername,
6786 bool ex)
6788 WERROR result;
6789 struct spoolss_AddPrinter r;
6790 struct spoolss_AddPrinterEx rex;
6791 struct spoolss_SetPrinterInfoCtr info_ctr;
6792 struct spoolss_SetPrinterInfo1 info1;
6793 struct spoolss_DevmodeContainer devmode_ctr;
6794 struct sec_desc_buf secdesc_ctr;
6795 struct spoolss_UserLevelCtr userlevel_ctr;
6796 struct policy_handle handle;
6797 bool found = false;
6798 struct dcerpc_binding_handle *b = p->binding_handle;
6800 ZERO_STRUCT(devmode_ctr);
6801 ZERO_STRUCT(secdesc_ctr);
6802 ZERO_STRUCT(userlevel_ctr);
6803 ZERO_STRUCT(info1);
6805 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6806 ex ? "Ex":"", printername);
6808 /* try to add printer to wellknown printer list (level 1) */
6810 userlevel_ctr.level = 1;
6812 info_ctr.info.info1 = &info1;
6813 info_ctr.level = 1;
6815 rex.in.server = NULL;
6816 rex.in.info_ctr = &info_ctr;
6817 rex.in.devmode_ctr = &devmode_ctr;
6818 rex.in.secdesc_ctr = &secdesc_ctr;
6819 rex.in.userlevel_ctr = &userlevel_ctr;
6820 rex.out.handle = &handle;
6822 r.in.server = NULL;
6823 r.in.info_ctr = &info_ctr;
6824 r.in.devmode_ctr = &devmode_ctr;
6825 r.in.secdesc_ctr = &secdesc_ctr;
6826 r.out.handle = &handle;
6828 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6829 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6830 "failed to add printer");
6831 result = ex ? rex.out.result : r.out.result;
6832 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6833 "unexpected result code");
6835 info1.name = printername;
6836 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6838 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6839 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6840 "failed to add printer");
6841 result = ex ? rex.out.result : r.out.result;
6842 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6843 "unexpected result code");
6845 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6846 better do a real check to see the printer is really there */
6848 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6849 PRINTER_ENUM_NETWORK, 1,
6850 printername,
6851 &found),
6852 "failed to enum printers");
6854 torture_assert(tctx, found, "failed to find newly added printer");
6856 info1.flags = 0;
6858 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6859 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6860 "failed to add printer");
6861 result = ex ? rex.out.result : r.out.result;
6862 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6863 "unexpected result code");
6865 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6866 better do a real check to see the printer has really been removed
6867 from the well known printer list */
6869 found = false;
6871 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6872 PRINTER_ENUM_NETWORK, 1,
6873 printername,
6874 &found),
6875 "failed to enum printers");
6876 #if 0
6877 torture_assert(tctx, !found, "printer still in well known printer list");
6878 #endif
6879 return true;
6882 static bool test_AddPrinter_normal(struct torture_context *tctx,
6883 struct dcerpc_pipe *p,
6884 struct policy_handle *handle_p,
6885 const char *printername,
6886 const char *drivername,
6887 const char *portname,
6888 struct spoolss_DeviceMode *devmode,
6889 bool ex)
6891 WERROR result;
6892 struct spoolss_AddPrinter r;
6893 struct spoolss_AddPrinterEx rex;
6894 struct spoolss_SetPrinterInfoCtr info_ctr;
6895 struct spoolss_SetPrinterInfo2 info2;
6896 struct spoolss_DevmodeContainer devmode_ctr;
6897 struct sec_desc_buf secdesc_ctr;
6898 struct spoolss_UserLevelCtr userlevel_ctr;
6899 struct policy_handle handle;
6900 bool found = false;
6901 bool existing_printer_deleted = false;
6902 struct dcerpc_binding_handle *b = p->binding_handle;
6904 ZERO_STRUCT(devmode_ctr);
6905 ZERO_STRUCT(secdesc_ctr);
6906 ZERO_STRUCT(userlevel_ctr);
6908 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6909 ex ? "Ex":"", printername);
6911 devmode_ctr.devmode = devmode;
6913 userlevel_ctr.level = 1;
6915 rex.in.server = NULL;
6916 rex.in.info_ctr = &info_ctr;
6917 rex.in.devmode_ctr = &devmode_ctr;
6918 rex.in.secdesc_ctr = &secdesc_ctr;
6919 rex.in.userlevel_ctr = &userlevel_ctr;
6920 rex.out.handle = &handle;
6922 r.in.server = NULL;
6923 r.in.info_ctr = &info_ctr;
6924 r.in.devmode_ctr = &devmode_ctr;
6925 r.in.secdesc_ctr = &secdesc_ctr;
6926 r.out.handle = &handle;
6928 again:
6930 /* try to add printer to printer list (level 2) */
6932 ZERO_STRUCT(info2);
6934 info_ctr.info.info2 = &info2;
6935 info_ctr.level = 2;
6937 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6938 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6939 "failed to add printer");
6940 result = ex ? rex.out.result : r.out.result;
6941 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6942 "unexpected result code");
6944 info2.printername = printername;
6946 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6947 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6948 "failed to add printer");
6949 result = ex ? rex.out.result : r.out.result;
6951 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6952 struct policy_handle printer_handle;
6954 if (existing_printer_deleted) {
6955 torture_fail(tctx, "already deleted printer still existing?");
6958 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6959 "failed to open printer handle");
6961 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6962 "failed to delete printer");
6964 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6965 "failed to close server handle");
6967 existing_printer_deleted = true;
6969 goto again;
6972 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6973 "unexpected result code");
6975 info2.portname = portname;
6977 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6978 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6979 "failed to add printer");
6980 result = ex ? rex.out.result : r.out.result;
6981 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6982 "unexpected result code");
6984 info2.drivername = drivername;
6986 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6987 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6988 "failed to add printer");
6989 result = ex ? rex.out.result : r.out.result;
6991 /* w2k8r2 allows to add printer w/o defining printprocessor */
6993 if (!W_ERROR_IS_OK(result)) {
6994 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6995 "unexpected result code");
6997 info2.printprocessor = "winprint";
6999 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7000 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7001 "failed to add printer");
7002 result = ex ? rex.out.result : r.out.result;
7003 torture_assert_werr_ok(tctx, result,
7004 "failed to add printer");
7007 *handle_p = handle;
7009 /* we are paranoid, really check if the printer is there now */
7011 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7012 PRINTER_ENUM_LOCAL, 1,
7013 printername,
7014 &found),
7015 "failed to enum printers");
7016 torture_assert(tctx, found, "failed to find newly added printer");
7018 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7019 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7020 "failed to add printer");
7021 result = ex ? rex.out.result : r.out.result;
7022 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7023 "unexpected result code");
7025 return true;
7028 static bool test_printer_info(struct torture_context *tctx,
7029 void *private_data)
7031 struct torture_printer_context *t =
7032 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7033 struct dcerpc_pipe *p = t->spoolss_pipe;
7034 struct dcerpc_binding_handle *b = p->binding_handle;
7036 bool ret = true;
7038 if (torture_setting_bool(tctx, "samba3", false)) {
7039 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7042 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7043 ret = false;
7046 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7047 ret = false;
7050 return ret;
7053 static bool test_EnumPrinterKey(struct torture_context *tctx,
7054 struct dcerpc_binding_handle *b,
7055 struct policy_handle *handle,
7056 const char *key_name,
7057 const char ***array)
7059 struct spoolss_EnumPrinterKey r;
7060 uint32_t needed = 0;
7061 union spoolss_KeyNames key_buffer;
7062 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7063 uint32_t _ndr_size;
7064 int i;
7066 r.in.handle = handle;
7067 r.in.key_name = key_name;
7068 r.out.key_buffer = &key_buffer;
7069 r.out.needed = &needed;
7070 r.out._ndr_size = &_ndr_size;
7072 for (i=0; i < ARRAY_SIZE(offered); i++) {
7074 if (offered[i] < 0 && needed) {
7075 if (needed <= 4) {
7076 continue;
7078 r.in.offered = needed + offered[i];
7079 } else {
7080 r.in.offered = offered[i];
7083 ZERO_STRUCT(key_buffer);
7085 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7087 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7088 "failed to call EnumPrinterKey");
7089 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7091 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7092 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7093 _ndr_size, r.in.offered/2));
7095 r.in.offered = needed;
7096 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7097 "failed to call EnumPrinterKey");
7100 if (offered[i] > 0) {
7101 torture_assert_werr_ok(tctx, r.out.result,
7102 "failed to call EnumPrinterKey");
7105 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7106 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7107 _ndr_size, r.in.offered/2));
7109 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7110 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7112 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7113 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7115 if (key_buffer.string_array) {
7116 uint32_t calc_needed = 0;
7117 int s;
7118 for (s=0; key_buffer.string_array[s]; s++) {
7119 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7121 if (!key_buffer.string_array[0]) {
7122 calc_needed += 2;
7124 calc_needed += 2;
7126 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7127 "EnumPrinterKey unexpected size");
7131 if (array) {
7132 *array = key_buffer.string_array;
7135 return true;
7138 bool test_printer_all_keys(struct torture_context *tctx,
7139 struct dcerpc_binding_handle *b,
7140 struct policy_handle *handle)
7142 const char **key_array = NULL;
7143 int i;
7145 torture_comment(tctx, "Testing Printer Keys\n");
7147 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7148 "failed to call test_EnumPrinterKey");
7150 for (i=0; key_array && key_array[i]; i++) {
7151 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7152 "failed to call test_EnumPrinterKey");
7154 for (i=0; key_array && key_array[i]; i++) {
7155 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7156 "failed to call test_EnumPrinterDataEx");
7159 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7161 return true;
7164 static bool test_openprinter_wrap(struct torture_context *tctx,
7165 void *private_data)
7167 struct torture_printer_context *t =
7168 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7169 struct dcerpc_pipe *p = t->spoolss_pipe;
7170 struct dcerpc_binding_handle *b = p->binding_handle;
7171 const char *printername = t->info2.printername;
7173 return test_openprinter(tctx, b, printername);
7176 static bool test_csetprinter(struct torture_context *tctx,
7177 void *private_data)
7179 struct torture_printer_context *t =
7180 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7181 struct dcerpc_pipe *p = t->spoolss_pipe;
7183 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7184 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7185 const char *portname = t->info2.portname;
7187 union spoolss_PrinterInfo info;
7188 struct policy_handle new_handle, new_handle2;
7189 struct dcerpc_binding_handle *b = p->binding_handle;
7191 torture_comment(tctx, "Testing c_setprinter\n");
7193 torture_assert(tctx,
7194 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7195 "failed to get level 0 printer info");
7196 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7197 info.info0.c_setprinter);
7199 /* check if c_setprinter on 1st handle increases after a printer has
7200 * been added */
7202 torture_assert(tctx,
7203 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7204 "failed to add new printer");
7205 torture_assert(tctx,
7206 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7207 "failed to get level 0 printer info");
7208 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7209 info.info0.c_setprinter);
7211 /* check if c_setprinter on new handle increases after a printer has
7212 * been added */
7214 torture_assert(tctx,
7215 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7216 "failed to get level 0 printer info");
7217 torture_comment(tctx, "csetprinter on created handle: %d\n",
7218 info.info0.c_setprinter);
7220 /* open the new printer and check if c_setprinter increases */
7222 torture_assert(tctx,
7223 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7224 "failed to open created printer");
7225 torture_assert(tctx,
7226 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7227 "failed to get level 0 printer info");
7228 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7229 info.info0.c_setprinter);
7231 /* cleanup */
7233 torture_assert(tctx,
7234 test_ClosePrinter(tctx, b, &new_handle2),
7235 "failed to close printer");
7236 torture_assert(tctx,
7237 test_DeletePrinter(tctx, b, &new_handle),
7238 "failed to delete new printer");
7240 return true;
7243 static bool compose_local_driver_directory(struct torture_context *tctx,
7244 const char *environment,
7245 const char *local_dir,
7246 const char **path)
7248 char *p;
7250 p = strrchr(local_dir, '/');
7251 if (!p) {
7252 return NULL;
7254 p++;
7256 if (strequal(environment, "Windows x64")) {
7257 if (!strequal(p, "x64")) {
7258 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7260 } else if (strequal(environment, "Windows NT x86")) {
7261 if (!strequal(p, "i386")) {
7262 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7264 } else {
7265 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7268 return true;
7271 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7272 const char *devicename)
7274 struct spoolss_DeviceMode *r;
7276 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7277 if (r == NULL) {
7278 return NULL;
7281 r->devicename = talloc_strdup(r, devicename);
7282 r->specversion = DMSPEC_NT4_AND_ABOVE;
7283 r->driverversion = 0x0600;
7284 r->size = 0x00dc;
7285 r->__driverextra_length = 0;
7286 r->fields = DEVMODE_FORMNAME |
7287 DEVMODE_TTOPTION |
7288 DEVMODE_PRINTQUALITY |
7289 DEVMODE_DEFAULTSOURCE |
7290 DEVMODE_COPIES |
7291 DEVMODE_SCALE |
7292 DEVMODE_PAPERSIZE |
7293 DEVMODE_ORIENTATION;
7294 r->orientation = DMORIENT_PORTRAIT;
7295 r->papersize = DMPAPER_LETTER;
7296 r->paperlength = 0;
7297 r->paperwidth = 0;
7298 r->scale = 100;
7299 r->copies = 55;
7300 r->defaultsource = DMBIN_FORMSOURCE;
7301 r->printquality = DMRES_HIGH;
7302 r->color = DMRES_MONOCHROME;
7303 r->duplex = DMDUP_SIMPLEX;
7304 r->yresolution = 0;
7305 r->ttoption = DMTT_SUBDEV;
7306 r->collate = DMCOLLATE_FALSE;
7307 r->formname = talloc_strdup(r, "Letter");
7309 return r;
7312 static bool test_architecture_buffer(struct torture_context *tctx,
7313 void *private_data)
7315 struct test_spoolss_context *ctx =
7316 talloc_get_type_abort(private_data, struct test_spoolss_context);
7318 struct spoolss_OpenPrinterEx r;
7319 struct spoolss_UserLevel1 u1;
7320 struct policy_handle handle;
7321 uint32_t architectures[] = {
7322 PROCESSOR_ARCHITECTURE_INTEL,
7323 PROCESSOR_ARCHITECTURE_IA64,
7324 PROCESSOR_ARCHITECTURE_AMD64
7326 uint32_t needed[3];
7327 int i;
7328 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7329 struct dcerpc_binding_handle *b = p->binding_handle;
7331 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7333 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7335 u1.size = 0;
7336 u1.client = NULL;
7337 u1.user = NULL;
7338 u1.build = 0;
7339 u1.major = 3;
7340 u1.minor = 0;
7341 u1.processor = architectures[i];
7343 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7344 r.in.datatype = NULL;
7345 r.in.devmode_ctr.devmode= NULL;
7346 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7347 r.in.userlevel_ctr.level = 1;
7348 r.in.userlevel_ctr.user_info.level1 = &u1;
7349 r.out.handle = &handle;
7351 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7352 torture_assert_werr_ok(tctx, r.out.result, "");
7355 struct spoolss_EnumPrinters e;
7356 uint32_t count;
7357 union spoolss_PrinterInfo *info;
7359 e.in.flags = PRINTER_ENUM_LOCAL;
7360 e.in.server = NULL;
7361 e.in.level = 2;
7362 e.in.buffer = NULL;
7363 e.in.offered = 0;
7364 e.out.count = &count;
7365 e.out.info = &info;
7366 e.out.needed = &needed[i];
7368 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7369 #if 0
7370 torture_comment(tctx, "needed was %d\n", needed[i]);
7371 #endif
7374 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7377 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7378 if (needed[i-1] != needed[i]) {
7379 torture_fail(tctx,
7380 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7381 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7385 return true;
7388 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7389 void *private_data)
7391 struct test_spoolss_context *ctx =
7392 talloc_get_type_abort(private_data, struct test_spoolss_context);
7393 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7394 struct dcerpc_binding_handle *b = p->binding_handle;
7396 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7399 static bool test_PrintServer_Forms(struct torture_context *tctx,
7400 void *private_data)
7402 struct test_spoolss_context *ctx =
7403 talloc_get_type_abort(private_data, struct test_spoolss_context);
7404 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7405 struct dcerpc_binding_handle *b = p->binding_handle;
7407 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7410 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7411 void *private_data)
7413 struct test_spoolss_context *ctx =
7414 talloc_get_type_abort(private_data, struct test_spoolss_context);
7415 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7416 struct dcerpc_binding_handle *b = p->binding_handle;
7418 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7421 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7423 NTSTATUS status;
7425 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7427 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7429 torture_assert(tctx,
7430 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7431 "failed to open printserver");
7432 torture_assert(tctx,
7433 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7434 "failed to get environment");
7436 return true;
7439 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7441 struct test_spoolss_context *t;
7443 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7445 return torture_rpc_spoolss_setup_common(tctx, t);
7448 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7450 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7452 return true;
7455 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7457 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7458 bool ret;
7460 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7461 talloc_free(t);
7463 return ret;
7466 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7468 struct dcerpc_pipe *p;
7469 struct dcerpc_binding_handle *b;
7470 const char *server_name_slash;
7471 const char *driver_name;
7472 const char *printer_name;
7473 const char *port_name;
7475 torture_assert_ntstatus_ok(tctx,
7476 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7477 "Error connecting to server");
7479 p = t->spoolss_pipe;
7480 b = p->binding_handle;
7481 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7483 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7484 t->driver.info8.driver_name = TORTURE_DRIVER;
7485 t->driver.info8.driver_path = "pscript5.dll";
7486 t->driver.info8.data_file = "cups6.ppd";
7487 t->driver.info8.config_file = "ps5ui.dll";
7488 t->driver.info8.help_file = "pscript.hlp";
7489 t->driver.info8.default_datatype = "RAW";
7490 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7491 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7492 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7493 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7494 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7495 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7496 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7497 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7498 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7499 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7501 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7503 t->info2.drivername = "Microsoft XPS Document Writer";
7504 t->info2.portname = "LPT1:";
7506 printer_name = t->info2.printername;
7507 port_name = t->info2.portname;
7509 torture_assert(tctx,
7510 fillup_printserver_info(tctx, p, &t->driver),
7511 "failed to fillup printserver info");
7513 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7515 torture_assert(tctx,
7516 compose_local_driver_directory(tctx, t->driver.remote.environment,
7517 t->driver.local.driver_directory,
7518 &t->driver.local.driver_directory),
7519 "failed to compose local driver directory");
7521 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7522 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7523 t->info2.drivername, t->driver.remote.environment);
7524 t->have_driver = true;
7525 goto try_add;
7528 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7529 t->info2.drivername, t->driver.remote.environment);
7530 torture_comment(tctx, "trying to upload own driver\n");
7532 if (!directory_exist(t->driver.local.driver_directory)) {
7533 torture_warning(tctx, "no local driver is available!");
7534 t->have_driver = false;
7535 goto try_add;
7538 torture_assert(tctx,
7539 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7540 "failed to upload printer driver");
7542 torture_assert(tctx,
7543 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7544 "failed to add driver");
7546 t->added_driver = true;
7547 t->have_driver = true;
7549 try_add:
7550 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7552 if (t->wellknown) {
7553 torture_assert(tctx,
7554 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7555 "failed to add wellknown printer");
7556 } else {
7557 torture_assert(tctx,
7558 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7559 "failed to add printer");
7562 return true;
7565 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7567 struct torture_printer_context *t;
7569 *data = t = talloc_zero(tctx, struct torture_printer_context);
7571 t->ex = false;
7572 t->wellknown = false;
7573 t->info2.printername = TORTURE_PRINTER;
7574 t->devmode = NULL;
7576 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7579 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7581 struct torture_printer_context *t;
7583 *data = t = talloc_zero(tctx, struct torture_printer_context);
7585 t->ex = true;
7586 t->wellknown = false;
7587 t->info2.printername = TORTURE_PRINTER_EX;
7588 t->devmode = NULL;
7590 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7593 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7595 struct torture_printer_context *t;
7597 *data = t = talloc_zero(tctx, struct torture_printer_context);
7599 t->ex = false;
7600 t->wellknown = true;
7601 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7602 t->devmode = NULL;
7604 /* FIXME */
7605 if (t->wellknown) {
7606 torture_skip(tctx, "skipping AddPrinter level 1");
7609 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7612 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7614 struct torture_printer_context *t;
7616 *data = t = talloc_zero(tctx, struct torture_printer_context);
7618 t->ex = true;
7619 t->wellknown = true;
7620 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7621 t->devmode = NULL;
7623 /* FIXME */
7624 if (t->wellknown) {
7625 torture_skip(tctx, "skipping AddPrinterEx level 1");
7628 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7631 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7633 struct torture_printer_context *t;
7635 *data = t = talloc_zero(tctx, struct torture_printer_context);
7637 t->ex = true;
7638 t->wellknown = false;
7639 t->info2.printername = TORTURE_PRINTER_EX;
7640 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7642 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7645 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7647 bool found = false;
7648 struct dcerpc_pipe *p = t->spoolss_pipe;
7649 struct dcerpc_binding_handle *b;
7650 const char *printer_name = t->info2.printername;
7652 if (t->added_driver) {
7653 torture_assert(tctx,
7654 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7655 "failed to remove printer driver");
7658 if (p && !t->wellknown) {
7659 b = p->binding_handle;
7661 torture_assert(tctx,
7662 test_DeletePrinter(tctx, b, &t->handle),
7663 "failed to delete printer");
7665 torture_assert(tctx,
7666 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7667 printer_name, &found),
7668 "failed to enumerate printers");
7670 torture_assert(tctx, !found, "deleted printer still there");
7673 return true;
7676 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7678 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7679 bool ret;
7681 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7682 talloc_free(t);
7684 return ret;
7687 static bool test_print_test(struct torture_context *tctx,
7688 void *private_data)
7690 struct torture_printer_context *t =
7691 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7692 struct dcerpc_pipe *p = t->spoolss_pipe;
7693 struct dcerpc_binding_handle *b = p->binding_handle;
7695 torture_assert(tctx,
7696 test_PausePrinter(tctx, b, &t->handle),
7697 "failed to pause printer");
7699 torture_assert(tctx,
7700 test_DoPrintTest(tctx, b, &t->handle),
7701 "failed to do print test");
7703 torture_assert(tctx,
7704 test_ResumePrinter(tctx, b, &t->handle),
7705 "failed to resume printer");
7707 return true;
7710 static bool test_print_test_extended(struct torture_context *tctx,
7711 void *private_data)
7713 struct torture_printer_context *t =
7714 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7715 struct dcerpc_pipe *p = t->spoolss_pipe;
7716 struct dcerpc_binding_handle *b = p->binding_handle;
7717 bool ret = true;
7719 torture_assert(tctx,
7720 test_PausePrinter(tctx, b, &t->handle),
7721 "failed to pause printer");
7723 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7724 if (ret == false) {
7725 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7726 if (torture_setting_bool(tctx, "samba3", false)) {
7727 torture_comment(tctx, "non-critical for samba3\n");
7728 ret = true;
7729 tctx->last_result = TORTURE_SKIP;
7733 torture_assert(tctx,
7734 test_ResumePrinter(tctx, b, &t->handle),
7735 "failed to resume printer");
7737 return ret;
7740 /* use smbd file IO to spool a print job */
7741 static bool test_print_test_smbd(struct torture_context *tctx,
7742 void *private_data)
7744 struct torture_printer_context *t =
7745 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7746 struct dcerpc_pipe *p = t->spoolss_pipe;
7747 struct dcerpc_binding_handle *b = p->binding_handle;
7748 NTSTATUS status;
7749 uint32_t count;
7750 union spoolss_JobInfo *info = NULL;
7751 int i;
7753 struct smb2_tree *tree;
7754 struct smb2_handle job_h;
7755 struct cli_credentials *credentials = cmdline_credentials;
7756 struct smbcli_options options;
7757 TALLOC_CTX *mem_ctx = talloc_new(tctx);
7759 * Do not test against the dynamically added printers, printing via
7760 * smbd means that a different spoolss process may handle the
7761 * OpenPrinter request to the one that handled the AddPrinter request.
7762 * This currently leads to an ugly race condition where one process
7763 * sees the new printer and one doesn't.
7765 const char *share = TORTURE_PRINTER_STATIC1;
7767 torture_comment(tctx, "Testing smbd job spooling\n");
7768 lpcfg_smbcli_options(tctx->lp_ctx, &options);
7770 status = smb2_connect_ext(mem_ctx,
7771 torture_setting_string(tctx, "host", NULL),
7772 lpcfg_smb_ports(tctx->lp_ctx),
7773 share,
7774 lpcfg_resolve_context(tctx->lp_ctx),
7775 credentials,
7777 &tree,
7778 tctx->ev,
7779 &options,
7780 lpcfg_socket_options(tctx->lp_ctx),
7781 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
7782 if (!NT_STATUS_IS_OK(status)) {
7783 printf("Failed to connect to SMB2 printer %s - %s\n",
7784 share, nt_errstr(status));
7785 return false;
7788 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
7789 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
7791 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
7792 sizeof("exciting print job data"));
7793 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
7795 /* check back end spoolss job was created */
7796 torture_assert(tctx,
7797 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
7798 "EnumJobs level 1 failed");
7800 for (i = 0; i < count; i++) {
7801 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
7802 break;
7805 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
7807 status = smb2_util_close(tree, job_h);
7808 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
7810 /* disconnect from printer share */
7811 talloc_free(mem_ctx);
7813 return true;
7816 static bool test_printer_sd(struct torture_context *tctx,
7817 void *private_data)
7819 struct torture_printer_context *t =
7820 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7821 struct dcerpc_pipe *p = t->spoolss_pipe;
7822 struct dcerpc_binding_handle *b = p->binding_handle;
7824 torture_assert(tctx,
7825 test_PrinterInfo_SD(tctx, b, &t->handle),
7826 "failed to test security descriptors");
7828 return true;
7831 static bool test_printer_dm(struct torture_context *tctx,
7832 void *private_data)
7834 struct torture_printer_context *t =
7835 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7836 struct dcerpc_pipe *p = t->spoolss_pipe;
7838 torture_assert(tctx,
7839 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7840 "failed to test devicemodes");
7842 return true;
7845 static bool test_printer_info_winreg(struct torture_context *tctx,
7846 void *private_data)
7848 struct torture_printer_context *t =
7849 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7850 struct dcerpc_pipe *p = t->spoolss_pipe;
7852 torture_assert(tctx,
7853 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7854 "failed to test printer info winreg");
7856 return true;
7859 static bool test_printer_change_id(struct torture_context *tctx,
7860 void *private_data)
7862 struct torture_printer_context *t =
7863 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7864 struct dcerpc_pipe *p = t->spoolss_pipe;
7866 torture_assert(tctx,
7867 test_ChangeID(tctx, p, &t->handle),
7868 "failed to test change id");
7870 return true;
7873 static bool test_printer_keys(struct torture_context *tctx,
7874 void *private_data)
7876 struct torture_printer_context *t =
7877 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7878 struct dcerpc_pipe *p = t->spoolss_pipe;
7879 struct dcerpc_binding_handle *b = p->binding_handle;
7881 torture_assert(tctx,
7882 test_printer_all_keys(tctx, b, &t->handle),
7883 "failed to test printer keys");
7885 return true;
7888 static bool test_printer_data_consistency(struct torture_context *tctx,
7889 void *private_data)
7891 struct torture_printer_context *t =
7892 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7893 struct dcerpc_pipe *p = t->spoolss_pipe;
7895 torture_assert(tctx,
7896 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7897 "failed to test printer data consistency");
7899 return true;
7902 static bool test_printer_data_keys(struct torture_context *tctx,
7903 void *private_data)
7905 struct torture_printer_context *t =
7906 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7907 struct dcerpc_pipe *p = t->spoolss_pipe;
7909 torture_assert(tctx,
7910 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7911 "failed to test printer data keys");
7913 return true;
7916 static bool test_printer_data_values(struct torture_context *tctx,
7917 void *private_data)
7919 struct torture_printer_context *t =
7920 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7921 struct dcerpc_pipe *p = t->spoolss_pipe;
7923 torture_assert(tctx,
7924 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7925 "failed to test printer data values");
7927 return true;
7930 static bool test_printer_data_set(struct torture_context *tctx,
7931 void *private_data)
7933 struct torture_printer_context *t =
7934 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7935 struct dcerpc_pipe *p = t->spoolss_pipe;
7937 torture_assert(tctx,
7938 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7939 "failed to test printer data set");
7941 return true;
7944 static bool test_printer_data_winreg(struct torture_context *tctx,
7945 void *private_data)
7947 struct torture_printer_context *t =
7948 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7949 struct dcerpc_pipe *p = t->spoolss_pipe;
7951 torture_assert(tctx,
7952 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7953 "failed to test printer data winreg");
7955 return true;
7958 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7959 void *private_data)
7961 struct torture_printer_context *t =
7962 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7963 struct dcerpc_pipe *p = t->spoolss_pipe;
7965 torture_assert(tctx,
7966 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7967 "failed to test printer data winreg dsspooler");
7969 return true;
7972 static bool test_driver_info_winreg(struct torture_context *tctx,
7973 void *private_data)
7975 struct torture_printer_context *t =
7976 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7977 struct dcerpc_pipe *p = t->spoolss_pipe;
7978 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7980 if (!t->have_driver) {
7981 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7984 torture_assert(tctx,
7985 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7986 "failed to test driver info winreg");
7988 return true;
7991 void torture_tcase_printer(struct torture_tcase *tcase)
7993 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7994 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7995 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7996 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7997 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
7998 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7999 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8000 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8001 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8002 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8003 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8004 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8005 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8006 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8007 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8008 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8009 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8010 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8011 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8014 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8016 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8017 struct torture_tcase *tcase;
8019 tcase = torture_suite_add_tcase(suite, "addprinter");
8021 torture_tcase_set_fixture(tcase,
8022 torture_rpc_spoolss_printer_setup,
8023 torture_rpc_spoolss_printer_teardown);
8025 torture_tcase_printer(tcase);
8027 tcase = torture_suite_add_tcase(suite, "addprinterex");
8029 torture_tcase_set_fixture(tcase,
8030 torture_rpc_spoolss_printerex_setup,
8031 torture_rpc_spoolss_printer_teardown);
8033 torture_tcase_printer(tcase);
8035 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8037 torture_tcase_set_fixture(tcase,
8038 torture_rpc_spoolss_printerwkn_setup,
8039 torture_rpc_spoolss_printer_teardown);
8041 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8043 torture_tcase_set_fixture(tcase,
8044 torture_rpc_spoolss_printerexwkn_setup,
8045 torture_rpc_spoolss_printer_teardown);
8047 #if 0
8048 /* test is not correct */
8049 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8051 torture_tcase_set_fixture(tcase,
8052 torture_rpc_spoolss_printerdm_setup,
8053 torture_rpc_spoolss_printer_teardown);
8055 torture_tcase_printer(tcase);
8056 #endif
8057 return suite;
8060 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8062 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8063 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8065 torture_tcase_set_fixture(tcase,
8066 torture_rpc_spoolss_setup,
8067 torture_rpc_spoolss_teardown);
8069 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8070 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8071 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8072 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8073 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8074 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8075 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8076 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8077 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8078 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8079 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8080 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8081 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8082 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8083 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8084 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8085 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8086 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8087 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8088 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8090 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8092 return suite;
8095 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8096 struct dcerpc_binding_handle *b,
8097 const char *server,
8098 const char *environment,
8099 const char **dir_p)
8101 struct spoolss_GetPrinterDriverDirectory r;
8102 uint32_t needed;
8104 r.in.server = server;
8105 r.in.environment = environment;
8106 r.in.level = 1;
8107 r.in.buffer = NULL;
8108 r.in.offered = 0;
8109 r.out.needed = &needed;
8111 torture_assert_ntstatus_ok(tctx,
8112 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8113 "failed to query driver directory");
8115 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8116 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8117 r.in.buffer = &blob;
8118 r.in.offered = needed;
8120 torture_assert_ntstatus_ok(tctx,
8121 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8122 "failed to query driver directory");
8125 torture_assert_werr_ok(tctx, r.out.result,
8126 "failed to query driver directory");
8128 if (dir_p) {
8129 *dir_p = r.out.info->info1.directory_name;
8132 return true;
8135 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8137 if (info_ctr == NULL) {
8138 return NULL;
8141 switch (info_ctr->level) {
8142 case 1:
8143 return info_ctr->info.info1->driver_name;
8144 case 2:
8145 return info_ctr->info.info2->driver_name;
8146 case 3:
8147 return info_ctr->info.info3->driver_name;
8148 case 4:
8149 return info_ctr->info.info4->driver_name;
8150 case 6:
8151 return info_ctr->info.info6->driver_name;
8152 case 8:
8153 return info_ctr->info.info8->driver_name;
8154 default:
8155 return NULL;
8159 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8161 if (info_ctr == NULL) {
8162 return NULL;
8165 switch (info_ctr->level) {
8166 case 2:
8167 return info_ctr->info.info2->architecture;
8168 case 3:
8169 return info_ctr->info.info3->architecture;
8170 case 4:
8171 return info_ctr->info.info4->architecture;
8172 case 6:
8173 return info_ctr->info.info6->architecture;
8174 case 8:
8175 return info_ctr->info.info8->architecture;
8176 default:
8177 return NULL;
8182 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8183 struct dcerpc_binding_handle *b,
8184 const char *servername,
8185 struct spoolss_AddDriverInfoCtr *info_ctr,
8186 WERROR expected_result)
8188 struct spoolss_AddPrinterDriver r;
8189 const char *drivername = get_driver_from_info(info_ctr);
8190 const char *environment = get_environment_from_info(info_ctr);
8192 r.in.servername = servername;
8193 r.in.info_ctr = info_ctr;
8195 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8196 drivername, info_ctr->level, environment);
8198 torture_assert_ntstatus_ok(tctx,
8199 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8200 "spoolss_AddPrinterDriver failed");
8201 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8202 "spoolss_AddPrinterDriver failed with unexpected result");
8204 return true;
8208 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8209 struct dcerpc_binding_handle *b,
8210 const char *servername,
8211 struct spoolss_AddDriverInfoCtr *info_ctr,
8212 uint32_t flags,
8213 WERROR expected_result)
8215 struct spoolss_AddPrinterDriverEx r;
8216 const char *drivername = get_driver_from_info(info_ctr);
8217 const char *environment = get_environment_from_info(info_ctr);
8219 r.in.servername = servername;
8220 r.in.info_ctr = info_ctr;
8221 r.in.flags = flags;
8223 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8224 drivername, info_ctr->level, environment);
8226 torture_assert_ntstatus_ok(tctx,
8227 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8228 "AddPrinterDriverEx failed");
8229 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8230 "AddPrinterDriverEx failed with unexpected result");
8232 return true;
8235 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8236 if (path && strlen(path)) {\
8237 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8240 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8241 struct dcerpc_binding_handle *b,
8242 const char *server_name,
8243 struct spoolss_AddDriverInfo8 *r,
8244 uint32_t flags,
8245 bool ex,
8246 const char *remote_driver_dir)
8248 struct spoolss_AddDriverInfoCtr info_ctr;
8249 struct spoolss_AddDriverInfo1 info1;
8251 ZERO_STRUCT(info1);
8253 info_ctr.level = 1;
8254 info_ctr.info.info1 = &info1;
8256 if (ex) {
8257 torture_assert(tctx,
8258 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8259 "failed to test AddPrinterDriverEx level 1");
8260 } else {
8261 torture_assert(tctx,
8262 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8263 "failed to test AddPrinterDriver level 1");
8266 info1.driver_name = r->driver_name;
8268 if (ex) {
8269 torture_assert(tctx,
8270 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8271 "failed to test AddPrinterDriverEx level 1");
8272 } else {
8273 torture_assert(tctx,
8274 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8275 "failed to test AddPrinterDriver level 1");
8278 return true;
8281 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8282 struct dcerpc_binding_handle *b,
8283 const char *server_name,
8284 struct spoolss_AddDriverInfo8 *r,
8285 uint32_t flags,
8286 bool ex,
8287 const char *remote_driver_dir)
8289 struct spoolss_AddDriverInfoCtr info_ctr;
8290 struct spoolss_AddDriverInfo2 info2;
8291 union spoolss_DriverInfo info;
8293 ZERO_STRUCT(info2);
8295 info_ctr.level = 2;
8296 info_ctr.info.info2 = &info2;
8298 if (ex) {
8299 torture_assert(tctx,
8300 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8301 "failed to test AddPrinterDriverEx level 2");
8302 } else {
8303 torture_assert(tctx,
8304 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8305 "failed to test AddPrinterDriver level 2");
8308 info2.driver_name = r->driver_name;
8310 if (ex) {
8311 torture_assert(tctx,
8312 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8313 "failed to test AddPrinterDriverEx level 2");
8314 } else {
8315 torture_assert(tctx,
8316 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8317 "failed to test AddPrinterDriver level 2");
8320 info2.version = r->version;
8322 if (ex) {
8323 torture_assert(tctx,
8324 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8325 "failed to test AddPrinterDriverEx level 2");
8326 } else {
8327 torture_assert(tctx,
8328 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8329 "failed to test AddPrinterDriver level 2");
8332 info2.architecture = r->architecture;
8334 if (ex) {
8335 torture_assert(tctx,
8336 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8337 "failed to test AddPrinterDriverEx level 2");
8338 } else {
8339 torture_assert(tctx,
8340 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8341 "failed to test AddPrinterDriver level 2");
8344 info2.driver_path = r->driver_path;
8346 if (ex) {
8347 torture_assert(tctx,
8348 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8349 "failed to test AddPrinterDriverEx level 2");
8350 } else {
8351 torture_assert(tctx,
8352 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8353 "failed to test AddPrinterDriver level 2");
8356 info2.data_file = r->data_file;
8358 if (ex) {
8359 torture_assert(tctx,
8360 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8361 "failed to test AddPrinterDriverEx level 2");
8362 } else {
8363 torture_assert(tctx,
8364 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8365 "failed to test AddPrinterDriver level 2");
8368 info2.config_file = r->config_file;
8370 if (ex) {
8371 torture_assert(tctx,
8372 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8373 "failed to test AddPrinterDriverEx");
8376 if (ex) {
8377 torture_assert(tctx,
8378 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8379 "failed to test AddPrinterDriverEx level 2");
8380 } else {
8381 torture_assert(tctx,
8382 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8383 "failed to test AddPrinterDriver level 2");
8386 torture_assert(tctx,
8387 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8388 "failed to find added printer driver");
8390 if (remote_driver_dir) {
8391 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8392 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8393 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8396 return true;
8399 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8400 struct dcerpc_binding_handle *b,
8401 const char *server_name,
8402 struct spoolss_AddDriverInfo8 *r,
8403 uint32_t flags,
8404 bool ex,
8405 const char *remote_driver_dir)
8407 struct spoolss_AddDriverInfoCtr info_ctr;
8408 struct spoolss_AddDriverInfo3 info3;
8409 union spoolss_DriverInfo info;
8411 info3.driver_name = r->driver_name;
8412 info3.version = r->version;
8413 info3.architecture = r->architecture;
8414 info3.driver_path = r->driver_path;
8415 info3.data_file = r->data_file;
8416 info3.config_file = r->config_file;
8417 info3.help_file = r->help_file;
8418 info3.monitor_name = r->monitor_name;
8419 info3.default_datatype = r->default_datatype;
8420 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8421 info3.dependent_files = r->dependent_files;
8423 info_ctr.level = 3;
8424 info_ctr.info.info3 = &info3;
8426 if (ex) {
8427 torture_assert(tctx,
8428 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8429 "failed to test AddPrinterDriverEx level 3");
8430 } else {
8431 torture_assert(tctx,
8432 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8433 "failed to test AddPrinterDriver level 3");
8436 torture_assert(tctx,
8437 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8438 "failed to find added printer driver");
8440 if (remote_driver_dir) {
8441 int i;
8442 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8443 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8444 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8445 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8446 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8447 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8451 return true;
8454 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8455 struct dcerpc_binding_handle *b,
8456 const char *server_name,
8457 struct spoolss_AddDriverInfo8 *r,
8458 uint32_t flags,
8459 bool ex,
8460 const char *remote_driver_dir)
8462 struct spoolss_AddDriverInfoCtr info_ctr;
8463 struct spoolss_AddDriverInfo4 info4;
8464 union spoolss_DriverInfo info;
8466 info4.version = r->version;
8467 info4.driver_name = r->driver_name;
8468 info4.architecture = r->architecture;
8469 info4.driver_path = r->driver_path;
8470 info4.data_file = r->data_file;
8471 info4.config_file = r->config_file;
8472 info4.help_file = r->help_file;
8473 info4.monitor_name = r->monitor_name;
8474 info4.default_datatype = r->default_datatype;
8475 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8476 info4.dependent_files = r->dependent_files;
8477 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8478 info4.previous_names = r->previous_names;
8480 info_ctr.level = 4;
8481 info_ctr.info.info4 = &info4;
8483 if (ex) {
8484 torture_assert(tctx,
8485 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8486 "failed to test AddPrinterDriverEx level 4");
8487 } else {
8488 torture_assert(tctx,
8489 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8490 "failed to test AddPrinterDriver level 4");
8493 torture_assert(tctx,
8494 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8495 "failed to find added printer driver");
8497 if (remote_driver_dir) {
8498 int i;
8499 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8500 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8501 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8502 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8503 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8504 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8508 return true;
8511 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8512 struct dcerpc_binding_handle *b,
8513 const char *server_name,
8514 struct spoolss_AddDriverInfo8 *r,
8515 uint32_t flags,
8516 bool ex,
8517 const char *remote_driver_dir)
8519 struct spoolss_AddDriverInfoCtr info_ctr;
8520 struct spoolss_AddDriverInfo6 info6;
8521 union spoolss_DriverInfo info;
8523 info6.version = r->version;
8524 info6.driver_name = r->driver_name;
8525 info6.architecture = r->architecture;
8526 info6.driver_path = r->driver_path;
8527 info6.data_file = r->data_file;
8528 info6.config_file = r->config_file;
8529 info6.help_file = r->help_file;
8530 info6.monitor_name = r->monitor_name;
8531 info6.default_datatype = r->default_datatype;
8532 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8533 info6.dependent_files = r->dependent_files;
8534 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8535 info6.previous_names = r->previous_names;
8536 info6.driver_date = r->driver_date;
8537 info6.driver_version = r->driver_version;
8538 info6.manufacturer_name = r->manufacturer_name;
8539 info6.manufacturer_url = r->manufacturer_url;
8540 info6.hardware_id = r->hardware_id;
8541 info6.provider = r->provider;
8543 info_ctr.level = 6;
8544 info_ctr.info.info6 = &info6;
8546 if (ex) {
8547 torture_assert(tctx,
8548 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8549 "failed to test AddPrinterDriverEx level 6");
8550 } else {
8551 torture_assert(tctx,
8552 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8553 "failed to test AddPrinterDriver level 6");
8556 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8558 if (!ex) {
8559 return true;
8562 torture_assert(tctx,
8563 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8564 "failed to find added printer driver");
8566 if (remote_driver_dir) {
8567 int i;
8568 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8569 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8570 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8571 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8572 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8573 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8577 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8578 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8580 return true;
8583 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8584 struct dcerpc_binding_handle *b,
8585 const char *server_name,
8586 struct spoolss_AddDriverInfo8 *r,
8587 uint32_t flags,
8588 bool ex,
8589 const char *remote_driver_dir)
8591 struct spoolss_AddDriverInfoCtr info_ctr;
8592 union spoolss_DriverInfo info;
8594 info_ctr.level = 8;
8595 info_ctr.info.info8 = r;
8597 if (ex) {
8598 torture_assert(tctx,
8599 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8600 "failed to test AddPrinterDriverEx level 8");
8601 } else {
8602 torture_assert(tctx,
8603 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8604 "failed to test AddPrinterDriver level 8");
8607 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8609 if (!ex) {
8610 return true;
8613 torture_assert(tctx,
8614 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8615 "failed to find added printer driver");
8617 if (remote_driver_dir) {
8618 int i;
8619 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8620 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8621 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8622 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8623 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8624 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8628 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8629 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8631 return true;
8634 #undef ASSERT_DRIVER_PATH
8636 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8637 struct dcerpc_binding_handle *b,
8638 const char *server,
8639 const char *driver,
8640 const char *environment,
8641 WERROR expected_result)
8643 struct spoolss_DeletePrinterDriver r;
8645 r.in.server = server;
8646 r.in.architecture = environment;
8647 r.in.driver = driver;
8649 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8651 torture_assert_ntstatus_ok(tctx,
8652 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8653 "DeletePrinterDriver failed");
8654 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8655 "DeletePrinterDriver failed with unexpected result");
8657 return true;
8660 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8661 struct dcerpc_binding_handle *b,
8662 const char *server,
8663 const char *driver,
8664 const char *environment,
8665 uint32_t delete_flags,
8666 uint32_t version,
8667 WERROR expected_result)
8669 struct spoolss_DeletePrinterDriverEx r;
8671 r.in.server = server;
8672 r.in.architecture = environment;
8673 r.in.driver = driver;
8674 r.in.delete_flags = delete_flags;
8675 r.in.version = version;
8677 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8679 torture_assert_ntstatus_ok(tctx,
8680 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8681 "DeletePrinterDriverEx failed");
8682 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8683 "DeletePrinterDriverEx failed with unexpected result");
8685 return true;
8688 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8689 struct dcerpc_binding_handle *b,
8690 const char *server_name,
8691 const char *driver,
8692 const char *environment)
8694 torture_assert(tctx,
8695 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8696 "failed to delete driver");
8698 torture_assert(tctx,
8699 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8700 "failed to delete driver");
8702 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8703 torture_fail(tctx, "deleted driver still enumerated");
8706 torture_assert(tctx,
8707 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8708 "2nd delete failed");
8710 return true;
8713 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8714 struct dcerpc_binding_handle *b,
8715 const char *server_name,
8716 const char *driver,
8717 const char *environment,
8718 uint32_t delete_flags,
8719 uint32_t version)
8721 torture_assert(tctx,
8722 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8723 "failed to delete driver");
8725 torture_assert(tctx,
8726 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8727 "failed to delete driver");
8729 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8730 torture_fail(tctx, "deleted driver still enumerated");
8733 torture_assert(tctx,
8734 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8735 "2nd delete failed");
8737 return true;
8740 static bool test_PrinterDriver_args(struct torture_context *tctx,
8741 struct dcerpc_binding_handle *b,
8742 const char *server_name,
8743 uint32_t level,
8744 struct spoolss_AddDriverInfo8 *r,
8745 uint32_t add_flags,
8746 uint32_t delete_flags,
8747 uint32_t delete_version,
8748 bool ex,
8749 const char *remote_driver_dir)
8751 bool ret = true;
8753 switch (level) {
8754 case 1:
8755 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8756 break;
8757 case 2:
8758 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8759 break;
8760 case 3:
8761 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8762 break;
8763 case 4:
8764 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8765 break;
8766 case 6:
8767 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8768 break;
8769 case 8:
8770 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8771 break;
8772 default:
8773 return false;
8776 if (ret == false) {
8777 return ret;
8780 if (level == 1) {
8781 return ret;
8784 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8786 if (!ex && (level == 6 || level == 8)) {
8787 return ret;
8791 struct dcerpc_pipe *p2;
8792 struct policy_handle hive_handle;
8793 struct dcerpc_binding_handle *b2;
8795 torture_assert_ntstatus_ok(tctx,
8796 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8797 "could not open winreg pipe");
8798 b2 = p2->binding_handle;
8800 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8802 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8804 test_winreg_CloseKey(tctx, b2, &hive_handle);
8806 talloc_free(p2);
8809 if (ex) {
8810 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8811 } else {
8812 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8816 static bool fillup_printserver_info(struct torture_context *tctx,
8817 struct dcerpc_pipe *p,
8818 struct torture_driver_context *d)
8820 struct policy_handle server_handle;
8821 struct dcerpc_binding_handle *b = p->binding_handle;
8822 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8824 torture_assert(tctx,
8825 test_OpenPrinter_server(tctx, p, &server_handle),
8826 "failed to open printserver");
8827 torture_assert(tctx,
8828 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8829 "failed to get environment");
8830 torture_assert(tctx,
8831 test_ClosePrinter(tctx, b, &server_handle),
8832 "failed to close printserver");
8834 torture_assert(tctx,
8835 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8836 d->local.environment ? d->local.environment : d->remote.environment,
8837 &d->remote.driver_directory),
8838 "failed to get driver directory");
8840 return true;
8843 static const char *driver_directory_dir(const char *driver_directory)
8845 char *p;
8847 p = strrchr(driver_directory, '\\');
8848 if (p) {
8849 return p+1;
8852 return NULL;
8855 static const char *driver_directory_share(struct torture_context *tctx,
8856 const char *driver_directory)
8858 const char *p;
8859 char *tok;
8861 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8862 driver_directory += 2;
8865 p = talloc_strdup(tctx, driver_directory);
8867 torture_assert(tctx,
8868 next_token_talloc(tctx, &p, &tok, "\\"),
8869 "cannot explode uri");
8870 torture_assert(tctx,
8871 next_token_talloc(tctx, &p, &tok, "\\"),
8872 "cannot explode uri");
8874 return tok;
8877 static bool upload_printer_driver_file(struct torture_context *tctx,
8878 struct smbcli_state *cli,
8879 struct torture_driver_context *d,
8880 const char *file_name)
8882 XFILE *f;
8883 int fnum;
8884 uint8_t *buf;
8885 int maxwrite = 64512;
8886 off_t nread = 0;
8887 size_t start = 0;
8888 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8889 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8890 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8892 if (!file_name || strlen(file_name) == 0) {
8893 return true;
8896 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8898 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8899 if (fnum == -1) {
8900 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8903 f = x_fopen(local_name, O_RDONLY, 0);
8904 if (f == NULL) {
8905 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8908 buf = talloc_array(tctx, uint8_t, maxwrite);
8909 if (!buf) {
8910 return false;
8913 while (!x_feof(f)) {
8914 int n = maxwrite;
8915 int ret;
8917 if ((n = x_fread(buf, 1, n, f)) < 1) {
8918 if((n == 0) && x_feof(f))
8919 break; /* Empty local file. */
8921 torture_warning(tctx,
8922 "failed to read file: %s\n", strerror(errno));
8923 break;
8926 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8928 if (n != ret) {
8929 torture_warning(tctx,
8930 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8931 break;
8934 nread += n;
8937 x_fclose(f);
8939 torture_assert_ntstatus_ok(tctx,
8940 smbcli_close(cli->tree, fnum),
8941 "failed to close file");
8943 return true;
8946 static bool connect_printer_driver_share(struct torture_context *tctx,
8947 const char *server_name,
8948 const char *share_name,
8949 struct smbcli_state **cli)
8951 struct smbcli_options smb_options;
8952 struct smbcli_session_options smb_session_options;
8954 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8955 share_name, server_name);
8957 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8958 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8960 torture_assert_ntstatus_ok(tctx,
8961 smbcli_full_connection(tctx, cli, server_name,
8962 lpcfg_smb_ports(tctx->lp_ctx),
8963 share_name, NULL,
8964 lpcfg_socket_options(tctx->lp_ctx),
8965 cmdline_credentials,
8966 lpcfg_resolve_context(tctx->lp_ctx),
8967 tctx->ev,
8968 &smb_options,
8969 &smb_session_options,
8970 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8971 "failed to open driver share");
8973 return true;
8976 static bool upload_printer_driver(struct torture_context *tctx,
8977 const char *server_name,
8978 struct torture_driver_context *d)
8980 struct smbcli_state *cli;
8981 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8982 int i;
8984 torture_assert(tctx,
8985 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8986 "failed to connect to driver share");
8988 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8989 server_name, share_name);
8991 torture_assert(tctx,
8992 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8993 "failed to upload driver_path");
8994 torture_assert(tctx,
8995 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8996 "failed to upload data_file");
8997 torture_assert(tctx,
8998 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8999 "failed to upload config_file");
9000 torture_assert(tctx,
9001 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9002 "failed to upload help_file");
9003 if (d->info8.dependent_files) {
9004 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9005 torture_assert(tctx,
9006 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9007 "failed to upload dependent_files");
9011 talloc_free(cli);
9013 return true;
9016 static bool check_printer_driver_file(struct torture_context *tctx,
9017 struct smbcli_state *cli,
9018 struct torture_driver_context *d,
9019 const char *file_name)
9021 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9022 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9023 remote_arch_dir,
9024 d->info8.version,
9025 file_name);
9026 int fnum;
9028 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9030 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9032 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9033 if (fnum == -1) {
9034 return false;
9037 torture_assert_ntstatus_ok(tctx,
9038 smbcli_close(cli->tree, fnum),
9039 "failed to close driver file");
9041 return true;
9044 static bool check_printer_driver_files(struct torture_context *tctx,
9045 const char *server_name,
9046 struct torture_driver_context *d,
9047 bool expect_exist)
9049 struct smbcli_state *cli;
9050 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9051 int i;
9053 torture_assert(tctx,
9054 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9055 "failed to connect to driver share");
9057 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9058 (expect_exist ? "": "non-"),
9059 server_name, share_name);
9061 if (d->info8.driver_path && d->info8.driver_path[0]) {
9062 torture_assert(tctx,
9063 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9064 "failed driver_path check");
9066 if (d->info8.data_file && d->info8.data_file[0]) {
9067 torture_assert(tctx,
9068 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9069 "failed data_file check");
9071 if (d->info8.config_file && d->info8.config_file[0]) {
9072 torture_assert(tctx,
9073 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9074 "failed config_file check");
9076 if (d->info8.help_file && d->info8.help_file[0]) {
9077 torture_assert(tctx,
9078 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9079 "failed help_file check");
9081 if (d->info8.dependent_files) {
9082 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9083 torture_assert(tctx,
9084 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9085 "failed dependent_files check");
9089 talloc_free(cli);
9091 return true;
9094 static bool remove_printer_driver_file(struct torture_context *tctx,
9095 struct smbcli_state *cli,
9096 struct torture_driver_context *d,
9097 const char *file_name)
9099 const char *remote_name;
9100 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9102 if (!file_name || strlen(file_name) == 0) {
9103 return true;
9106 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9108 torture_comment(tctx, "Removing %s\n", remote_name);
9110 torture_assert_ntstatus_ok(tctx,
9111 smbcli_unlink(cli->tree, remote_name),
9112 "failed to unlink");
9114 return true;
9117 static bool remove_printer_driver(struct torture_context *tctx,
9118 const char *server_name,
9119 struct torture_driver_context *d)
9121 struct smbcli_state *cli;
9122 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9123 int i;
9125 torture_assert(tctx,
9126 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9127 "failed to connect to driver share");
9129 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9130 server_name, share_name);
9132 torture_assert(tctx,
9133 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9134 "failed to remove driver_path");
9135 torture_assert(tctx,
9136 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9137 "failed to remove data_file");
9138 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9139 torture_assert(tctx,
9140 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9141 "failed to remove config_file");
9143 torture_assert(tctx,
9144 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9145 "failed to remove help_file");
9146 if (d->info8.dependent_files) {
9147 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9148 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9149 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9150 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9151 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9152 continue;
9154 torture_assert(tctx,
9155 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9156 "failed to remove dependent_files");
9160 talloc_free(cli);
9162 return true;
9166 static bool test_add_driver_arg(struct torture_context *tctx,
9167 struct dcerpc_pipe *p,
9168 struct torture_driver_context *d)
9170 bool ret = true;
9171 struct dcerpc_binding_handle *b = p->binding_handle;
9172 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9173 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9174 int i;
9175 struct spoolss_AddDriverInfo8 info8;
9176 uint32_t add_flags = APD_COPY_NEW_FILES;
9177 uint32_t delete_flags = 0;
9179 ZERO_STRUCT(info8);
9181 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9182 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9184 torture_assert(tctx,
9185 fillup_printserver_info(tctx, p, d),
9186 "failed to fillup printserver info");
9188 if (!directory_exist(d->local.driver_directory)) {
9189 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9192 torture_assert(tctx,
9193 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9194 "failed to upload printer driver");
9196 info8 = d->info8;
9197 if (d->info8.dependent_files) {
9198 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9199 if (d->info8.dependent_files->string) {
9200 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9202 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9203 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9204 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9208 info8.architecture = d->local.environment;
9210 for (i=0; i < ARRAY_SIZE(levels); i++) {
9212 if (torture_setting_bool(tctx, "samba3", false)) {
9213 switch (levels[i]) {
9214 case 2:
9215 case 4:
9216 case 8:
9217 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9218 continue;
9219 default:
9220 break;
9223 if (torture_setting_bool(tctx, "w2k3", false)) {
9224 switch (levels[i]) {
9225 case 8:
9226 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9227 continue;
9228 default:
9229 break;
9233 torture_comment(tctx,
9234 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9235 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9237 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);
9240 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9241 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9242 if (d->info8.config_file) {
9243 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9245 if (d->info8.help_file) {
9246 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9248 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9249 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9250 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9254 for (i=0; i < ARRAY_SIZE(levels); i++) {
9256 if (torture_setting_bool(tctx, "samba3", false)) {
9257 switch (levels[i]) {
9258 case 2:
9259 case 4:
9260 case 8:
9261 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9262 continue;
9263 default:
9264 break;
9267 if (torture_setting_bool(tctx, "w2k3", false)) {
9268 switch (levels[i]) {
9269 case 8:
9270 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9271 continue;
9272 default:
9273 break;
9277 torture_comment(tctx,
9278 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9279 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9281 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);
9284 torture_assert(tctx,
9285 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9286 "failed to remove printer driver");
9288 torture_comment(tctx, "\n");
9290 return ret;
9293 static bool test_add_driver_ex_64(struct torture_context *tctx,
9294 struct dcerpc_pipe *p)
9296 struct torture_driver_context *d;
9298 d = talloc_zero(tctx, struct torture_driver_context);
9300 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9301 d->info8.driver_name = TORTURE_DRIVER_EX;
9302 d->info8.architecture = NULL;
9303 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9304 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9305 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9306 d->local.environment = talloc_strdup(d, "Windows x64");
9307 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9308 d->ex = true;
9310 return test_add_driver_arg(tctx, p, d);
9313 static bool test_add_driver_ex_32(struct torture_context *tctx,
9314 struct dcerpc_pipe *p)
9316 struct torture_driver_context *d;
9318 d = talloc_zero(tctx, struct torture_driver_context);
9320 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9321 d->info8.driver_name = TORTURE_DRIVER_EX;
9322 d->info8.architecture = NULL;
9323 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9324 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9325 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9326 d->local.environment = talloc_strdup(d, "Windows NT x86");
9327 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9328 d->ex = true;
9330 return test_add_driver_arg(tctx, p, d);
9333 static bool test_add_driver_64(struct torture_context *tctx,
9334 struct dcerpc_pipe *p)
9336 struct torture_driver_context *d;
9338 d = talloc_zero(tctx, struct torture_driver_context);
9340 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9341 d->info8.driver_name = TORTURE_DRIVER;
9342 d->info8.architecture = NULL;
9343 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9344 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9345 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9346 d->local.environment = talloc_strdup(d, "Windows x64");
9347 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9348 d->ex = false;
9350 return test_add_driver_arg(tctx, p, d);
9353 static bool test_add_driver_32(struct torture_context *tctx,
9354 struct dcerpc_pipe *p)
9356 struct torture_driver_context *d;
9358 d = talloc_zero(tctx, struct torture_driver_context);
9360 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9361 d->info8.driver_name = TORTURE_DRIVER;
9362 d->info8.architecture = NULL;
9363 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9364 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9365 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9366 d->local.environment = talloc_strdup(d, "Windows NT x86");
9367 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9368 d->ex = false;
9370 return test_add_driver_arg(tctx, p, d);
9373 static bool test_add_driver_adobe(struct torture_context *tctx,
9374 struct dcerpc_pipe *p)
9376 struct torture_driver_context *d;
9378 if (!torture_setting_bool(tctx, "samba3", false)) {
9379 torture_skip(tctx, "skipping adobe test which only works against samba3");
9382 d = talloc_zero(tctx, struct torture_driver_context);
9384 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9385 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9386 d->info8.architecture = NULL;
9387 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9388 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9389 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9390 #if 0
9391 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9392 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9393 #endif
9394 d->local.environment = talloc_strdup(d, "Windows 4.0");
9395 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9396 d->ex = false;
9398 return test_add_driver_arg(tctx, p, d);
9401 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9402 struct dcerpc_pipe *p)
9404 struct torture_driver_context *d;
9405 struct spoolss_StringArray *a;
9407 if (!torture_setting_bool(tctx, "samba3", false)) {
9408 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9411 d = talloc_zero(tctx, struct torture_driver_context);
9413 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9414 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9415 d->info8.architecture = NULL;
9416 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9417 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9418 d->info8.config_file = NULL;
9419 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9420 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9421 d->info8.default_datatype = talloc_strdup(d, "RAW");
9423 a = talloc_zero(d, struct spoolss_StringArray);
9424 a->string = talloc_zero_array(a, const char *, 7);
9425 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9426 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9427 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9428 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9429 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9430 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9432 d->info8.dependent_files = a;
9433 d->local.environment = talloc_strdup(d, "Windows 4.0");
9434 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9435 d->ex = false;
9437 return test_add_driver_arg(tctx, p, d);
9440 static bool test_add_driver_timestamps(struct torture_context *tctx,
9441 struct dcerpc_pipe *p)
9443 struct torture_driver_context *d;
9444 struct timeval t = timeval_current();
9446 d = talloc_zero(tctx, struct torture_driver_context);
9448 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9449 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9450 d->info8.architecture = NULL;
9451 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9452 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9453 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9454 d->info8.driver_date = timeval_to_nttime(&t);
9455 d->local.environment = talloc_strdup(d, "Windows NT x86");
9456 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9457 d->ex = true;
9459 torture_assert(tctx,
9460 test_add_driver_arg(tctx, p, d),
9461 "");
9463 unix_to_nt_time(&d->info8.driver_date, 1);
9465 torture_assert(tctx,
9466 test_add_driver_arg(tctx, p, d),
9467 "");
9469 return true;
9472 static bool test_multiple_drivers(struct torture_context *tctx,
9473 struct dcerpc_pipe *p)
9475 struct torture_driver_context *d;
9476 struct dcerpc_binding_handle *b = p->binding_handle;
9477 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9478 int i;
9479 struct spoolss_AddDriverInfo8 info8;
9480 uint32_t add_flags = APD_COPY_NEW_FILES;
9481 uint32_t delete_flags = 0;
9483 d = talloc_zero(tctx, struct torture_driver_context);
9485 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9486 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9487 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9488 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9489 d->local.environment = talloc_strdup(d, "Windows NT x86");
9490 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9491 d->ex = true;
9493 torture_assert(tctx,
9494 fillup_printserver_info(tctx, p, d),
9495 "failed to fillup printserver info");
9497 if (!directory_exist(d->local.driver_directory)) {
9498 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9501 torture_assert(tctx,
9502 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9503 "failed to upload printer driver");
9505 info8 = d->info8;
9506 info8.architecture = d->local.environment;
9508 for (i=0; i < 3; i++) {
9509 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9511 torture_assert(tctx,
9512 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9513 "failed to add driver");
9516 torture_assert(tctx,
9517 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9518 "failed to delete driver");
9520 torture_assert(tctx,
9521 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9522 "torture_test_driver_1 no longer on the server");
9524 torture_assert(tctx,
9525 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9526 "torture_test_driver_2 no longer on the server");
9528 torture_assert(tctx,
9529 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9530 "failed to delete driver");
9532 torture_assert(tctx,
9533 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9534 "torture_test_driver_2 no longer on the server");
9536 torture_assert(tctx,
9537 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9538 "failed to delete driver");
9540 torture_assert(tctx,
9541 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9542 "failed to remove printer driver");
9544 return true;
9547 static bool test_del_driver_all_files(struct torture_context *tctx,
9548 struct dcerpc_pipe *p)
9550 struct torture_driver_context *d;
9551 struct spoolss_StringArray *a;
9552 uint32_t add_flags = APD_COPY_NEW_FILES;
9553 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9554 struct dcerpc_binding_handle *b = p->binding_handle;
9555 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9557 d = talloc_zero(tctx, struct torture_driver_context);
9559 d->ex = true;
9560 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9561 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9562 d->info8.architecture = NULL;
9563 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9564 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9565 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9566 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9567 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9568 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9570 a = talloc_zero(d, struct spoolss_StringArray);
9571 a->string = talloc_zero_array(a, const char *, 3);
9572 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9573 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9575 d->info8.dependent_files = a;
9576 d->info8.architecture = d->local.environment;
9578 torture_assert(tctx,
9579 fillup_printserver_info(tctx, p, d),
9580 "failed to fillup printserver info");
9582 if (!directory_exist(d->local.driver_directory)) {
9583 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9586 torture_assert(tctx,
9587 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9588 "failed to upload printer driver");
9590 torture_assert(tctx,
9591 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9592 "failed to add driver");
9594 torture_assert(tctx,
9595 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9596 d->info8.driver_name,
9597 d->local.environment,
9598 delete_flags,
9599 d->info8.version),
9600 "failed to delete driver");
9602 torture_assert(tctx,
9603 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9604 "printer driver file check failed");
9606 talloc_free(d);
9607 return true;
9610 static bool test_del_driver_unused_files(struct torture_context *tctx,
9611 struct dcerpc_pipe *p)
9613 struct torture_driver_context *d1;
9614 struct torture_driver_context *d2;
9615 uint32_t add_flags = APD_COPY_NEW_FILES;
9616 struct dcerpc_binding_handle *b = p->binding_handle;
9617 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9619 d1 = talloc_zero(tctx, struct torture_driver_context);
9620 d1->ex = true;
9621 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9622 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9623 d1->info8.architecture = NULL;
9624 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9625 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9626 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9627 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9628 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9629 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9630 d1->info8.architecture = d1->local.environment;
9632 d2 = talloc_zero(tctx, struct torture_driver_context);
9633 d2->ex = true;
9634 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9635 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9636 d2->info8.architecture = NULL;
9637 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9638 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9639 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9640 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9641 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9642 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9643 d2->info8.architecture = d2->local.environment;
9645 torture_assert(tctx,
9646 fillup_printserver_info(tctx, p, d1),
9647 "failed to fillup printserver info");
9648 torture_assert(tctx,
9649 fillup_printserver_info(tctx, p, d2),
9650 "failed to fillup printserver info");
9652 if (!directory_exist(d1->local.driver_directory)) {
9653 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9656 torture_assert(tctx,
9657 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9658 "failed to upload printer driver");
9659 torture_assert(tctx,
9660 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9661 "failed to add driver");
9663 torture_assert(tctx,
9664 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9665 "failed to upload printer driver");
9666 torture_assert(tctx,
9667 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9668 "failed to add driver");
9670 /* some files are in use by a separate driver, should fail */
9671 torture_assert(tctx,
9672 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9673 d1->info8.driver_name,
9674 d1->local.environment,
9675 DPD_DELETE_ALL_FILES,
9676 d1->info8.version,
9677 WERR_PRINTER_DRIVER_IN_USE),
9678 "invalid delete driver response");
9680 /* should only delete files not in use by other driver */
9681 torture_assert(tctx,
9682 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9683 d1->info8.driver_name,
9684 d1->local.environment,
9685 DPD_DELETE_UNUSED_FILES,
9686 d1->info8.version,
9687 WERR_OK),
9688 "failed to delete driver (unused files)");
9690 /* check non-overlapping were deleted */
9691 d1->info8.driver_path = NULL;
9692 d1->info8.help_file = NULL;
9693 torture_assert(tctx,
9694 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9695 "printer driver file check failed");
9696 /* d2 files should be uneffected */
9697 torture_assert(tctx,
9698 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9699 "printer driver file check failed");
9701 torture_assert(tctx,
9702 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9703 d2->info8.driver_name,
9704 d2->local.environment,
9705 DPD_DELETE_ALL_FILES,
9706 d2->info8.version,
9707 WERR_OK),
9708 "failed to delete driver");
9710 torture_assert(tctx,
9711 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9712 "printer driver file check failed");
9714 talloc_free(d1);
9715 talloc_free(d2);
9716 return true;
9719 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9721 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9723 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9724 "driver", &ndr_table_spoolss);
9725 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9726 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9728 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9729 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9731 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9733 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9735 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9737 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9739 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9741 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9743 return suite;