s4-smbtorture: split out a "printerdata_keys" test for RPC-SPOOLSS-PRINTER.
[Samba.git] / source4 / torture / rpc / spoolss.c
blobaa708d1ec049d89149b9b4fd523167b60591e5b9
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-2010
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 "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
41 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
42 #define TORTURE_PRINTER "torture_printer"
43 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
44 #define TORTURE_PRINTER_EX "torture_printer_ex"
45 #define TORTURE_DRIVER "torture_driver"
46 #define TORTURE_DRIVER_EX "torture_driver_ex"
48 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
49 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
50 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
51 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
52 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
53 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
55 struct test_spoolss_context {
56 struct dcerpc_pipe *spoolss_pipe;
58 /* server environment */
59 const char *environment;
61 /* print server handle */
62 struct policy_handle server_handle;
64 /* for EnumPorts */
65 uint32_t port_count[3];
66 union spoolss_PortInfo *ports[3];
68 /* for EnumPrinterDrivers */
69 uint32_t driver_count[8];
70 union spoolss_DriverInfo *drivers[8];
72 /* for EnumMonitors */
73 uint32_t monitor_count[3];
74 union spoolss_MonitorInfo *monitors[3];
76 /* for EnumPrintProcessors */
77 uint32_t print_processor_count[2];
78 union spoolss_PrintProcessorInfo *print_processors[2];
80 /* for EnumPrinters */
81 uint32_t printer_count[6];
82 union spoolss_PrinterInfo *printers[6];
85 struct torture_driver_context {
86 struct {
87 const char *driver_directory;
88 const char *environment;
89 } local;
90 struct {
91 const char *driver_directory;
92 const char *environment;
93 } remote;
94 struct spoolss_AddDriverInfo8 info8;
95 bool ex;
98 struct torture_printer_context {
99 struct dcerpc_pipe *spoolss_pipe;
100 struct spoolss_SetPrinterInfo2 info2;
101 struct torture_driver_context driver;
102 bool ex;
103 bool wellknown;
104 bool added_driver;
105 bool have_driver;
106 struct spoolss_DeviceMode *devmode;
107 struct policy_handle handle;
110 static bool upload_printer_driver(struct torture_context *tctx,
111 const char *server_name,
112 struct torture_driver_context *d);
113 static bool remove_printer_driver(struct torture_context *tctx,
114 const char *server_name,
115 struct torture_driver_context *d);
116 static bool fillup_printserver_info(struct torture_context *tctx,
117 struct dcerpc_pipe *p,
118 struct torture_driver_context *d);
119 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
120 struct dcerpc_binding_handle *b,
121 const char *server_name,
122 struct spoolss_AddDriverInfo8 *r,
123 uint32_t flags,
124 bool ex);
126 #define COMPARE_STRING(tctx, c,r,e) \
127 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
129 /* not every compiler supports __typeof__() */
130 #if (__GNUC__ >= 3)
131 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
132 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
133 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
135 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
136 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
138 } while(0)
139 #else
140 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
141 #endif
143 #define COMPARE_UINT32(tctx, c, r, e) do {\
144 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
145 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
146 } while(0)
148 #define COMPARE_UINT64(tctx, c, r, e) do {\
149 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
150 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
151 } while(0)
154 #define COMPARE_NTTIME(tctx, c, r, e) do {\
155 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
156 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
157 } while(0)
159 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
160 int __i; \
161 if (!c.e && !r.e) { \
162 break; \
164 if (c.e && !r.e) { \
165 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
167 if (!c.e && r.e) { \
168 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
170 for (__i=0;c.e[__i] != NULL; __i++) { \
171 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
173 } while(0)
175 #define CHECK_ALIGN(size, n) do {\
176 if (size % n) {\
177 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
178 size, n, size + n - (size % n));\
180 } while(0)
182 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
184 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
185 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
186 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
187 uint32_t round_size = DO_ROUND(size, align);\
188 if (round_size != needed) {\
189 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
190 CHECK_ALIGN(size, align);\
193 } while(0)
195 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
196 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
197 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
198 uint32_t round_size = DO_ROUND(size, align);\
199 if (round_size != needed) {\
200 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
201 CHECK_ALIGN(size, align);\
204 } while(0)
206 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
207 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
208 uint32_t size = ndr_size_##fn(info, level, 0);\
209 uint32_t round_size = DO_ROUND(size, align);\
210 if (round_size != needed) {\
211 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
212 CHECK_ALIGN(size, align);\
215 } while(0)
217 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
218 const union spoolss_PrinterInfo *i,
219 uint32_t level,
220 union spoolss_SetPrinterInfo *s)
222 switch (level) {
223 case 0:
224 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
225 break;
226 case 2:
227 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
228 s->info2->servername = i->info2.servername;
229 s->info2->printername = i->info2.printername;
230 s->info2->sharename = i->info2.sharename;
231 s->info2->portname = i->info2.portname;
232 s->info2->drivername = i->info2.drivername;
233 s->info2->comment = i->info2.comment;
234 s->info2->location = i->info2.location;
235 s->info2->devmode_ptr = 0;
236 s->info2->sepfile = i->info2.sepfile;
237 s->info2->printprocessor = i->info2.printprocessor;
238 s->info2->datatype = i->info2.datatype;
239 s->info2->parameters = i->info2.parameters;
240 s->info2->secdesc_ptr = 0;
241 s->info2->attributes = i->info2.attributes;
242 s->info2->priority = i->info2.priority;
243 s->info2->defaultpriority = i->info2.defaultpriority;
244 s->info2->starttime = i->info2.starttime;
245 s->info2->untiltime = i->info2.untiltime;
246 s->info2->status = i->info2.status;
247 s->info2->cjobs = i->info2.cjobs;
248 s->info2->averageppm = i->info2.averageppm;
249 break;
250 case 3:
251 case 4:
252 case 5:
253 case 6:
254 case 7:
255 case 8:
256 case 9:
257 default:
258 return false;
261 return true;
264 static bool test_OpenPrinter_server(struct torture_context *tctx,
265 struct dcerpc_pipe *p,
266 struct policy_handle *server_handle)
268 NTSTATUS status;
269 struct spoolss_OpenPrinter op;
270 struct dcerpc_binding_handle *b = p->binding_handle;
272 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
273 op.in.datatype = NULL;
274 op.in.devmode_ctr.devmode= NULL;
275 op.in.access_mask = 0;
276 op.out.handle = server_handle;
278 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
280 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
281 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
282 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
284 return true;
287 static bool test_EnumPorts(struct torture_context *tctx,
288 void *private_data)
290 struct test_spoolss_context *ctx =
291 talloc_get_type_abort(private_data, struct test_spoolss_context);
292 struct dcerpc_pipe *p = ctx->spoolss_pipe;
293 struct dcerpc_binding_handle *b = p->binding_handle;
294 NTSTATUS status;
295 struct spoolss_EnumPorts r;
296 uint16_t levels[] = { 1, 2 };
297 int i, j;
299 for (i=0;i<ARRAY_SIZE(levels);i++) {
300 int level = levels[i];
301 DATA_BLOB blob;
302 uint32_t needed;
303 uint32_t count;
304 union spoolss_PortInfo *info;
306 r.in.servername = "";
307 r.in.level = level;
308 r.in.buffer = NULL;
309 r.in.offered = 0;
310 r.out.needed = &needed;
311 r.out.count = &count;
312 r.out.info = &info;
314 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
316 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
317 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
318 if (W_ERROR_IS_OK(r.out.result)) {
319 /* TODO: do some more checks here */
320 continue;
322 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
323 "EnumPorts unexpected return code");
325 blob = data_blob_talloc_zero(ctx, needed);
326 r.in.buffer = &blob;
327 r.in.offered = needed;
329 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
330 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
332 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
334 torture_assert(tctx, info, "EnumPorts returned no info");
336 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
338 ctx->port_count[level] = count;
339 ctx->ports[level] = info;
342 for (i=1;i<ARRAY_SIZE(levels);i++) {
343 int level = levels[i];
344 int old_level = levels[i-1];
345 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
346 "EnumPorts invalid value");
348 /* if the array sizes are not the same we would maybe segfault in the following code */
350 for (i=0;i<ARRAY_SIZE(levels);i++) {
351 int level = levels[i];
352 for (j=0;j<ctx->port_count[level];j++) {
353 union spoolss_PortInfo *cur = &ctx->ports[level][j];
354 union spoolss_PortInfo *ref = &ctx->ports[2][j];
355 switch (level) {
356 case 1:
357 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
358 break;
359 case 2:
360 /* level 2 is our reference, and it makes no sense to compare it to itself */
361 break;
366 return true;
369 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
370 void *private_data)
372 struct test_spoolss_context *ctx =
373 talloc_get_type_abort(private_data, struct test_spoolss_context);
375 NTSTATUS status;
376 struct dcerpc_pipe *p = ctx->spoolss_pipe;
377 struct dcerpc_binding_handle *b = p->binding_handle;
378 struct spoolss_GetPrintProcessorDirectory r;
379 struct {
380 uint16_t level;
381 const char *server;
382 } levels[] = {{
383 .level = 1,
384 .server = NULL
386 .level = 1,
387 .server = ""
389 .level = 78,
390 .server = ""
392 .level = 1,
393 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
395 .level = 1024,
396 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
399 int i;
400 uint32_t needed;
402 for (i=0;i<ARRAY_SIZE(levels);i++) {
403 int level = levels[i].level;
404 DATA_BLOB blob;
406 r.in.server = levels[i].server;
407 r.in.environment = ctx->environment;
408 r.in.level = level;
409 r.in.buffer = NULL;
410 r.in.offered = 0;
411 r.out.needed = &needed;
413 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
415 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
416 torture_assert_ntstatus_ok(tctx, status,
417 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
418 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
419 "GetPrintProcessorDirectory unexpected return code");
421 blob = data_blob_talloc_zero(tctx, needed);
422 r.in.buffer = &blob;
423 r.in.offered = needed;
425 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
426 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
428 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
430 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
433 return true;
437 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
438 void *private_data)
440 struct test_spoolss_context *ctx =
441 talloc_get_type_abort(private_data, struct test_spoolss_context);
443 NTSTATUS status;
444 struct dcerpc_pipe *p = ctx->spoolss_pipe;
445 struct dcerpc_binding_handle *b = p->binding_handle;
446 struct spoolss_GetPrinterDriverDirectory r;
447 struct {
448 uint16_t level;
449 const char *server;
450 } levels[] = {{
451 .level = 1,
452 .server = NULL
454 .level = 1,
455 .server = ""
457 .level = 78,
458 .server = ""
460 .level = 1,
461 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
463 .level = 1024,
464 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
467 int i;
468 uint32_t needed;
470 for (i=0;i<ARRAY_SIZE(levels);i++) {
471 int level = levels[i].level;
472 DATA_BLOB blob;
474 r.in.server = levels[i].server;
475 r.in.environment = ctx->environment;
476 r.in.level = level;
477 r.in.buffer = NULL;
478 r.in.offered = 0;
479 r.out.needed = &needed;
481 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
483 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
484 torture_assert_ntstatus_ok(tctx, status,
485 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
486 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
487 "GetPrinterDriverDirectory unexpected return code");
489 blob = data_blob_talloc_zero(tctx, needed);
490 r.in.buffer = &blob;
491 r.in.offered = needed;
493 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
494 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
496 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
498 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
501 return true;
504 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
505 struct dcerpc_binding_handle *b,
506 const char *server_name,
507 const char *environment,
508 uint32_t level,
509 uint32_t *count_p,
510 union spoolss_DriverInfo **info_p)
512 struct spoolss_EnumPrinterDrivers r;
513 uint32_t needed;
514 uint32_t count;
515 union spoolss_DriverInfo *info;
517 r.in.server = server_name;
518 r.in.environment = environment;
519 r.in.level = level;
520 r.in.buffer = NULL;
521 r.in.offered = 0;
522 r.out.needed = &needed;
523 r.out.count = &count;
524 r.out.info = &info;
526 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
527 r.in.environment, r.in.level);
529 torture_assert_ntstatus_ok(tctx,
530 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
531 "EnumPrinterDrivers failed");
532 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
533 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
534 r.in.buffer = &blob;
535 r.in.offered = needed;
537 torture_assert_ntstatus_ok(tctx,
538 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
539 "EnumPrinterDrivers failed");
542 torture_assert_werr_ok(tctx, r.out.result,
543 "EnumPrinterDrivers failed");
545 if (count_p) {
546 *count_p = count;
548 if (info_p) {
549 *info_p = info;
552 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
554 return true;
558 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
559 struct dcerpc_binding_handle *b,
560 const char *server_name,
561 const char *environment,
562 uint32_t level,
563 const char *driver_name)
565 uint32_t count;
566 union spoolss_DriverInfo *info;
567 int i;
569 torture_assert(tctx,
570 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
571 "failed to enumerate printer drivers");
573 for (i=0; i < count; i++) {
574 const char *driver_name_ret;
575 switch (level) {
576 case 1:
577 driver_name_ret = info[i].info1.driver_name;
578 break;
579 case 2:
580 driver_name_ret = info[i].info2.driver_name;
581 break;
582 case 3:
583 driver_name_ret = info[i].info3.driver_name;
584 break;
585 case 4:
586 driver_name_ret = info[i].info4.driver_name;
587 break;
588 case 5:
589 driver_name_ret = info[i].info5.driver_name;
590 break;
591 case 6:
592 driver_name_ret = info[i].info6.driver_name;
593 break;
594 case 7:
595 driver_name_ret = info[i].info7.driver_name;
596 break;
597 case 8:
598 driver_name_ret = info[i].info8.driver_name;
599 break;
600 default:
601 break;
603 if (strequal(driver_name, driver_name_ret)) {
604 return true;
608 return false;
611 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
612 void *private_data)
614 struct test_spoolss_context *ctx =
615 talloc_get_type_abort(private_data, struct test_spoolss_context);
616 struct dcerpc_pipe *p = ctx->spoolss_pipe;
617 struct dcerpc_binding_handle *b = p->binding_handle;
618 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
619 int i, j, a;
621 /* FIXME: gd, come back and fix "" as server, and handle
622 * priority of returned error codes in torture test and samba 3
623 * server */
624 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
625 const char *environments[2];
627 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
628 environments[1] = ctx->environment;
630 for (a=0;a<ARRAY_SIZE(environments);a++) {
632 for (i=0;i<ARRAY_SIZE(levels);i++) {
633 int level = levels[i];
634 uint32_t count;
635 union spoolss_DriverInfo *info;
637 torture_assert(tctx,
638 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
639 "failed to enumerate drivers");
641 ctx->driver_count[level] = count;
642 ctx->drivers[level] = info;
645 for (i=1;i<ARRAY_SIZE(levels);i++) {
646 int level = levels[i];
647 int old_level = levels[i-1];
649 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
650 "EnumPrinterDrivers invalid value");
653 for (i=0;i<ARRAY_SIZE(levels);i++) {
654 int level = levels[i];
656 for (j=0;j<ctx->driver_count[level];j++) {
657 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
658 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
660 switch (level) {
661 case 1:
662 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
663 break;
664 case 2:
665 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
666 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
667 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
668 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
669 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
670 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
671 break;
672 case 3:
673 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
674 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
675 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
676 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
677 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
678 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
679 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
680 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
681 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
682 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
683 break;
684 case 4:
685 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
686 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
687 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
688 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
689 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
690 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
691 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
692 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
693 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
694 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
695 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
696 break;
697 case 5:
698 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
699 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
700 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
701 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
702 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
703 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
704 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
705 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
706 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
707 break;
708 case 6:
709 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
710 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
711 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
712 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
713 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
714 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
715 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
716 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
717 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
718 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
719 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
720 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
721 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
722 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
723 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
724 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
725 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
726 break;
727 case 8:
728 /* level 8 is our reference, and it makes no sense to compare it to itself */
729 break;
735 return true;
738 static bool test_EnumMonitors(struct torture_context *tctx,
739 void *private_data)
741 struct test_spoolss_context *ctx =
742 talloc_get_type_abort(private_data, struct test_spoolss_context);
743 struct dcerpc_pipe *p = ctx->spoolss_pipe;
744 struct dcerpc_binding_handle *b = p->binding_handle;
745 NTSTATUS status;
746 struct spoolss_EnumMonitors r;
747 uint16_t levels[] = { 1, 2 };
748 int i, j;
750 for (i=0;i<ARRAY_SIZE(levels);i++) {
751 int level = levels[i];
752 DATA_BLOB blob;
753 uint32_t needed;
754 uint32_t count;
755 union spoolss_MonitorInfo *info;
757 r.in.servername = "";
758 r.in.level = level;
759 r.in.buffer = NULL;
760 r.in.offered = 0;
761 r.out.needed = &needed;
762 r.out.count = &count;
763 r.out.info = &info;
765 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
767 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
768 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
769 if (W_ERROR_IS_OK(r.out.result)) {
770 /* TODO: do some more checks here */
771 continue;
773 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
774 "EnumMonitors failed");
776 blob = data_blob_talloc_zero(ctx, needed);
777 r.in.buffer = &blob;
778 r.in.offered = needed;
780 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
781 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
783 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
785 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
787 ctx->monitor_count[level] = count;
788 ctx->monitors[level] = info;
791 for (i=1;i<ARRAY_SIZE(levels);i++) {
792 int level = levels[i];
793 int old_level = levels[i-1];
794 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
795 "EnumMonitors invalid value");
798 for (i=0;i<ARRAY_SIZE(levels);i++) {
799 int level = levels[i];
800 for (j=0;j<ctx->monitor_count[level];j++) {
801 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
802 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
803 switch (level) {
804 case 1:
805 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
806 break;
807 case 2:
808 /* level 2 is our reference, and it makes no sense to compare it to itself */
809 break;
814 return true;
817 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
818 struct dcerpc_binding_handle *b,
819 const char *environment,
820 uint32_t level,
821 uint32_t *count_p,
822 union spoolss_PrintProcessorInfo **info_p)
824 struct spoolss_EnumPrintProcessors r;
825 DATA_BLOB blob;
826 uint32_t needed;
827 uint32_t count;
828 union spoolss_PrintProcessorInfo *info;
830 r.in.servername = "";
831 r.in.environment = environment;
832 r.in.level = level;
833 r.in.buffer = NULL;
834 r.in.offered = 0;
835 r.out.needed = &needed;
836 r.out.count = &count;
837 r.out.info = &info;
839 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
841 torture_assert_ntstatus_ok(tctx,
842 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
843 "EnumPrintProcessors failed");
844 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
845 blob = data_blob_talloc_zero(tctx, needed);
846 r.in.buffer = &blob;
847 r.in.offered = needed;
848 torture_assert_ntstatus_ok(tctx,
849 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
850 "EnumPrintProcessors failed");
852 torture_assert_werr_ok(tctx, r.out.result,
853 "EnumPrintProcessors failed");
855 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
857 if (count_p) {
858 *count_p = count;
860 if (info_p) {
861 *info_p = info;
864 return true;
867 static bool test_EnumPrintProcessors(struct torture_context *tctx,
868 void *private_data)
870 struct test_spoolss_context *ctx =
871 talloc_get_type_abort(private_data, struct test_spoolss_context);
873 uint16_t levels[] = { 1 };
874 int i, j;
875 struct dcerpc_pipe *p = ctx->spoolss_pipe;
876 struct dcerpc_binding_handle *b = p->binding_handle;
878 for (i=0;i<ARRAY_SIZE(levels);i++) {
879 int level = levels[i];
880 union spoolss_PrintProcessorInfo *info;
881 uint32_t count;
883 torture_assert(tctx,
884 test_EnumPrintProcessors_level(tctx, b, ctx->environment, level, &count, &info),
885 "test_EnumPrintProcessors_level failed");
887 ctx->print_processor_count[level] = count;
888 ctx->print_processors[level] = info;
891 for (i=1;i<ARRAY_SIZE(levels);i++) {
892 int level = levels[i];
893 int old_level = levels[i-1];
894 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
895 "EnumPrintProcessors failed");
898 for (i=0;i<ARRAY_SIZE(levels);i++) {
899 int level = levels[i];
900 for (j=0;j<ctx->print_processor_count[level];j++) {
901 #if 0
902 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
903 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
904 #endif
905 switch (level) {
906 case 1:
907 /* level 1 is our reference, and it makes no sense to compare it to itself */
908 break;
913 return true;
916 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
917 void *private_data)
919 struct test_spoolss_context *ctx =
920 talloc_get_type_abort(private_data, struct test_spoolss_context);
922 NTSTATUS status;
923 struct spoolss_EnumPrintProcDataTypes r;
924 uint16_t levels[] = { 1 };
925 int i;
926 struct dcerpc_pipe *p = ctx->spoolss_pipe;
927 struct dcerpc_binding_handle *b = p->binding_handle;
929 for (i=0;i<ARRAY_SIZE(levels);i++) {
930 int level = levels[i];
931 DATA_BLOB blob;
932 uint32_t needed;
933 uint32_t count;
934 union spoolss_PrintProcDataTypesInfo *info;
936 r.in.servername = "";
937 r.in.print_processor_name = "winprint";
938 r.in.level = level;
939 r.in.buffer = NULL;
940 r.in.offered = 0;
941 r.out.needed = &needed;
942 r.out.count = &count;
943 r.out.info = &info;
945 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
947 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
948 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
949 if (W_ERROR_IS_OK(r.out.result)) {
950 /* TODO: do some more checks here */
951 continue;
953 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
954 "EnumPrintProcDataTypes unexpected return code");
956 blob = data_blob_talloc_zero(tctx, needed);
957 r.in.buffer = &blob;
958 r.in.offered = needed;
960 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
961 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
963 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
965 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, needed, 4);
969 return true;
973 static bool test_EnumPrinters(struct torture_context *tctx,
974 void *private_data)
976 struct test_spoolss_context *ctx =
977 talloc_get_type_abort(private_data, struct test_spoolss_context);
978 struct dcerpc_pipe *p = ctx->spoolss_pipe;
979 struct dcerpc_binding_handle *b = p->binding_handle;
980 struct spoolss_EnumPrinters r;
981 NTSTATUS status;
982 uint16_t levels[] = { 0, 1, 2, 4, 5 };
983 int i, j;
985 for (i=0;i<ARRAY_SIZE(levels);i++) {
986 int level = levels[i];
987 DATA_BLOB blob;
988 uint32_t needed;
989 uint32_t count;
990 union spoolss_PrinterInfo *info;
992 r.in.flags = PRINTER_ENUM_LOCAL;
993 r.in.server = "";
994 r.in.level = level;
995 r.in.buffer = NULL;
996 r.in.offered = 0;
997 r.out.needed = &needed;
998 r.out.count = &count;
999 r.out.info = &info;
1001 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1003 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1004 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1005 if (W_ERROR_IS_OK(r.out.result)) {
1006 /* TODO: do some more checks here */
1007 continue;
1009 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1010 "EnumPrinters unexpected return code");
1012 blob = data_blob_talloc_zero(ctx, needed);
1013 r.in.buffer = &blob;
1014 r.in.offered = needed;
1016 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1017 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1019 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1021 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1023 ctx->printer_count[level] = count;
1024 ctx->printers[level] = info;
1027 for (i=1;i<ARRAY_SIZE(levels);i++) {
1028 int level = levels[i];
1029 int old_level = levels[i-1];
1030 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1031 "EnumPrinters invalid value");
1034 for (i=0;i<ARRAY_SIZE(levels);i++) {
1035 int level = levels[i];
1036 for (j=0;j<ctx->printer_count[level];j++) {
1037 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1038 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1039 switch (level) {
1040 case 0:
1041 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1042 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1043 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1044 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1045 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1046 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1047 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1048 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1049 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1050 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1051 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1052 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1053 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1054 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1055 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1056 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1057 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1058 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1059 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1060 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1061 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1062 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1063 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1064 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1065 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1066 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1067 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1068 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1069 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1070 break;
1071 case 1:
1072 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1073 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1074 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1075 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1076 break;
1077 case 2:
1078 /* level 2 is our reference, and it makes no sense to compare it to itself */
1079 break;
1080 case 4:
1081 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1082 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1083 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1084 break;
1085 case 5:
1086 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1087 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1088 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1089 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1090 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1091 break;
1096 /* TODO:
1097 * - verify that the port of a printer was in the list returned by EnumPorts
1100 return true;
1103 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1104 struct dcerpc_binding_handle *b,
1105 struct policy_handle *handle,
1106 const char *driver_name,
1107 const char *environment);
1109 bool test_GetPrinter_level(struct torture_context *tctx,
1110 struct dcerpc_binding_handle *b,
1111 struct policy_handle *handle,
1112 uint32_t level,
1113 union spoolss_PrinterInfo *info)
1115 struct spoolss_GetPrinter r;
1116 uint32_t needed;
1118 r.in.handle = handle;
1119 r.in.level = level;
1120 r.in.buffer = NULL;
1121 r.in.offered = 0;
1122 r.out.needed = &needed;
1124 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1126 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1127 "GetPrinter failed");
1129 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1130 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1131 r.in.buffer = &blob;
1132 r.in.offered = needed;
1134 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1135 "GetPrinter failed");
1138 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1140 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1142 if (info && r.out.info) {
1143 *info = *r.out.info;
1146 return true;
1150 static bool test_GetPrinter(struct torture_context *tctx,
1151 struct dcerpc_binding_handle *b,
1152 struct policy_handle *handle,
1153 const char *environment)
1155 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1156 int i;
1158 for (i=0;i<ARRAY_SIZE(levels);i++) {
1160 union spoolss_PrinterInfo info;
1162 ZERO_STRUCT(info);
1164 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1165 "failed to call GetPrinter");
1167 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1168 torture_assert(tctx,
1169 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1170 "failed to call test_GetPrinterDriver2");
1174 return true;
1177 static bool test_SetPrinter(struct torture_context *tctx,
1178 struct dcerpc_binding_handle *b,
1179 struct policy_handle *handle,
1180 struct spoolss_SetPrinterInfoCtr *info_ctr,
1181 struct spoolss_DevmodeContainer *devmode_ctr,
1182 struct sec_desc_buf *secdesc_ctr,
1183 enum spoolss_PrinterControl command)
1185 struct spoolss_SetPrinter r;
1187 r.in.handle = handle;
1188 r.in.info_ctr = info_ctr;
1189 r.in.devmode_ctr = devmode_ctr;
1190 r.in.secdesc_ctr = secdesc_ctr;
1191 r.in.command = command;
1193 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1195 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1196 "failed to call SetPrinter");
1197 torture_assert_werr_ok(tctx, r.out.result,
1198 "failed to call SetPrinter");
1200 return true;
1203 static bool test_SetPrinter_errors(struct torture_context *tctx,
1204 struct dcerpc_binding_handle *b,
1205 struct policy_handle *handle)
1207 struct spoolss_SetPrinter r;
1208 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1209 int i;
1211 struct spoolss_SetPrinterInfoCtr info_ctr;
1212 struct spoolss_DevmodeContainer devmode_ctr;
1213 struct sec_desc_buf secdesc_ctr;
1215 info_ctr.level = 0;
1216 info_ctr.info.info0 = NULL;
1218 ZERO_STRUCT(devmode_ctr);
1219 ZERO_STRUCT(secdesc_ctr);
1221 r.in.handle = handle;
1222 r.in.info_ctr = &info_ctr;
1223 r.in.devmode_ctr = &devmode_ctr;
1224 r.in.secdesc_ctr = &secdesc_ctr;
1225 r.in.command = 0;
1227 torture_comment(tctx, "Testing SetPrinter all zero\n");
1229 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1230 "failed to call SetPrinter");
1231 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1232 "failed to call SetPrinter");
1234 again:
1235 for (i=0; i < ARRAY_SIZE(levels); i++) {
1237 struct spoolss_SetPrinterInfo0 info0;
1238 struct spoolss_SetPrinterInfo1 info1;
1239 struct spoolss_SetPrinterInfo2 info2;
1240 struct spoolss_SetPrinterInfo3 info3;
1241 struct spoolss_SetPrinterInfo4 info4;
1242 struct spoolss_SetPrinterInfo5 info5;
1243 struct spoolss_SetPrinterInfo6 info6;
1244 struct spoolss_SetPrinterInfo7 info7;
1245 struct spoolss_SetPrinterInfo8 info8;
1246 struct spoolss_SetPrinterInfo9 info9;
1249 info_ctr.level = levels[i];
1250 switch (levels[i]) {
1251 case 0:
1252 ZERO_STRUCT(info0);
1253 info_ctr.info.info0 = &info0;
1254 break;
1255 case 1:
1256 ZERO_STRUCT(info1);
1257 info_ctr.info.info1 = &info1;
1258 break;
1259 case 2:
1260 ZERO_STRUCT(info2);
1261 info_ctr.info.info2 = &info2;
1262 break;
1263 case 3:
1264 ZERO_STRUCT(info3);
1265 info_ctr.info.info3 = &info3;
1266 break;
1267 case 4:
1268 ZERO_STRUCT(info4);
1269 info_ctr.info.info4 = &info4;
1270 break;
1271 case 5:
1272 ZERO_STRUCT(info5);
1273 info_ctr.info.info5 = &info5;
1274 break;
1275 case 6:
1276 ZERO_STRUCT(info6);
1277 info_ctr.info.info6 = &info6;
1278 break;
1279 case 7:
1280 ZERO_STRUCT(info7);
1281 info_ctr.info.info7 = &info7;
1282 break;
1283 case 8:
1284 ZERO_STRUCT(info8);
1285 info_ctr.info.info8 = &info8;
1286 break;
1287 case 9:
1288 ZERO_STRUCT(info9);
1289 info_ctr.info.info9 = &info9;
1290 break;
1293 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1294 info_ctr.level, r.in.command);
1296 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1297 "failed to call SetPrinter");
1299 switch (r.in.command) {
1300 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1301 /* is ignored for all levels other then 0 */
1302 if (info_ctr.level > 0) {
1303 /* ignored then */
1304 break;
1306 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1307 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1308 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1309 if (info_ctr.level > 0) {
1310 /* is invalid for all levels other then 0 */
1311 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1312 "unexpected error code returned");
1313 continue;
1314 } else {
1315 torture_assert_werr_ok(tctx, r.out.result,
1316 "failed to call SetPrinter with non 0 command");
1317 continue;
1319 break;
1321 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1322 /* FIXME: gd needs further investigation */
1323 default:
1324 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1325 "unexpected error code returned");
1326 continue;
1329 switch (info_ctr.level) {
1330 case 1:
1331 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1332 "unexpected error code returned");
1333 break;
1334 case 2:
1335 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1336 "unexpected error code returned");
1337 break;
1338 case 3:
1339 case 4:
1340 case 5:
1341 case 7:
1342 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1343 "unexpected error code returned");
1344 break;
1345 case 9:
1346 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1347 "unexpected error code returned");
1348 break;
1349 default:
1350 torture_assert_werr_ok(tctx, r.out.result,
1351 "failed to call SetPrinter");
1352 break;
1356 if (r.in.command < 5) {
1357 r.in.command++;
1358 goto again;
1361 return true;
1364 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1366 if ((r->level == 2) && (r->info.info2)) {
1367 r->info.info2->secdesc_ptr = 0;
1368 r->info.info2->devmode_ptr = 0;
1372 static bool test_PrinterInfo(struct torture_context *tctx,
1373 struct dcerpc_binding_handle *b,
1374 struct policy_handle *handle)
1376 NTSTATUS status;
1377 struct spoolss_SetPrinter s;
1378 struct spoolss_GetPrinter q;
1379 struct spoolss_GetPrinter q0;
1380 struct spoolss_SetPrinterInfoCtr info_ctr;
1381 union spoolss_PrinterInfo info;
1382 struct spoolss_DevmodeContainer devmode_ctr;
1383 struct sec_desc_buf secdesc_ctr;
1384 uint32_t needed;
1385 bool ret = true;
1386 int i;
1388 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1390 uint32_t status_list[] = {
1391 /* these do not stick
1392 PRINTER_STATUS_PAUSED,
1393 PRINTER_STATUS_ERROR,
1394 PRINTER_STATUS_PENDING_DELETION, */
1395 PRINTER_STATUS_PAPER_JAM,
1396 PRINTER_STATUS_PAPER_OUT,
1397 PRINTER_STATUS_MANUAL_FEED,
1398 PRINTER_STATUS_PAPER_PROBLEM,
1399 PRINTER_STATUS_OFFLINE,
1400 PRINTER_STATUS_IO_ACTIVE,
1401 PRINTER_STATUS_BUSY,
1402 PRINTER_STATUS_PRINTING,
1403 PRINTER_STATUS_OUTPUT_BIN_FULL,
1404 PRINTER_STATUS_NOT_AVAILABLE,
1405 PRINTER_STATUS_WAITING,
1406 PRINTER_STATUS_PROCESSING,
1407 PRINTER_STATUS_INITIALIZING,
1408 PRINTER_STATUS_WARMING_UP,
1409 PRINTER_STATUS_TONER_LOW,
1410 PRINTER_STATUS_NO_TONER,
1411 PRINTER_STATUS_PAGE_PUNT,
1412 PRINTER_STATUS_USER_INTERVENTION,
1413 PRINTER_STATUS_OUT_OF_MEMORY,
1414 PRINTER_STATUS_DOOR_OPEN,
1415 PRINTER_STATUS_SERVER_UNKNOWN,
1416 PRINTER_STATUS_POWER_SAVE,
1417 /* these do not stick
1418 0x02000000,
1419 0x04000000,
1420 0x08000000,
1421 0x10000000,
1422 0x20000000,
1423 0x40000000,
1424 0x80000000 */
1426 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1427 uint32_t attribute_list[] = {
1428 PRINTER_ATTRIBUTE_QUEUED,
1429 /* fails with WERR_INVALID_DATATYPE:
1430 PRINTER_ATTRIBUTE_DIRECT, */
1431 /* does not stick
1432 PRINTER_ATTRIBUTE_DEFAULT, */
1433 PRINTER_ATTRIBUTE_SHARED,
1434 /* does not stick
1435 PRINTER_ATTRIBUTE_NETWORK, */
1436 PRINTER_ATTRIBUTE_HIDDEN,
1437 PRINTER_ATTRIBUTE_LOCAL,
1438 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1439 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1440 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1441 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1442 /* does not stick
1443 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1444 /* fails with WERR_INVALID_DATATYPE:
1445 PRINTER_ATTRIBUTE_RAW_ONLY, */
1446 /* these do not stick
1447 PRINTER_ATTRIBUTE_PUBLISHED,
1448 PRINTER_ATTRIBUTE_FAX,
1449 PRINTER_ATTRIBUTE_TS,
1450 0x00010000,
1451 0x00020000,
1452 0x00040000,
1453 0x00080000,
1454 0x00100000,
1455 0x00200000,
1456 0x00400000,
1457 0x00800000,
1458 0x01000000,
1459 0x02000000,
1460 0x04000000,
1461 0x08000000,
1462 0x10000000,
1463 0x20000000,
1464 0x40000000,
1465 0x80000000 */
1468 ZERO_STRUCT(devmode_ctr);
1469 ZERO_STRUCT(secdesc_ctr);
1471 s.in.handle = handle;
1472 s.in.command = 0;
1473 s.in.info_ctr = &info_ctr;
1474 s.in.devmode_ctr = &devmode_ctr;
1475 s.in.secdesc_ctr = &secdesc_ctr;
1477 q.in.handle = handle;
1478 q.out.info = &info;
1479 q0 = q;
1481 #define TESTGETCALL(call, r) \
1482 r.in.buffer = NULL; \
1483 r.in.offered = 0;\
1484 r.out.needed = &needed; \
1485 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1486 if (!NT_STATUS_IS_OK(status)) { \
1487 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1488 r.in.level, nt_errstr(status), __location__); \
1489 ret = false; \
1490 break; \
1492 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1493 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1494 r.in.buffer = &blob; \
1495 r.in.offered = needed; \
1497 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1498 if (!NT_STATUS_IS_OK(status)) { \
1499 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1500 r.in.level, nt_errstr(status), __location__); \
1501 ret = false; \
1502 break; \
1504 if (!W_ERROR_IS_OK(r.out.result)) { \
1505 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1506 r.in.level, win_errstr(r.out.result), __location__); \
1507 ret = false; \
1508 break; \
1512 #define TESTSETCALL_EXP(call, r, err) \
1513 clear_info2(&info_ctr);\
1514 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1515 if (!NT_STATUS_IS_OK(status)) { \
1516 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1517 r.in.info_ctr->level, nt_errstr(status), __location__); \
1518 ret = false; \
1519 break; \
1521 if (!W_ERROR_IS_OK(err)) { \
1522 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1523 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1524 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1525 ret = false; \
1527 break; \
1529 if (!W_ERROR_IS_OK(r.out.result)) { \
1530 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1531 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1532 ret = false; \
1533 break; \
1536 #define TESTSETCALL(call, r) \
1537 TESTSETCALL_EXP(call, r, WERR_OK)
1539 #define STRING_EQUAL(s1, s2, field) \
1540 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1541 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1542 #field, s2, __location__); \
1543 ret = false; \
1544 break; \
1547 #define MEM_EQUAL(s1, s2, length, field) \
1548 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1549 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1550 #field, (const char *)s2, __location__); \
1551 ret = false; \
1552 break; \
1555 #define INT_EQUAL(i1, i2, field) \
1556 if (i1 != i2) { \
1557 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1558 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1559 ret = false; \
1560 break; \
1563 #define SD_EQUAL(sd1, sd2, field) \
1564 if (!security_descriptor_equal(sd1, sd2)) { \
1565 torture_comment(tctx, "Failed to set %s (%s)\n", \
1566 #field, __location__); \
1567 ret = false; \
1568 break; \
1571 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1572 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1573 q.in.level = lvl1; \
1574 TESTGETCALL(GetPrinter, q) \
1575 info_ctr.level = lvl1; \
1576 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1577 info_ctr.info.info ## lvl1->field1 = value;\
1578 TESTSETCALL_EXP(SetPrinter, s, err) \
1579 info_ctr.info.info ## lvl1->field1 = ""; \
1580 TESTGETCALL(GetPrinter, q) \
1581 info_ctr.info.info ## lvl1->field1 = value; \
1582 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1583 q.in.level = lvl2; \
1584 TESTGETCALL(GetPrinter, q) \
1585 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1586 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1587 } while (0)
1589 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1590 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1591 } while (0);
1593 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1594 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1595 q.in.level = lvl1; \
1596 TESTGETCALL(GetPrinter, q) \
1597 info_ctr.level = lvl1; \
1598 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1599 info_ctr.info.info ## lvl1->field1 = value; \
1600 TESTSETCALL(SetPrinter, s) \
1601 info_ctr.info.info ## lvl1->field1 = 0; \
1602 TESTGETCALL(GetPrinter, q) \
1603 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1604 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1605 q.in.level = lvl2; \
1606 TESTGETCALL(GetPrinter, q) \
1607 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1608 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1609 } while (0)
1611 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1612 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1613 } while (0)
1615 q0.in.level = 0;
1616 do { TESTGETCALL(GetPrinter, q0) } while (0);
1618 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1619 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1621 /* level 0 printername does not stick */
1622 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1623 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1624 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1625 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1626 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1627 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1628 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1629 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1630 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1631 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1632 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1633 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1634 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1635 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1636 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1638 /* servername can be set but does not stick
1639 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1640 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1641 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1644 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1645 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1646 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1647 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1648 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1650 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1651 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1652 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1653 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1654 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1655 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1656 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1657 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1658 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1659 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1661 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1662 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1663 attribute_list[i],
1664 (attribute_list[i] | default_attribute)
1665 ); */
1666 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1667 attribute_list[i],
1668 (attribute_list[i] | default_attribute)
1670 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1671 attribute_list[i],
1672 (attribute_list[i] | default_attribute)
1674 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1675 attribute_list[i],
1676 (attribute_list[i] | default_attribute)
1678 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1679 attribute_list[i],
1680 (attribute_list[i] | default_attribute)
1681 ); */
1682 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1683 attribute_list[i],
1684 (attribute_list[i] | default_attribute)
1686 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1687 attribute_list[i],
1688 (attribute_list[i] | default_attribute)
1690 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1691 attribute_list[i],
1692 (attribute_list[i] | default_attribute)
1694 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1695 attribute_list[i],
1696 (attribute_list[i] | default_attribute)
1697 ); */
1698 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1699 attribute_list[i],
1700 (attribute_list[i] | default_attribute)
1702 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1703 attribute_list[i],
1704 (attribute_list[i] | default_attribute)
1706 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1707 attribute_list[i],
1708 (attribute_list[i] | default_attribute)
1712 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1713 /* level 2 sets do not stick
1714 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1715 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1716 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1717 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1718 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1719 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1722 /* priorities need to be between 0 and 99
1723 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1724 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1725 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1726 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1727 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1728 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1729 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1730 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1731 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1733 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1734 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1736 /* does not stick
1737 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1738 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1740 /* does not stick
1741 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1742 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1744 /* FIXME: gd also test devmode and secdesc behavior */
1747 /* verify composition of level 1 description field */
1748 const char *description;
1749 const char *tmp;
1751 q0.in.level = 1;
1752 do { TESTGETCALL(GetPrinter, q0) } while (0);
1754 description = talloc_strdup(tctx, q0.out.info->info1.description);
1756 q0.in.level = 2;
1757 do { TESTGETCALL(GetPrinter, q0) } while (0);
1759 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1760 q0.out.info->info2.printername,
1761 q0.out.info->info2.drivername,
1762 q0.out.info->info2.location);
1764 do { STRING_EQUAL(description, tmp, "description")} while (0);
1767 return ret;
1770 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1771 do { struct dom_sid *__got = (got), *__expected = (expected); \
1772 if (!dom_sid_equal(__got, __expected)) { \
1773 torture_result(torture_ctx, TORTURE_FAIL, \
1774 __location__": "#got" was %s, expected %s: %s", \
1775 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1776 return false; \
1778 } while(0)
1780 static bool test_security_descriptor_equal(struct torture_context *tctx,
1781 const struct security_descriptor *sd1,
1782 const struct security_descriptor *sd2)
1784 if (sd1 == sd2) {
1785 return true;
1788 if (!sd1 || !sd2) {
1789 torture_comment(tctx, "%s\n", __location__);
1790 return false;
1793 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1794 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1796 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1797 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1799 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1800 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1801 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1802 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1803 return false;
1805 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1806 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1807 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1808 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1809 return false;
1812 return true;
1815 static bool test_sd_set_level(struct torture_context *tctx,
1816 struct dcerpc_binding_handle *b,
1817 struct policy_handle *handle,
1818 uint32_t level,
1819 struct security_descriptor *sd)
1821 struct spoolss_SetPrinterInfoCtr info_ctr;
1822 struct spoolss_DevmodeContainer devmode_ctr;
1823 struct sec_desc_buf secdesc_ctr;
1824 union spoolss_SetPrinterInfo sinfo;
1826 ZERO_STRUCT(devmode_ctr);
1827 ZERO_STRUCT(secdesc_ctr);
1829 switch (level) {
1830 case 2: {
1831 union spoolss_PrinterInfo info;
1832 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1833 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1835 info_ctr.level = 2;
1836 info_ctr.info = sinfo;
1838 break;
1840 case 3: {
1841 struct spoolss_SetPrinterInfo3 info3;
1843 info3.sec_desc_ptr = 0;
1845 info_ctr.level = 3;
1846 info_ctr.info.info3 = &info3;
1848 break;
1850 default:
1851 return false;
1854 secdesc_ctr.sd = sd;
1856 torture_assert(tctx,
1857 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1859 return true;
1862 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1863 struct dcerpc_binding_handle *b,
1864 struct policy_handle *handle)
1866 union spoolss_PrinterInfo info;
1867 struct security_descriptor *sd1, *sd2;
1868 int i;
1870 /* just compare level 2 and level 3 */
1872 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1874 sd1 = info.info2.secdesc;
1876 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1878 sd2 = info.info3.secdesc;
1880 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1881 "SD level 2 != SD level 3");
1884 /* query level 2, set level 2, query level 2 */
1886 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1888 sd1 = info.info2.secdesc;
1890 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1892 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1894 sd2 = info.info2.secdesc;
1895 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1896 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1897 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1900 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1901 "SD level 2 != SD level 2 after SD has been set via level 2");
1904 /* query level 2, set level 3, query level 2 */
1906 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1908 sd1 = info.info2.secdesc;
1910 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1912 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1914 sd2 = info.info2.secdesc;
1916 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1917 "SD level 2 != SD level 2 after SD has been set via level 3");
1919 /* set modified sd level 3, query level 2 */
1921 for (i=0; i < 93; i++) {
1922 struct security_ace a;
1923 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1924 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1925 a.flags = 0;
1926 a.size = 0; /* autogenerated */
1927 a.access_mask = 0;
1928 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1929 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1932 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1934 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1935 sd2 = info.info2.secdesc;
1937 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1938 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1939 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1942 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1943 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1946 return true;
1950 * wrapper call that saves original sd, runs tests, and restores sd
1953 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1954 struct dcerpc_binding_handle *b,
1955 struct policy_handle *handle)
1957 union spoolss_PrinterInfo info;
1958 struct security_descriptor *sd;
1959 bool ret = true;
1961 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1963 /* save original sd */
1965 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1966 "failed to get initial security descriptor");
1968 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1970 /* run tests */
1972 ret = test_PrinterInfo_SDs(tctx, b, handle);
1974 /* restore original sd */
1976 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1977 "failed to restore initial security descriptor");
1979 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1980 ret ? "succeeded" : "failed");
1983 return ret;
1986 static bool test_devmode_set_level(struct torture_context *tctx,
1987 struct dcerpc_binding_handle *b,
1988 struct policy_handle *handle,
1989 uint32_t level,
1990 struct spoolss_DeviceMode *devmode)
1992 struct spoolss_SetPrinterInfoCtr info_ctr;
1993 struct spoolss_DevmodeContainer devmode_ctr;
1994 struct sec_desc_buf secdesc_ctr;
1995 union spoolss_SetPrinterInfo sinfo;
1997 ZERO_STRUCT(devmode_ctr);
1998 ZERO_STRUCT(secdesc_ctr);
2000 switch (level) {
2001 case 2: {
2002 union spoolss_PrinterInfo info;
2003 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2004 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2006 info_ctr.level = 2;
2007 info_ctr.info = sinfo;
2009 break;
2011 case 8: {
2012 struct spoolss_SetPrinterInfo8 info8;
2014 info8.devmode_ptr = 0;
2016 info_ctr.level = 8;
2017 info_ctr.info.info8 = &info8;
2019 break;
2021 default:
2022 return false;
2025 devmode_ctr.devmode = devmode;
2027 torture_assert(tctx,
2028 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2030 return true;
2034 static bool test_devicemode_equal(struct torture_context *tctx,
2035 const struct spoolss_DeviceMode *d1,
2036 const struct spoolss_DeviceMode *d2)
2038 if (d1 == d2) {
2039 return true;
2042 if (!d1 || !d2) {
2043 torture_comment(tctx, "%s\n", __location__);
2044 return false;
2046 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2047 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2048 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2049 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2050 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2051 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2052 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2053 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2054 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2055 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2056 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2057 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2058 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2059 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2060 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2061 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2062 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2063 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2064 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2065 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2066 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2067 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2068 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2069 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2070 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2071 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2072 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2073 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2074 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2075 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2076 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2077 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2078 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2079 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2080 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2082 return true;
2085 static bool test_devicemode_full(struct torture_context *tctx,
2086 struct dcerpc_binding_handle *b,
2087 struct policy_handle *handle)
2089 struct spoolss_SetPrinter s;
2090 struct spoolss_GetPrinter q;
2091 struct spoolss_GetPrinter q0;
2092 struct spoolss_SetPrinterInfoCtr info_ctr;
2093 struct spoolss_SetPrinterInfo8 info8;
2094 union spoolss_PrinterInfo info;
2095 struct spoolss_DevmodeContainer devmode_ctr;
2096 struct sec_desc_buf secdesc_ctr;
2097 uint32_t needed;
2098 bool ret = true;
2099 NTSTATUS status;
2101 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2102 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2103 q.in.level = lvl1; \
2104 TESTGETCALL(GetPrinter, q) \
2105 info_ctr.level = lvl1; \
2106 if (lvl1 == 2) {\
2107 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2108 } else if (lvl1 == 8) {\
2109 info_ctr.info.info ## lvl1 = &info8; \
2111 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2112 devmode_ctr.devmode->field1 = value; \
2113 TESTSETCALL(SetPrinter, s) \
2114 TESTGETCALL(GetPrinter, q) \
2115 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2116 q.in.level = lvl2; \
2117 TESTGETCALL(GetPrinter, q) \
2118 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2119 } while (0)
2121 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2122 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2123 } while (0)
2125 ZERO_STRUCT(devmode_ctr);
2126 ZERO_STRUCT(secdesc_ctr);
2127 ZERO_STRUCT(info8);
2129 s.in.handle = handle;
2130 s.in.command = 0;
2131 s.in.info_ctr = &info_ctr;
2132 s.in.devmode_ctr = &devmode_ctr;
2133 s.in.secdesc_ctr = &secdesc_ctr;
2135 q.in.handle = handle;
2136 q.out.info = &info;
2137 q0 = q;
2139 #if 0
2140 const char *devicename;/* [charset(UTF16)] */
2141 enum spoolss_DeviceModeSpecVersion specversion;
2142 uint16_t driverversion;
2143 uint16_t size;
2144 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2145 uint32_t fields;
2146 #endif
2148 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2149 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2150 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2151 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2152 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2153 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2154 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2155 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2156 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2157 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2158 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2159 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2160 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2161 #if 0
2162 const char *formname;/* [charset(UTF16)] */
2163 #endif
2164 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2165 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2166 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2167 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2168 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2169 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2170 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2171 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2172 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2173 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2174 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2175 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2176 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2177 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2179 return ret;
2182 static bool call_OpenPrinterEx(struct torture_context *tctx,
2183 struct dcerpc_pipe *p,
2184 const char *name,
2185 struct spoolss_DeviceMode *devmode,
2186 struct policy_handle *handle);
2188 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2189 struct dcerpc_pipe *p,
2190 struct policy_handle *handle,
2191 const char *name)
2193 union spoolss_PrinterInfo info;
2194 struct spoolss_DeviceMode *devmode;
2195 struct spoolss_DeviceMode *devmode2;
2196 struct policy_handle handle_devmode;
2197 struct dcerpc_binding_handle *b = p->binding_handle;
2199 /* simply compare level8 and level2 devmode */
2201 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2203 devmode = info.info8.devmode;
2205 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2207 devmode2 = info.info2.devmode;
2209 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2210 "DM level 8 != DM level 2");
2213 /* set devicemode level 8 and see if it persists */
2215 devmode->copies = 93;
2216 devmode->formname = talloc_strdup(tctx, "Legal");
2218 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2220 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2222 devmode2 = info.info8.devmode;
2224 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2225 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2227 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2229 devmode2 = info.info2.devmode;
2231 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2232 "modified DM level 8 != DM level 2");
2235 /* set devicemode level 2 and see if it persists */
2237 devmode->copies = 39;
2238 devmode->formname = talloc_strdup(tctx, "Executive");
2240 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2242 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2244 devmode2 = info.info8.devmode;
2246 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2247 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2249 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2251 devmode2 = info.info2.devmode;
2253 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2254 "modified DM level 8 != DM level 2");
2257 /* check every single bit in public part of devicemode */
2259 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2260 "failed to set every single devicemode component");
2263 /* change formname upon open and see if it persists in getprinter calls */
2265 devmode->formname = talloc_strdup(tctx, "A4");
2266 devmode->copies = 42;
2268 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2269 "failed to open printer handle");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2273 devmode2 = info.info8.devmode;
2275 if (strequal(devmode->devicename, devmode2->devicename)) {
2276 torture_warning(tctx, "devicenames are the same\n");
2277 } else {
2278 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2279 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2282 if (strequal(devmode->formname, devmode2->formname)) {
2283 torture_warning(tctx, "formname are the same\n");
2284 } else {
2285 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2286 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2289 if (devmode->copies == devmode2->copies) {
2290 torture_warning(tctx, "copies are the same\n");
2291 } else {
2292 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2293 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2296 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2298 devmode2 = info.info2.devmode;
2300 if (strequal(devmode->devicename, devmode2->devicename)) {
2301 torture_warning(tctx, "devicenames are the same\n");
2302 } else {
2303 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2304 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2307 if (strequal(devmode->formname, devmode2->formname)) {
2308 torture_warning(tctx, "formname is the same\n");
2309 } else {
2310 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2311 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2314 if (devmode->copies == devmode2->copies) {
2315 torture_warning(tctx, "copies are the same\n");
2316 } else {
2317 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2318 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2321 test_ClosePrinter(tctx, b, &handle_devmode);
2323 return true;
2327 * wrapper call that saves original devmode, runs tests, and restores devmode
2330 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2331 struct dcerpc_pipe *p,
2332 struct policy_handle *handle,
2333 const char *name,
2334 struct spoolss_DeviceMode *addprinter_devmode)
2336 union spoolss_PrinterInfo info;
2337 struct spoolss_DeviceMode *devmode;
2338 bool ret = true;
2339 struct dcerpc_binding_handle *b = p->binding_handle;
2341 torture_comment(tctx, "Testing Printer Devicemodes\n");
2343 /* save original devmode */
2345 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2346 "failed to get initial global devicemode");
2348 devmode = info.info8.devmode;
2350 if (addprinter_devmode) {
2351 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2352 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2356 /* run tests */
2358 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2360 /* restore original devmode */
2362 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2363 "failed to restore initial global device mode");
2365 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2366 ret ? "succeeded" : "failed");
2369 return ret;
2372 bool test_ClosePrinter(struct torture_context *tctx,
2373 struct dcerpc_binding_handle *b,
2374 struct policy_handle *handle)
2376 NTSTATUS status;
2377 struct spoolss_ClosePrinter r;
2379 r.in.handle = handle;
2380 r.out.handle = handle;
2382 torture_comment(tctx, "Testing ClosePrinter\n");
2384 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2385 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2386 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2388 return true;
2391 static bool test_GetForm_args(struct torture_context *tctx,
2392 struct dcerpc_binding_handle *b,
2393 struct policy_handle *handle,
2394 const char *form_name,
2395 uint32_t level,
2396 union spoolss_FormInfo *info_p)
2398 NTSTATUS status;
2399 struct spoolss_GetForm r;
2400 uint32_t needed;
2402 r.in.handle = handle;
2403 r.in.form_name = form_name;
2404 r.in.level = level;
2405 r.in.buffer = NULL;
2406 r.in.offered = 0;
2407 r.out.needed = &needed;
2409 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2411 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2412 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2414 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2415 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2416 r.in.buffer = &blob;
2417 r.in.offered = needed;
2418 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2419 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2421 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2423 torture_assert(tctx, r.out.info, "No form info returned");
2426 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2428 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2430 if (info_p) {
2431 *info_p = *r.out.info;
2434 return true;
2437 static bool test_GetForm(struct torture_context *tctx,
2438 struct dcerpc_binding_handle *b,
2439 struct policy_handle *handle,
2440 const char *form_name,
2441 uint32_t level)
2443 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2446 static bool test_EnumForms(struct torture_context *tctx,
2447 struct dcerpc_binding_handle *b,
2448 struct policy_handle *handle,
2449 bool print_server,
2450 uint32_t level,
2451 uint32_t *count_p,
2452 union spoolss_FormInfo **info_p)
2454 struct spoolss_EnumForms r;
2455 uint32_t needed;
2456 uint32_t count;
2457 union spoolss_FormInfo *info;
2459 r.in.handle = handle;
2460 r.in.level = level;
2461 r.in.buffer = NULL;
2462 r.in.offered = 0;
2463 r.out.needed = &needed;
2464 r.out.count = &count;
2465 r.out.info = &info;
2467 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2469 torture_assert_ntstatus_ok(tctx,
2470 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2471 "EnumForms failed");
2473 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2474 torture_skip(tctx, "EnumForms level 2 not supported");
2477 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2478 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2481 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2482 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2483 r.in.buffer = &blob;
2484 r.in.offered = needed;
2486 torture_assert_ntstatus_ok(tctx,
2487 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2488 "EnumForms failed");
2490 torture_assert(tctx, info, "No forms returned");
2493 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2495 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2497 if (info_p) {
2498 *info_p = info;
2500 if (count_p) {
2501 *count_p = count;
2504 return true;
2507 static bool test_EnumForms_all(struct torture_context *tctx,
2508 struct dcerpc_binding_handle *b,
2509 struct policy_handle *handle,
2510 bool print_server)
2512 uint32_t levels[] = { 1, 2 };
2513 int i, j;
2515 for (i=0; i<ARRAY_SIZE(levels); i++) {
2517 uint32_t count = 0;
2518 union spoolss_FormInfo *info = NULL;
2520 torture_assert(tctx,
2521 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2522 "failed to enum forms");
2524 for (j = 0; j < count; j++) {
2525 if (!print_server) {
2526 torture_assert(tctx,
2527 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2528 "failed to get form");
2533 return true;
2536 static bool test_EnumForms_find_one(struct torture_context *tctx,
2537 struct dcerpc_binding_handle *b,
2538 struct policy_handle *handle,
2539 bool print_server,
2540 const char *form_name)
2542 union spoolss_FormInfo *info;
2543 uint32_t count;
2544 bool found = false;
2545 int i;
2547 torture_assert(tctx,
2548 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2549 "failed to enumerate forms");
2551 for (i=0; i<count; i++) {
2552 if (strequal(form_name, info[i].info1.form_name)) {
2553 found = true;
2554 break;
2558 return found;
2561 static bool test_DeleteForm(struct torture_context *tctx,
2562 struct dcerpc_binding_handle *b,
2563 struct policy_handle *handle,
2564 const char *form_name,
2565 WERROR expected_result)
2567 struct spoolss_DeleteForm r;
2569 r.in.handle = handle;
2570 r.in.form_name = form_name;
2572 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2574 torture_assert_ntstatus_ok(tctx,
2575 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2576 "DeleteForm failed");
2577 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2578 "DeleteForm gave unexpected result");
2579 if (W_ERROR_IS_OK(r.out.result)) {
2580 torture_assert_ntstatus_ok(tctx,
2581 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2582 "2nd DeleteForm failed");
2583 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2584 "2nd DeleteForm failed");
2587 return true;
2590 static bool test_AddForm(struct torture_context *tctx,
2591 struct dcerpc_binding_handle *b,
2592 struct policy_handle *handle,
2593 uint32_t level,
2594 union spoolss_AddFormInfo *info,
2595 WERROR expected_result)
2597 struct spoolss_AddForm r;
2599 if (level != 1) {
2600 torture_skip(tctx, "only level 1 supported");
2603 r.in.handle = handle;
2604 r.in.level = level;
2605 r.in.info = *info;
2607 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2608 r.in.info.info1->form_name, r.in.level,
2609 r.in.info.info1->flags);
2611 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2612 "AddForm failed");
2613 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2614 "AddForm gave unexpected result");
2616 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2617 "2nd AddForm failed");
2618 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2619 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2620 "2nd AddForm gave unexpected result");
2621 } else {
2622 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2623 "2nd AddForm gave unexpected result");
2626 return true;
2629 static bool test_SetForm(struct torture_context *tctx,
2630 struct dcerpc_binding_handle *b,
2631 struct policy_handle *handle,
2632 const char *form_name,
2633 uint32_t level,
2634 union spoolss_AddFormInfo *info)
2636 struct spoolss_SetForm r;
2638 r.in.handle = handle;
2639 r.in.form_name = form_name;
2640 r.in.level = level;
2641 r.in.info = *info;
2643 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2644 form_name, r.in.level);
2646 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2647 "SetForm failed");
2649 torture_assert_werr_ok(tctx, r.out.result,
2650 "SetForm failed");
2652 return true;
2655 static bool test_GetForm_winreg(struct torture_context *tctx,
2656 struct dcerpc_binding_handle *b,
2657 struct policy_handle *handle,
2658 const char *key_name,
2659 const char *form_name,
2660 enum winreg_Type *w_type,
2661 uint32_t *w_size,
2662 uint32_t *w_length,
2663 uint8_t **w_data);
2665 static bool test_Forms_args(struct torture_context *tctx,
2666 struct dcerpc_binding_handle *b,
2667 struct policy_handle *handle,
2668 bool print_server,
2669 const char *printer_name,
2670 struct dcerpc_binding_handle *winreg_handle,
2671 struct policy_handle *hive_handle,
2672 const char *form_name,
2673 struct spoolss_AddFormInfo1 *info1,
2674 WERROR expected_add_result,
2675 WERROR expected_delete_result)
2677 union spoolss_FormInfo info;
2678 union spoolss_AddFormInfo add_info;
2680 enum winreg_Type w_type;
2681 uint32_t w_size;
2682 uint32_t w_length;
2683 uint8_t *w_data;
2685 add_info.info1 = info1;
2687 torture_assert(tctx,
2688 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2689 "failed to add form");
2691 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2693 torture_assert(tctx,
2694 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2695 "failed to get form via winreg");
2697 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2698 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2699 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2700 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2701 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2702 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2703 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2704 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2705 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2706 /* skip index here */
2707 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2710 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2711 torture_assert(tctx,
2712 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2713 "failed to get added form");
2715 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2716 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2717 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2718 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2719 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2720 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2721 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2723 if (winreg_handle && hive_handle) {
2724 torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2725 torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2726 torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2727 torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2728 torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2729 torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2730 /* skip index here */
2731 torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2734 add_info.info1->size.width = 1234;
2736 torture_assert(tctx,
2737 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2738 "failed to set form");
2739 torture_assert(tctx,
2740 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2741 "failed to get setted form");
2743 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2746 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2747 torture_assert(tctx,
2748 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2749 "Newly added form not found in enum call");
2752 torture_assert(tctx,
2753 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2754 "failed to delete form");
2756 return true;
2759 static bool test_Forms(struct torture_context *tctx,
2760 struct dcerpc_binding_handle *b,
2761 struct policy_handle *handle,
2762 bool print_server,
2763 const char *printer_name,
2764 struct dcerpc_binding_handle *winreg_handle,
2765 struct policy_handle *hive_handle)
2767 const struct spoolss_FormSize size = {
2768 .width = 50,
2769 .height = 25
2771 const struct spoolss_FormArea area = {
2772 .left = 5,
2773 .top = 10,
2774 .right = 45,
2775 .bottom = 15
2777 int i;
2779 struct {
2780 struct spoolss_AddFormInfo1 info1;
2781 WERROR expected_add_result;
2782 WERROR expected_delete_result;
2783 } forms[] = {
2785 .info1 = {
2786 .flags = SPOOLSS_FORM_USER,
2787 .form_name = "testform_user",
2788 .size = size,
2789 .area = area,
2791 .expected_add_result = WERR_OK,
2792 .expected_delete_result = WERR_OK
2795 weird, we can add a builtin form but we can never remove it
2796 again - gd
2799 .info1 = {
2800 .flags = SPOOLSS_FORM_BUILTIN,
2801 .form_name = "testform_builtin",
2802 .size = size,
2803 .area = area,
2805 .expected_add_result = WERR_OK,
2806 .expected_delete_result = WERR_INVALID_PARAM,
2810 .info1 = {
2811 .flags = SPOOLSS_FORM_PRINTER,
2812 .form_name = "testform_printer",
2813 .size = size,
2814 .area = area,
2816 .expected_add_result = WERR_OK,
2817 .expected_delete_result = WERR_OK
2820 .info1 = {
2821 .flags = SPOOLSS_FORM_USER,
2822 .form_name = "Letter",
2823 .size = size,
2824 .area = area,
2826 .expected_add_result = WERR_FILE_EXISTS,
2827 .expected_delete_result = WERR_INVALID_PARAM
2830 .info1 = {
2831 .flags = SPOOLSS_FORM_BUILTIN,
2832 .form_name = "Letter",
2833 .size = size,
2834 .area = area,
2836 .expected_add_result = WERR_FILE_EXISTS,
2837 .expected_delete_result = WERR_INVALID_PARAM
2840 .info1 = {
2841 .flags = SPOOLSS_FORM_PRINTER,
2842 .form_name = "Letter",
2843 .size = size,
2844 .area = area,
2846 .expected_add_result = WERR_FILE_EXISTS,
2847 .expected_delete_result = WERR_INVALID_PARAM
2850 .info1 = {
2851 .flags = 12345,
2852 .form_name = "invalid_flags",
2853 .size = size,
2854 .area = area,
2856 .expected_add_result = WERR_INVALID_PARAM,
2857 .expected_delete_result = WERR_INVALID_FORM_NAME
2862 for (i=0; i < ARRAY_SIZE(forms); i++) {
2863 torture_assert(tctx,
2864 test_Forms_args(tctx, b, handle, print_server, printer_name,
2865 winreg_handle, hive_handle,
2866 forms[i].info1.form_name,
2867 &forms[i].info1,
2868 forms[i].expected_add_result,
2869 forms[i].expected_delete_result),
2870 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2873 return true;
2876 static bool test_EnumPorts_old(struct torture_context *tctx,
2877 void *private_data)
2879 struct test_spoolss_context *ctx =
2880 talloc_get_type_abort(private_data, struct test_spoolss_context);
2882 NTSTATUS status;
2883 struct spoolss_EnumPorts r;
2884 uint32_t needed;
2885 uint32_t count;
2886 union spoolss_PortInfo *info;
2887 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2888 struct dcerpc_binding_handle *b = p->binding_handle;
2890 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2891 dcerpc_server_name(p));
2892 r.in.level = 2;
2893 r.in.buffer = NULL;
2894 r.in.offered = 0;
2895 r.out.needed = &needed;
2896 r.out.count = &count;
2897 r.out.info = &info;
2899 torture_comment(tctx, "Testing EnumPorts\n");
2901 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2903 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2905 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2906 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2907 r.in.buffer = &blob;
2908 r.in.offered = needed;
2910 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2911 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2912 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2914 torture_assert(tctx, info, "No ports returned");
2917 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2919 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
2921 return true;
2924 static bool test_AddPort(struct torture_context *tctx,
2925 void *private_data)
2927 struct test_spoolss_context *ctx =
2928 talloc_get_type_abort(private_data, struct test_spoolss_context);
2930 NTSTATUS status;
2931 struct spoolss_AddPort r;
2932 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2933 struct dcerpc_binding_handle *b = p->binding_handle;
2935 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2936 dcerpc_server_name(p));
2937 r.in.unknown = 0;
2938 r.in.monitor_name = "foo";
2940 torture_comment(tctx, "Testing AddPort\n");
2942 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2944 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2946 /* win2k3 returns WERR_NOT_SUPPORTED */
2948 #if 0
2950 if (!W_ERROR_IS_OK(r.out.result)) {
2951 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2952 return false;
2955 #endif
2957 return true;
2960 static bool test_GetJob_args(struct torture_context *tctx,
2961 struct dcerpc_binding_handle *b,
2962 struct policy_handle *handle,
2963 uint32_t job_id,
2964 uint32_t level,
2965 union spoolss_JobInfo *info_p)
2967 NTSTATUS status;
2968 struct spoolss_GetJob r;
2969 union spoolss_JobInfo info;
2970 uint32_t needed;
2972 r.in.handle = handle;
2973 r.in.job_id = job_id;
2974 r.in.level = level;
2975 r.in.buffer = NULL;
2976 r.in.offered = 0;
2977 r.out.needed = &needed;
2978 r.out.info = &info;
2980 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2982 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2983 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2984 if (level == 0) {
2985 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2988 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2989 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2990 r.in.buffer = &blob;
2991 r.in.offered = needed;
2993 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2994 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2997 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2998 torture_assert(tctx, r.out.info, "No job info returned");
3000 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3002 if (info_p) {
3003 *info_p = *r.out.info;
3006 return true;
3009 static bool test_GetJob(struct torture_context *tctx,
3010 struct dcerpc_binding_handle *b,
3011 struct policy_handle *handle,
3012 uint32_t job_id)
3014 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3015 uint32_t i;
3017 for (i=0; i < ARRAY_SIZE(levels); i++) {
3018 torture_assert(tctx,
3019 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3020 "GetJob failed");
3023 return true;
3026 static bool test_SetJob(struct torture_context *tctx,
3027 struct dcerpc_binding_handle *b,
3028 struct policy_handle *handle,
3029 uint32_t job_id,
3030 struct spoolss_JobInfoContainer *ctr,
3031 enum spoolss_JobControl command)
3033 NTSTATUS status;
3034 struct spoolss_SetJob r;
3036 r.in.handle = handle;
3037 r.in.job_id = job_id;
3038 r.in.ctr = ctr;
3039 r.in.command = command;
3041 switch (command) {
3042 case SPOOLSS_JOB_CONTROL_PAUSE:
3043 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3044 break;
3045 case SPOOLSS_JOB_CONTROL_RESUME:
3046 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3047 break;
3048 case SPOOLSS_JOB_CONTROL_CANCEL:
3049 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3050 break;
3051 case SPOOLSS_JOB_CONTROL_RESTART:
3052 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3053 break;
3054 case SPOOLSS_JOB_CONTROL_DELETE:
3055 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3056 break;
3057 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3058 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3059 break;
3060 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3061 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3062 break;
3063 case SPOOLSS_JOB_CONTROL_RETAIN:
3064 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3065 break;
3066 case SPOOLSS_JOB_CONTROL_RELEASE:
3067 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3068 break;
3069 default:
3070 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3071 break;
3074 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3075 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3076 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3078 return true;
3081 static bool test_AddJob(struct torture_context *tctx,
3082 struct dcerpc_binding_handle *b,
3083 struct policy_handle *handle)
3085 NTSTATUS status;
3086 struct spoolss_AddJob r;
3087 uint32_t needed;
3089 r.in.level = 0;
3090 r.in.handle = handle;
3091 r.in.offered = 0;
3092 r.out.needed = &needed;
3093 r.in.buffer = r.out.buffer = NULL;
3095 torture_comment(tctx, "Testing AddJob\n");
3097 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3098 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3100 r.in.level = 1;
3102 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3103 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3105 return true;
3109 static bool test_EnumJobs_args(struct torture_context *tctx,
3110 struct dcerpc_binding_handle *b,
3111 struct policy_handle *handle,
3112 uint32_t level,
3113 uint32_t *count_p,
3114 union spoolss_JobInfo **info_p)
3116 NTSTATUS status;
3117 struct spoolss_EnumJobs r;
3118 uint32_t needed;
3119 uint32_t count;
3120 union spoolss_JobInfo *info;
3122 r.in.handle = handle;
3123 r.in.firstjob = 0;
3124 r.in.numjobs = 0xffffffff;
3125 r.in.level = level;
3126 r.in.buffer = NULL;
3127 r.in.offered = 0;
3128 r.out.needed = &needed;
3129 r.out.count = &count;
3130 r.out.info = &info;
3132 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3134 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3136 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3138 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3139 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3140 r.in.buffer = &blob;
3141 r.in.offered = needed;
3143 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3145 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3146 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3147 torture_assert(tctx, info, "No jobs returned");
3149 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3151 } else {
3152 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3155 if (count_p) {
3156 *count_p = count;
3158 if (info_p) {
3159 *info_p = info;
3162 return true;
3165 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3166 struct dcerpc_binding_handle *b,
3167 struct policy_handle *handle,
3168 uint32_t *job_id)
3170 NTSTATUS status;
3171 struct spoolss_StartDocPrinter s;
3172 struct spoolss_DocumentInfo1 info1;
3173 struct spoolss_StartPagePrinter sp;
3174 struct spoolss_WritePrinter w;
3175 struct spoolss_EndPagePrinter ep;
3176 struct spoolss_EndDocPrinter e;
3177 int i;
3178 uint32_t num_written;
3180 torture_comment(tctx, "Testing StartDocPrinter\n");
3182 s.in.handle = handle;
3183 s.in.level = 1;
3184 s.in.info.info1 = &info1;
3185 s.out.job_id = job_id;
3186 info1.document_name = "TorturePrintJob";
3187 info1.output_file = NULL;
3188 info1.datatype = "RAW";
3190 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3191 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3192 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3194 for (i=1; i < 4; i++) {
3195 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3197 sp.in.handle = handle;
3199 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3200 torture_assert_ntstatus_ok(tctx, status,
3201 "dcerpc_spoolss_StartPagePrinter failed");
3202 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3204 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3206 w.in.handle = handle;
3207 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3208 w.out.num_written = &num_written;
3210 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3211 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3212 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3214 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3216 ep.in.handle = handle;
3218 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3219 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3220 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3223 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3225 e.in.handle = handle;
3227 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3228 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3229 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3231 return true;
3234 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3235 struct dcerpc_binding_handle *b,
3236 struct policy_handle *handle,
3237 uint32_t num_jobs,
3238 uint32_t *job_ids)
3240 uint32_t count;
3241 union spoolss_JobInfo *info = NULL;
3242 int i;
3244 torture_assert(tctx,
3245 test_AddJob(tctx, b, handle),
3246 "AddJob failed");
3248 torture_assert(tctx,
3249 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3250 "EnumJobs level 1 failed");
3252 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3254 for (i=0; i < num_jobs; i++) {
3255 union spoolss_JobInfo ginfo;
3256 const char *document_name;
3257 const char *new_document_name = "any_other_docname";
3258 struct spoolss_JobInfoContainer ctr;
3259 struct spoolss_SetJobInfo1 info1;
3261 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3263 torture_assert(tctx,
3264 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3265 "failed to call test_GetJob");
3267 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3269 document_name = ginfo.info1.document_name;
3271 info1.job_id = ginfo.info1.job_id;
3272 info1.printer_name = ginfo.info1.printer_name;
3273 info1.server_name = ginfo.info1.server_name;
3274 info1.user_name = ginfo.info1.user_name;
3275 info1.document_name = new_document_name;
3276 info1.data_type = ginfo.info1.data_type;
3277 info1.text_status = ginfo.info1.text_status;
3278 info1.status = ginfo.info1.status;
3279 info1.priority = ginfo.info1.priority;
3280 info1.position = ginfo.info1.position;
3281 info1.total_pages = ginfo.info1.total_pages;
3282 info1.pages_printed = ginfo.info1.pages_printed;
3283 info1.submitted = ginfo.info1.submitted;
3285 ctr.level = 1;
3286 ctr.info.info1 = &info1;
3288 torture_assert(tctx,
3289 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3290 "failed to call test_SetJob level 1");
3292 torture_assert(tctx,
3293 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3294 "failed to call test_GetJob");
3296 if (strequal(ginfo.info1.document_name, document_name)) {
3297 torture_warning(tctx,
3298 talloc_asprintf(tctx, "document_name did *NOT* change from '%s' to '%s'\n",
3299 document_name, new_document_name));
3303 for (i=0; i < num_jobs; i++) {
3304 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3305 torture_warning(tctx, "failed to pause printjob\n");
3307 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3308 torture_warning(tctx, "failed to resume printjob\n");
3312 return true;
3315 static bool test_DoPrintTest(struct torture_context *tctx,
3316 struct dcerpc_binding_handle *b,
3317 struct policy_handle *handle)
3319 bool ret = true;
3320 uint32_t num_jobs = 8;
3321 uint32_t *job_ids;
3322 int i;
3324 torture_comment(tctx, "Testing real print operations\n");
3326 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3328 for (i=0; i < num_jobs; i++) {
3329 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3332 for (i=0; i < num_jobs; i++) {
3333 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3336 if (ret == true) {
3337 torture_comment(tctx, "real print operations test succeeded\n\n");
3340 return ret;
3343 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3344 struct dcerpc_binding_handle *b,
3345 struct policy_handle *handle)
3347 bool ret = true;
3348 uint32_t num_jobs = 8;
3349 uint32_t *job_ids;
3350 int i;
3351 torture_comment(tctx, "Testing real print operations (extended)\n");
3353 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3355 for (i=0; i < num_jobs; i++) {
3356 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3359 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3361 for (i=0; i < num_jobs; i++) {
3362 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3365 if (ret == true) {
3366 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3369 return ret;
3372 static bool test_PausePrinter(struct torture_context *tctx,
3373 struct dcerpc_binding_handle *b,
3374 struct policy_handle *handle)
3376 NTSTATUS status;
3377 struct spoolss_SetPrinter r;
3378 struct spoolss_SetPrinterInfoCtr info_ctr;
3379 struct spoolss_DevmodeContainer devmode_ctr;
3380 struct sec_desc_buf secdesc_ctr;
3382 info_ctr.level = 0;
3383 info_ctr.info.info0 = NULL;
3385 ZERO_STRUCT(devmode_ctr);
3386 ZERO_STRUCT(secdesc_ctr);
3388 r.in.handle = handle;
3389 r.in.info_ctr = &info_ctr;
3390 r.in.devmode_ctr = &devmode_ctr;
3391 r.in.secdesc_ctr = &secdesc_ctr;
3392 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3394 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3396 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3398 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3400 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3402 return true;
3405 static bool test_ResumePrinter(struct torture_context *tctx,
3406 struct dcerpc_binding_handle *b,
3407 struct policy_handle *handle)
3409 NTSTATUS status;
3410 struct spoolss_SetPrinter r;
3411 struct spoolss_SetPrinterInfoCtr info_ctr;
3412 struct spoolss_DevmodeContainer devmode_ctr;
3413 struct sec_desc_buf secdesc_ctr;
3415 info_ctr.level = 0;
3416 info_ctr.info.info0 = NULL;
3418 ZERO_STRUCT(devmode_ctr);
3419 ZERO_STRUCT(secdesc_ctr);
3421 r.in.handle = handle;
3422 r.in.info_ctr = &info_ctr;
3423 r.in.devmode_ctr = &devmode_ctr;
3424 r.in.secdesc_ctr = &secdesc_ctr;
3425 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3427 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3429 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3431 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3433 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3435 return true;
3438 static bool test_GetPrinterData(struct torture_context *tctx,
3439 struct dcerpc_binding_handle *b,
3440 struct policy_handle *handle,
3441 const char *value_name,
3442 enum winreg_Type *type_p,
3443 uint8_t **data_p,
3444 uint32_t *needed_p)
3446 NTSTATUS status;
3447 struct spoolss_GetPrinterData r;
3448 uint32_t needed;
3449 enum winreg_Type type;
3450 union spoolss_PrinterData data;
3452 r.in.handle = handle;
3453 r.in.value_name = value_name;
3454 r.in.offered = 0;
3455 r.out.needed = &needed;
3456 r.out.type = &type;
3457 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3459 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3461 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3462 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3464 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3465 r.in.offered = needed;
3466 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3467 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3468 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3471 torture_assert_werr_ok(tctx, r.out.result,
3472 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3474 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3476 if (type_p) {
3477 *type_p = type;
3480 if (data_p) {
3481 *data_p = r.out.data;
3484 if (needed_p) {
3485 *needed_p = needed;
3488 return true;
3491 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3492 struct dcerpc_pipe *p,
3493 struct policy_handle *handle,
3494 const char *key_name,
3495 const char *value_name,
3496 enum winreg_Type *type_p,
3497 uint8_t **data_p,
3498 uint32_t *needed_p)
3500 NTSTATUS status;
3501 struct spoolss_GetPrinterDataEx r;
3502 enum winreg_Type type;
3503 uint32_t needed;
3504 union spoolss_PrinterData data;
3505 struct dcerpc_binding_handle *b = p->binding_handle;
3507 r.in.handle = handle;
3508 r.in.key_name = key_name;
3509 r.in.value_name = value_name;
3510 r.in.offered = 0;
3511 r.out.type = &type;
3512 r.out.needed = &needed;
3513 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3515 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3516 r.in.key_name, r.in.value_name);
3518 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3519 if (!NT_STATUS_IS_OK(status)) {
3520 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3521 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3523 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3526 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3527 r.in.offered = needed;
3528 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3529 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3530 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3533 torture_assert_werr_ok(tctx, r.out.result,
3534 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3536 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3538 if (type_p) {
3539 *type_p = type;
3542 if (data_p) {
3543 *data_p = r.out.data;
3546 if (needed_p) {
3547 *needed_p = needed;
3550 return true;
3553 static bool test_get_environment(struct torture_context *tctx,
3554 struct dcerpc_binding_handle *b,
3555 struct policy_handle *handle,
3556 const char **architecture)
3558 DATA_BLOB blob;
3559 enum winreg_Type type;
3560 uint8_t *data;
3561 uint32_t needed;
3563 torture_assert(tctx,
3564 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3565 "failed to get Architecture");
3567 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3569 blob = data_blob_const(data, needed);
3570 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3572 return true;
3575 static bool test_GetPrinterData_list(struct torture_context *tctx,
3576 void *private_data)
3578 struct test_spoolss_context *ctx =
3579 talloc_get_type_abort(private_data, struct test_spoolss_context);
3580 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3581 struct dcerpc_binding_handle *b = p->binding_handle;
3582 const char *list[] = {
3583 "W3SvcInstalled",
3584 "BeepEnabled",
3585 "EventLog",
3586 /* "NetPopup", not on w2k8 */
3587 /* "NetPopupToComputer", not on w2k8 */
3588 "MajorVersion",
3589 "MinorVersion",
3590 "DefaultSpoolDirectory",
3591 "Architecture",
3592 "DsPresent",
3593 "OSVersion",
3594 /* "OSVersionEx", not on s3 */
3595 "DNSMachineName"
3597 int i;
3599 for (i=0; i < ARRAY_SIZE(list); i++) {
3600 enum winreg_Type type, type_ex;
3601 uint8_t *data, *data_ex;
3602 uint32_t needed, needed_ex;
3604 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3605 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3606 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3607 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3608 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3609 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3610 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3613 return true;
3616 static bool test_EnumPrinterData(struct torture_context *tctx,
3617 struct dcerpc_pipe *p,
3618 struct policy_handle *handle,
3619 uint32_t enum_index,
3620 uint32_t value_offered,
3621 uint32_t data_offered,
3622 enum winreg_Type *type_p,
3623 uint32_t *value_needed_p,
3624 uint32_t *data_needed_p,
3625 const char **value_name_p,
3626 uint8_t **data_p,
3627 WERROR *result_p)
3629 struct spoolss_EnumPrinterData r;
3630 uint32_t data_needed;
3631 uint32_t value_needed;
3632 enum winreg_Type type;
3633 struct dcerpc_binding_handle *b = p->binding_handle;
3635 r.in.handle = handle;
3636 r.in.enum_index = enum_index;
3637 r.in.value_offered = value_offered;
3638 r.in.data_offered = data_offered;
3639 r.out.data_needed = &data_needed;
3640 r.out.value_needed = &value_needed;
3641 r.out.type = &type;
3642 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3643 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3645 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3647 torture_assert_ntstatus_ok(tctx,
3648 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3649 "EnumPrinterData failed");
3651 if (type_p) {
3652 *type_p = type;
3654 if (value_needed_p) {
3655 *value_needed_p = value_needed;
3657 if (data_needed_p) {
3658 *data_needed_p = data_needed;
3660 if (value_name_p) {
3661 *value_name_p = r.out.value_name;
3663 if (data_p) {
3664 *data_p = r.out.data;
3666 if (result_p) {
3667 *result_p = r.out.result;
3670 return true;
3674 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3675 struct dcerpc_pipe *p,
3676 struct policy_handle *handle)
3678 uint32_t enum_index = 0;
3679 enum winreg_Type type;
3680 uint32_t value_needed;
3681 uint32_t data_needed;
3682 uint8_t *data;
3683 const char *value_name;
3684 WERROR result;
3686 torture_comment(tctx, "Testing EnumPrinterData\n");
3688 do {
3689 torture_assert(tctx,
3690 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3691 &type, &value_needed, &data_needed,
3692 &value_name, &data, &result),
3693 "EnumPrinterData failed");
3695 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3696 break;
3699 torture_assert(tctx,
3700 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3701 &type, &value_needed, &data_needed,
3702 &value_name, &data, &result),
3703 "EnumPrinterData failed");
3705 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3706 break;
3709 enum_index++;
3711 } while (W_ERROR_IS_OK(result));
3713 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3715 return true;
3718 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3719 struct dcerpc_binding_handle *b,
3720 struct policy_handle *handle,
3721 const char *key_name,
3722 uint32_t *count_p,
3723 struct spoolss_PrinterEnumValues **info_p)
3725 struct spoolss_EnumPrinterDataEx r;
3726 struct spoolss_PrinterEnumValues *info;
3727 uint32_t needed;
3728 uint32_t count;
3730 r.in.handle = handle;
3731 r.in.key_name = key_name;
3732 r.in.offered = 0;
3733 r.out.needed = &needed;
3734 r.out.count = &count;
3735 r.out.info = &info;
3737 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3739 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3740 "EnumPrinterDataEx failed");
3741 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3742 r.in.offered = needed;
3743 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3744 "EnumPrinterDataEx failed");
3747 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3749 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3751 if (count_p) {
3752 *count_p = count;
3754 if (info_p) {
3755 *info_p = info;
3758 return true;
3761 static bool test_SetPrinterData(struct torture_context *tctx,
3762 struct dcerpc_binding_handle *b,
3763 struct policy_handle *handle,
3764 const char *value_name,
3765 enum winreg_Type type,
3766 uint8_t *data,
3767 uint32_t offered);
3768 static bool test_DeletePrinterData(struct torture_context *tctx,
3769 struct dcerpc_binding_handle *b,
3770 struct policy_handle *handle,
3771 const char *value_name);
3773 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3774 struct dcerpc_pipe *p,
3775 struct policy_handle *handle)
3777 uint32_t count;
3778 struct spoolss_PrinterEnumValues *info;
3779 int i;
3780 uint32_t value_needed, data_needed;
3781 uint32_t value_offered, data_offered;
3782 WERROR result;
3783 struct dcerpc_binding_handle *b = p->binding_handle;
3785 enum winreg_Type type;
3786 DATA_BLOB blob;
3788 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3790 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3791 type = REG_SZ;
3793 torture_assert(tctx,
3794 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3795 "SetPrinterData failed");
3797 blob = data_blob_string_const("torture_data2");
3799 torture_assert(tctx,
3800 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3801 "SetPrinterData failed");
3803 blob = data_blob_talloc(tctx, NULL, 4);
3804 SIVAL(blob.data, 0, 0x11223344);
3806 torture_assert(tctx,
3807 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3808 "SetPrinterData failed");
3810 torture_assert(tctx,
3811 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3812 "failed to call EnumPrinterDataEx");
3814 /* get the max sizes for value and data */
3816 torture_assert(tctx,
3817 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3818 NULL, &value_needed, &data_needed,
3819 NULL, NULL, &result),
3820 "EnumPrinterData failed");
3821 torture_assert_werr_ok(tctx, result, "unexpected result");
3823 /* check if the reply from the EnumPrinterData really matches max values */
3825 for (i=0; i < count; i++) {
3826 if (info[i].value_name_len > value_needed) {
3827 torture_fail(tctx,
3828 talloc_asprintf(tctx,
3829 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3830 info[i].value_name_len, value_needed));
3832 if (info[i].data_length > data_needed) {
3833 torture_fail(tctx,
3834 talloc_asprintf(tctx,
3835 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3836 info[i].data_length, data_needed));
3840 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3841 * sort or not sort the replies by value name, we should be able to do
3842 * the following entry comparison */
3844 data_offered = data_needed;
3845 value_offered = value_needed;
3847 for (i=0; i < count; i++) {
3849 const char *value_name;
3850 uint8_t *data;
3852 torture_assert(tctx,
3853 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3854 &type, &value_needed, &data_needed,
3855 &value_name, &data, &result),
3856 "EnumPrinterData failed");
3858 if (i -1 == count) {
3859 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3860 "unexpected result");
3861 break;
3862 } else {
3863 torture_assert_werr_ok(tctx, result, "unexpected result");
3866 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3867 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3868 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3869 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3870 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3873 torture_assert(tctx,
3874 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3875 "DeletePrinterData failed");
3876 torture_assert(tctx,
3877 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3878 "DeletePrinterData failed");
3879 torture_assert(tctx,
3880 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3881 "DeletePrinterData failed");
3883 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3885 return true;
3888 static bool test_DeletePrinterData(struct torture_context *tctx,
3889 struct dcerpc_binding_handle *b,
3890 struct policy_handle *handle,
3891 const char *value_name)
3893 NTSTATUS status;
3894 struct spoolss_DeletePrinterData r;
3896 r.in.handle = handle;
3897 r.in.value_name = value_name;
3899 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3900 r.in.value_name);
3902 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3904 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3905 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3907 return true;
3910 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3911 struct dcerpc_binding_handle *b,
3912 struct policy_handle *handle,
3913 const char *key_name,
3914 const char *value_name)
3916 struct spoolss_DeletePrinterDataEx r;
3918 r.in.handle = handle;
3919 r.in.key_name = key_name;
3920 r.in.value_name = value_name;
3922 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3923 r.in.key_name, r.in.value_name);
3925 torture_assert_ntstatus_ok(tctx,
3926 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3927 "DeletePrinterDataEx failed");
3928 torture_assert_werr_ok(tctx, r.out.result,
3929 "DeletePrinterDataEx failed");
3931 return true;
3934 static bool test_DeletePrinterKey(struct torture_context *tctx,
3935 struct dcerpc_binding_handle *b,
3936 struct policy_handle *handle,
3937 const char *key_name)
3939 struct spoolss_DeletePrinterKey r;
3941 r.in.handle = handle;
3942 r.in.key_name = key_name;
3944 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3946 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3947 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3948 return true;
3951 torture_assert_ntstatus_ok(tctx,
3952 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3953 "DeletePrinterKey failed");
3954 torture_assert_werr_ok(tctx, r.out.result,
3955 "DeletePrinterKey failed");
3957 return true;
3960 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3961 struct dcerpc_binding_handle *b,
3962 struct policy_handle *handle)
3964 struct winreg_OpenHKLM r;
3966 r.in.system_name = NULL;
3967 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3968 r.out.handle = handle;
3970 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3972 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3973 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3975 return true;
3978 static void init_winreg_String(struct winreg_String *name, const char *s)
3980 name->name = s;
3981 if (s) {
3982 name->name_len = 2 * (strlen_m(s) + 1);
3983 name->name_size = name->name_len;
3984 } else {
3985 name->name_len = 0;
3986 name->name_size = 0;
3990 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3991 struct dcerpc_binding_handle *b,
3992 struct policy_handle *hive_handle,
3993 const char *keyname,
3994 uint32_t options,
3995 struct policy_handle *key_handle)
3997 struct winreg_OpenKey r;
3999 r.in.parent_handle = hive_handle;
4000 init_winreg_String(&r.in.keyname, keyname);
4001 r.in.options = options;
4002 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4003 r.out.handle = key_handle;
4005 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4007 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4008 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4010 return true;
4013 static bool test_winreg_OpenKey(struct torture_context *tctx,
4014 struct dcerpc_binding_handle *b,
4015 struct policy_handle *hive_handle,
4016 const char *keyname,
4017 struct policy_handle *key_handle)
4019 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4020 REG_OPTION_NON_VOLATILE, key_handle);
4023 static bool test_winreg_CloseKey(struct torture_context *tctx,
4024 struct dcerpc_binding_handle *b,
4025 struct policy_handle *handle)
4027 struct winreg_CloseKey r;
4029 r.in.handle = handle;
4030 r.out.handle = handle;
4032 torture_comment(tctx, "Testing winreg_CloseKey\n");
4034 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4035 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4037 return true;
4040 bool test_winreg_QueryValue(struct torture_context *tctx,
4041 struct dcerpc_binding_handle *b,
4042 struct policy_handle *handle,
4043 const char *value_name,
4044 enum winreg_Type *type_p,
4045 uint32_t *data_size_p,
4046 uint32_t *data_length_p,
4047 uint8_t **data_p)
4049 struct winreg_QueryValue r;
4050 enum winreg_Type type = REG_NONE;
4051 uint32_t data_size = 0;
4052 uint32_t data_length = 0;
4053 struct winreg_String valuename;
4054 uint8_t *data = NULL;
4056 init_winreg_String(&valuename, value_name);
4058 data = talloc_zero_array(tctx, uint8_t, 0);
4060 r.in.handle = handle;
4061 r.in.value_name = &valuename;
4062 r.in.type = &type;
4063 r.in.data_size = &data_size;
4064 r.in.data_length = &data_length;
4065 r.in.data = data;
4066 r.out.type = &type;
4067 r.out.data = data;
4068 r.out.data_size = &data_size;
4069 r.out.data_length = &data_length;
4071 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4073 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4074 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4075 *r.in.data_size = *r.out.data_size;
4076 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4077 r.in.data = data;
4078 r.out.data = data;
4079 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4081 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4083 if (type_p) {
4084 *type_p = *r.out.type;
4086 if (data_size_p) {
4087 *data_size_p = *r.out.data_size;
4089 if (data_length_p) {
4090 *data_length_p = *r.out.data_length;
4092 if (data_p) {
4093 *data_p = r.out.data;
4096 return true;
4099 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4100 struct dcerpc_binding_handle *b,
4101 struct policy_handle *handle,
4102 const char *printer_name,
4103 const char *key_name,
4104 const char *value_name,
4105 enum winreg_Type *w_type,
4106 uint32_t *w_size,
4107 uint32_t *w_length,
4108 uint8_t **w_data)
4110 const char *printer_key;
4111 struct policy_handle key_handle;
4113 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4114 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4116 torture_assert(tctx,
4117 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4119 torture_assert(tctx,
4120 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4122 torture_assert(tctx,
4123 test_winreg_CloseKey(tctx, b, &key_handle), "");
4125 return true;
4128 static bool test_GetForm_winreg(struct torture_context *tctx,
4129 struct dcerpc_binding_handle *b,
4130 struct policy_handle *handle,
4131 const char *key_name,
4132 const char *form_name,
4133 enum winreg_Type *w_type,
4134 uint32_t *w_size,
4135 uint32_t *w_length,
4136 uint8_t **w_data)
4138 struct policy_handle key_handle;
4140 torture_assert(tctx,
4141 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4143 torture_assert(tctx,
4144 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4146 torture_assert(tctx,
4147 test_winreg_CloseKey(tctx, b, &key_handle), "");
4149 return true;
4152 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4153 struct dcerpc_binding_handle *b,
4154 struct policy_handle *handle,
4155 const char *symlink_keyname,
4156 const char *symlink_destination)
4158 /* check if the first key is a symlink to the second key */
4160 enum winreg_Type w_type;
4161 uint32_t w_size;
4162 uint32_t w_length;
4163 uint8_t *w_data;
4164 struct policy_handle key_handle;
4165 DATA_BLOB blob;
4166 const char *str;
4168 if (torture_setting_bool(tctx, "samba3", false)) {
4169 torture_skip(tctx, "skip winreg symlink test against samba");
4172 torture_assert(tctx,
4173 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4174 "failed to open key link");
4176 torture_assert(tctx,
4177 test_winreg_QueryValue(tctx, b, &key_handle,
4178 "SymbolicLinkValue",
4179 &w_type, &w_size, &w_length, &w_data),
4180 "failed to query for 'SymbolicLinkValue' attribute");
4182 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4184 blob = data_blob(w_data, w_size);
4185 str = reg_val_data_string(tctx, REG_SZ, blob);
4187 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4189 torture_assert(tctx,
4190 test_winreg_CloseKey(tctx, b, &key_handle),
4191 "failed to close key link");
4193 return true;
4196 static const char *strip_unc(const char *unc)
4198 char *name;
4200 if (!unc) {
4201 return NULL;
4204 if (unc[0] == '\\' && unc[1] == '\\') {
4205 unc +=2;
4208 name = strchr(unc, '\\');
4209 if (name) {
4210 return name+1;
4213 return unc;
4216 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4217 struct dcerpc_binding_handle *b,
4218 struct policy_handle *handle,
4219 const char *printer_name,
4220 struct dcerpc_binding_handle *winreg_handle,
4221 struct policy_handle *hive_handle)
4223 union spoolss_PrinterInfo info;
4224 const char *keys[] = {
4225 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4226 TOP_LEVEL_PRINT_PRINTERS_KEY
4228 int i;
4229 const char *printername, *sharename;
4231 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4233 torture_assert(tctx,
4234 test_GetPrinter_level(tctx, b, handle, 2, &info),
4235 "failed to get printer info level 2");
4237 printername = strip_unc(info.info2.printername);
4238 sharename = strip_unc(info.info2.sharename);
4240 #define test_sz(wname, iname) \
4241 do {\
4242 DATA_BLOB blob;\
4243 const char *str;\
4244 enum winreg_Type w_type;\
4245 uint32_t w_size;\
4246 uint32_t w_length;\
4247 uint8_t *w_data;\
4248 torture_assert(tctx,\
4249 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4250 &w_type, &w_size, &w_length, &w_data),\
4251 "failed to query winreg");\
4252 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4253 blob = data_blob(w_data, w_size);\
4254 str = reg_val_data_string(tctx, REG_SZ, blob);\
4255 if (w_size == 2 && iname == NULL) {\
4256 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4257 } else {\
4258 torture_assert_str_equal(tctx, str, iname,\
4259 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4261 } while(0);
4263 #define test_dword(wname, iname) \
4264 do {\
4265 uint32_t value;\
4266 enum winreg_Type w_type;\
4267 uint32_t w_size;\
4268 uint32_t w_length;\
4269 uint8_t *w_data;\
4270 torture_assert(tctx,\
4271 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4272 &w_type, &w_size, &w_length, &w_data),\
4273 "failed to query winreg");\
4274 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4275 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4276 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4277 value = IVAL(w_data, 0);\
4278 torture_assert_int_equal(tctx, value, iname,\
4279 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4280 } while(0);
4282 #define test_dm(wname, iname) \
4283 do {\
4284 DATA_BLOB blob;\
4285 struct spoolss_DeviceMode dm;\
4286 enum ndr_err_code ndr_err;\
4287 enum winreg_Type w_type;\
4288 uint32_t w_size;\
4289 uint32_t w_length;\
4290 uint8_t *w_data;\
4291 torture_assert(tctx,\
4292 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4293 &w_type, &w_size, &w_length, &w_data),\
4294 "failed to query winreg");\
4295 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4296 blob = data_blob(w_data, w_size);\
4297 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4298 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4299 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4300 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4301 "dm unequal");\
4302 } while(0);
4304 #define test_sd(wname, iname) \
4305 do {\
4306 DATA_BLOB blob;\
4307 struct security_descriptor sd;\
4308 enum ndr_err_code ndr_err;\
4309 enum winreg_Type w_type;\
4310 uint32_t w_size;\
4311 uint32_t w_length;\
4312 uint8_t *w_data;\
4313 torture_assert(tctx,\
4314 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4315 &w_type, &w_size, &w_length, &w_data),\
4316 "failed to query winreg");\
4317 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4318 blob = data_blob(w_data, w_size);\
4319 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4320 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4321 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4322 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4323 "sd unequal");\
4324 } while(0);
4326 #define test_multi_sz(wname, iname) \
4327 do {\
4328 DATA_BLOB blob;\
4329 const char **array;\
4330 enum winreg_Type w_type;\
4331 uint32_t w_size;\
4332 uint32_t w_length;\
4333 uint8_t *w_data;\
4334 int i;\
4335 torture_assert(tctx,\
4336 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4337 &w_type, &w_size, &w_length, &w_data),\
4338 "failed to query winreg");\
4339 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4340 blob = data_blob(w_data, w_size);\
4341 torture_assert(tctx, \
4342 pull_reg_multi_sz(tctx, &blob, &array),\
4343 "failed to pull multi sz");\
4344 for (i=0; array[i] != NULL; i++) {\
4345 torture_assert_str_equal(tctx, array[i], iname[i],\
4346 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4348 } while(0);
4351 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4352 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4353 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4355 torture_warning(tctx, "failed to check for winreg symlink");
4359 for (i=0; i < ARRAY_SIZE(keys); i++) {
4361 const char *printer_key;
4362 struct policy_handle key_handle;
4364 printer_key = talloc_asprintf(tctx, "%s\\%s",
4365 keys[i], printer_name);
4367 torture_assert(tctx,
4368 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4370 test_sz("Name", printername);
4371 test_sz("Share Name", sharename);
4372 test_sz("Port", info.info2.portname);
4373 test_sz("Printer Driver", info.info2.drivername);
4374 test_sz("Description", info.info2.comment);
4375 test_sz("Location", info.info2.location);
4376 test_sz("Separator File", info.info2.sepfile);
4377 test_sz("Print Processor", info.info2.printprocessor);
4378 test_sz("Datatype", info.info2.datatype);
4379 test_sz("Parameters", info.info2.parameters);
4380 /* winreg: 0, spoolss not */
4381 /* test_dword("Attributes", info.info2.attributes); */
4382 test_dword("Priority", info.info2.priority);
4383 test_dword("Default Priority", info.info2.defaultpriority);
4384 /* winreg: 60, spoolss: 0 */
4385 /* test_dword("StartTime", info.info2.starttime); */
4386 /* test_dword("UntilTime", info.info2.untiltime); */
4387 /* winreg != spoolss */
4388 /* test_dword("Status", info.info2.status); */
4389 test_dm("Default DevMode", info.info2.devmode);
4390 test_sd("Security", info.info2.secdesc);
4392 torture_assert(tctx,
4393 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4396 #undef test_dm
4397 #undef test_sd
4399 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4401 return true;
4404 static bool test_PrintProcessors(struct torture_context *tctx,
4405 struct dcerpc_binding_handle *b,
4406 const char *environment,
4407 struct dcerpc_binding_handle *winreg_handle,
4408 struct policy_handle *hive_handle)
4410 union spoolss_PrintProcessorInfo *info;
4411 uint32_t count;
4412 int i;
4414 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4416 torture_assert(tctx,
4417 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info),
4418 "failed to enum print processors level 1");
4420 for (i=0; i < count; i++) {
4422 const char *processor_key;
4423 struct policy_handle key_handle;
4425 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4426 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4427 environment,
4428 info[i].info1.print_processor_name);
4430 torture_assert(tctx,
4431 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4433 /* nothing to check in there so far */
4435 torture_assert(tctx,
4436 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4439 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4441 return true;
4444 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4445 struct dcerpc_binding_handle *b,
4446 struct policy_handle *handle,
4447 const char *driver_name,
4448 const char *architecture,
4449 uint32_t level,
4450 uint32_t client_major_version,
4451 uint32_t client_minor_version,
4452 union spoolss_DriverInfo *info_p,
4453 WERROR *result);
4455 static const char *strip_path(const char *path)
4457 char *p;
4459 if (path == NULL) {
4460 return NULL;
4463 p = strrchr(path, '\\');
4464 if (p) {
4465 return p+1;
4468 return path;
4471 static const char **strip_paths(const char **path_array)
4473 int i;
4475 if (path_array == NULL) {
4476 return NULL;
4479 for (i=0; path_array[i] != NULL; i++) {
4480 path_array[i] = strip_path(path_array[i]);
4483 return path_array;
4486 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4488 time_t t;
4489 struct tm *tm;
4490 t = nt_time_to_unix(nt);
4491 tm = localtime(&t);
4493 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4494 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4497 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4499 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4500 (unsigned)((v >> 48) & 0xFFFF),
4501 (unsigned)((v >> 32) & 0xFFFF),
4502 (unsigned)((v >> 16) & 0xFFFF),
4503 (unsigned)(v & 0xFFFF));
4506 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4507 struct dcerpc_binding_handle *b,
4508 struct policy_handle *handle,
4509 const char *printer_name,
4510 const char *driver_name,
4511 const char *environment,
4512 struct dcerpc_binding_handle *winreg_handle,
4513 struct policy_handle *hive_handle)
4515 WERROR result;
4516 union spoolss_DriverInfo info;
4517 const char *driver_key;
4518 struct policy_handle key_handle;
4520 const char *driver_path;
4521 const char *data_file;
4522 const char *config_file;
4523 const char *help_file;
4524 const char **dependent_files;
4526 const char *driver_date;
4527 const char *inbox_driver_date;
4529 const char *driver_version;
4530 const char *inbox_driver_version;
4532 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4534 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4535 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4536 environment,
4538 driver_name);
4540 torture_assert(tctx,
4541 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4542 "failed to open driver key");
4544 if (torture_setting_bool(tctx, "samba3", false)) {
4545 goto try_level3;
4548 torture_assert(tctx,
4549 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4550 "failed to get driver info level 8");
4552 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4553 goto try_level6;
4556 driver_path = strip_path(info.info8.driver_path);
4557 data_file = strip_path(info.info8.data_file);
4558 config_file = strip_path(info.info8.config_file);
4559 help_file = strip_path(info.info8.help_file);
4560 dependent_files = strip_paths(info.info8.dependent_files);
4562 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4563 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4565 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4566 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4568 test_sz("Configuration File", config_file);
4569 test_sz("Data File", data_file);
4570 test_sz("Datatype", info.info8.default_datatype);
4571 test_sz("Driver", driver_path);
4572 test_sz("DriverDate", driver_date);
4573 test_sz("DriverVersion", driver_version);
4574 test_sz("HardwareID", info.info8.hardware_id);
4575 test_sz("Help File", help_file);
4576 test_sz("InfPath", info.info8.inf_path);
4577 test_sz("Manufacturer", info.info8.manufacturer_name);
4578 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4579 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4580 test_sz("Monitor", info.info8.monitor_name);
4581 test_sz("OEM URL", info.info8.manufacturer_url);
4582 test_sz("Print Processor", info.info8.print_processor);
4583 test_sz("Provider", info.info8.provider);
4584 test_sz("VendorSetup", info.info8.vendor_setup);
4585 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4586 test_multi_sz("Dependent Files", dependent_files);
4587 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4588 test_multi_sz("Previous Names", info.info8.previous_names);
4589 /* test_dword("Attributes", ?); */
4590 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4591 test_dword("Version", info.info8.version);
4592 /* test_dword("TempDir", ?); */
4594 try_level6:
4596 torture_assert(tctx,
4597 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4598 "failed to get driver info level 6");
4600 driver_path = strip_path(info.info6.driver_path);
4601 data_file = strip_path(info.info6.data_file);
4602 config_file = strip_path(info.info6.config_file);
4603 help_file = strip_path(info.info6.help_file);
4604 dependent_files = strip_paths(info.info6.dependent_files);
4606 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4608 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4610 test_sz("Configuration File", config_file);
4611 test_sz("Data File", data_file);
4612 test_sz("Datatype", info.info6.default_datatype);
4613 test_sz("Driver", driver_path);
4614 test_sz("DriverDate", driver_date);
4615 test_sz("DriverVersion", driver_version);
4616 test_sz("HardwareID", info.info6.hardware_id);
4617 test_sz("Help File", help_file);
4618 test_sz("Manufacturer", info.info6.manufacturer_name);
4619 test_sz("Monitor", info.info6.monitor_name);
4620 test_sz("OEM URL", info.info6.manufacturer_url);
4621 test_sz("Provider", info.info6.provider);
4622 test_multi_sz("Dependent Files", dependent_files);
4623 test_multi_sz("Previous Names", info.info6.previous_names);
4624 /* test_dword("Attributes", ?); */
4625 test_dword("Version", info.info6.version);
4626 /* test_dword("TempDir", ?); */
4628 try_level3:
4630 torture_assert(tctx,
4631 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4632 "failed to get driver info level 3");
4634 driver_path = strip_path(info.info3.driver_path);
4635 data_file = strip_path(info.info3.data_file);
4636 config_file = strip_path(info.info3.config_file);
4637 help_file = strip_path(info.info3.help_file);
4638 dependent_files = strip_paths(info.info3.dependent_files);
4640 test_sz("Configuration File", config_file);
4641 test_sz("Data File", data_file);
4642 test_sz("Datatype", info.info3.default_datatype);
4643 test_sz("Driver", driver_path);
4644 test_sz("Help File", help_file);
4645 test_sz("Monitor", info.info3.monitor_name);
4646 test_multi_sz("Dependent Files", dependent_files);
4647 /* test_dword("Attributes", ?); */
4648 test_dword("Version", info.info3.version);
4649 /* test_dword("TempDir", ?); */
4652 torture_assert(tctx,
4653 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4655 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4657 return true;
4660 #undef test_sz
4661 #undef test_dword
4663 static bool test_SetPrinterData(struct torture_context *tctx,
4664 struct dcerpc_binding_handle *b,
4665 struct policy_handle *handle,
4666 const char *value_name,
4667 enum winreg_Type type,
4668 uint8_t *data,
4669 uint32_t offered)
4671 struct spoolss_SetPrinterData r;
4673 r.in.handle = handle;
4674 r.in.value_name = value_name;
4675 r.in.type = type;
4676 r.in.data = data;
4677 r.in.offered = offered;
4679 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4680 r.in.value_name);
4682 torture_assert_ntstatus_ok(tctx,
4683 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4684 "SetPrinterData failed");
4685 torture_assert_werr_ok(tctx, r.out.result,
4686 "SetPrinterData failed");
4688 return true;
4691 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4692 struct dcerpc_binding_handle *b,
4693 struct policy_handle *handle,
4694 const char *printer_name,
4695 struct dcerpc_binding_handle *winreg_handle,
4696 struct policy_handle *hive_handle)
4698 const char *values[] = {
4699 "spootyfoot",
4700 "spooty\\foot",
4701 #if 0
4702 /* FIXME: not working with s3 atm. */
4703 "spooty,foot",
4704 "spooty,fo,ot",
4705 #endif
4706 "spooty foot",
4707 #if 0
4708 /* FIXME: not working with s3 atm. */
4709 "spooty\\fo,ot",
4710 "spooty,fo\\ot"
4711 #endif
4713 int i;
4715 for (i=0; i < ARRAY_SIZE(values); i++) {
4717 enum winreg_Type type;
4718 DATA_BLOB blob;
4719 uint8_t *data;
4720 uint32_t needed;
4722 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4723 type = REG_SZ;
4725 torture_assert(tctx,
4726 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4727 "SetPrinterData failed");
4729 torture_assert(tctx,
4730 test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4731 "GetPrinterData failed");
4733 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4734 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4735 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4737 if (winreg_handle && hive_handle) {
4739 enum winreg_Type w_type;
4740 uint32_t w_size;
4741 uint32_t w_length;
4742 uint8_t *w_data;
4744 torture_assert(tctx,
4745 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4746 printer_name, "PrinterDriverData", values[i],
4747 &w_type, &w_size, &w_length, &w_data), "");
4749 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4750 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4751 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4752 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4755 torture_assert(tctx,
4756 test_DeletePrinterData(tctx, b, handle, values[i]),
4757 "DeletePrinterData failed");
4760 return true;
4764 static bool test_EnumPrinterKey(struct torture_context *tctx,
4765 struct dcerpc_binding_handle *b,
4766 struct policy_handle *handle,
4767 const char *key_name,
4768 const char ***array);
4770 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4771 struct dcerpc_binding_handle *b,
4772 struct policy_handle *handle,
4773 const char *key_name,
4774 const char *value_name,
4775 enum winreg_Type type,
4776 uint8_t *data,
4777 uint32_t offered)
4779 NTSTATUS status;
4780 struct spoolss_SetPrinterDataEx r;
4782 r.in.handle = handle;
4783 r.in.key_name = key_name;
4784 r.in.value_name = value_name;
4785 r.in.type = type;
4786 r.in.data = data;
4787 r.in.offered = offered;
4789 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4790 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4792 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4794 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4795 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4797 return true;
4800 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4801 struct dcerpc_pipe *p,
4802 struct policy_handle *handle)
4804 struct dcerpc_binding_handle *b = p->binding_handle;
4805 const char *value_name = "dog";
4806 const char *keys[] = {
4807 "torturedataex",
4808 "torture data ex",
4809 #if 0
4810 /* FIXME: not working with s3 atm. */
4811 "torturedataex_with_subkey\\subkey",
4812 "torturedataex_with_subkey\\subkey:0",
4813 "torturedataex_with_subkey\\subkey:1",
4814 "torturedataex_with_subkey\\subkey\\subsubkey",
4815 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4816 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4817 #endif
4818 "torture,data",
4819 #if 0
4820 /* FIXME: not working with s3 atm. */
4822 "torture,data,ex",
4823 "torture,data\\ex",
4824 "torture\\data,ex"
4825 #endif
4827 int i;
4829 for (i=0; i < ARRAY_SIZE(keys); i++) {
4831 char *c;
4832 const char *key;
4833 enum winreg_Type type;
4834 DATA_BLOB blob_in, blob_out;
4835 const char **subkeys;
4836 uint32_t ecount;
4837 struct spoolss_PrinterEnumValues *einfo;
4838 uint32_t needed;
4840 blob_in = data_blob_talloc(tctx, NULL, 42);
4842 generate_random_buffer(blob_in.data, blob_in.length);
4844 torture_assert(tctx,
4845 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
4846 "failed to call SetPrinterDataEx");
4848 torture_assert(tctx,
4849 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
4850 "failed to call GetPrinterDataEx");
4852 blob_out.length = needed;
4853 torture_assert(tctx,
4854 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4855 "failed to call EnumPrinterDataEx");
4857 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
4858 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
4859 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
4861 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4862 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4863 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4864 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
4865 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
4866 if (einfo[0].data_length > 0) {
4867 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
4870 key = talloc_strdup(tctx, keys[i]);
4872 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4873 return false;
4876 c = strchr(key, '\\');
4877 if (c) {
4878 int k;
4880 /* we have subkeys */
4882 *c = 0;
4884 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4885 return false;
4888 for (k=0; subkeys && subkeys[k]; k++) {
4890 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4892 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4893 return false;
4897 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4898 return false;
4901 } else {
4902 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4903 return false;
4908 return true;
4911 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4912 struct dcerpc_pipe *p,
4913 struct policy_handle *handle,
4914 const char *printername,
4915 struct dcerpc_binding_handle *winreg_handle,
4916 struct policy_handle *hive_handle)
4918 struct dcerpc_binding_handle *b = p->binding_handle;
4919 const char *value_name = "dog";
4920 const char *key_name = "torturedataex";
4921 enum winreg_Type types[] = {
4922 REG_SZ,
4923 REG_MULTI_SZ,
4924 REG_DWORD,
4925 REG_BINARY
4927 const char *str = "abcdefghi";
4928 int t, s;
4930 for (t=0; t < ARRAY_SIZE(types); t++) {
4931 for (s=0; s < strlen(str); s++) {
4933 enum winreg_Type type;
4934 const char *string = talloc_strndup(tctx, str, s);
4935 const char *array[2];
4936 DATA_BLOB blob = data_blob_string_const(string);
4937 DATA_BLOB data;
4938 uint8_t *data_out;
4939 uint32_t needed, offered = 0;
4940 uint32_t ecount;
4941 struct spoolss_PrinterEnumValues *einfo;
4943 array[0] = talloc_strdup(tctx, string);
4944 array[1] = NULL;
4946 if (types[t] == REG_DWORD) {
4947 s = 0xffff;
4950 if (torture_setting_bool(tctx, "samba3", false)) {
4951 if ((types[t] == REG_MULTI_SZ) && s == 0) {
4952 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4953 continue;
4957 switch (types[t]) {
4958 case REG_BINARY:
4959 data = blob;
4960 offered = blob.length;
4961 break;
4962 case REG_DWORD:
4963 data = data_blob_talloc(tctx, NULL, 4);
4964 SIVAL(data.data, 0, 0x12345678);
4965 offered = 4;
4966 break;
4967 case REG_SZ:
4968 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
4969 type = REG_SZ;
4970 offered = data.length;
4971 /*strlen_m_term(data.string)*2;*/
4972 break;
4973 case REG_MULTI_SZ:
4974 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
4975 type = REG_MULTI_SZ;
4976 offered = data.length;
4977 break;
4978 default:
4979 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4982 torture_assert(tctx,
4983 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
4984 "failed to call SetPrinterDataEx");
4986 torture_assert(tctx,
4987 test_GetPrinterDataEx(tctx, p, handle, key_name, value_name, &type, &data_out, &needed),
4988 "failed to call GetPrinterDataEx");
4990 torture_assert(tctx,
4991 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
4992 "failed to call EnumPrinterDataEx");
4994 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4995 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4996 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4998 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4999 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5000 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5001 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5002 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5003 if (einfo[0].data_length > 0) {
5004 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5007 if (winreg_handle && hive_handle) {
5008 enum winreg_Type w_type;
5009 uint32_t w_size;
5010 uint32_t w_length;
5011 uint8_t *w_data;
5013 torture_assert(tctx,
5014 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5015 printername, key_name, value_name,
5016 &w_type, &w_size, &w_length, &w_data), "");
5018 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5019 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5020 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5021 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5024 torture_assert(tctx,
5025 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5026 "failed to call DeletePrinterDataEx");
5030 return true;
5033 static bool test_PrinterData_winreg(struct torture_context *tctx,
5034 struct dcerpc_pipe *p,
5035 struct policy_handle *handle,
5036 const char *printer_name)
5038 struct dcerpc_binding_handle *b = p->binding_handle;
5039 struct dcerpc_pipe *p2;
5040 bool ret = true;
5041 struct policy_handle hive_handle;
5042 struct dcerpc_binding_handle *b2;
5044 torture_assert_ntstatus_ok(tctx,
5045 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5046 "could not open winreg pipe");
5047 b2 = p2->binding_handle;
5049 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5051 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5052 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5054 test_winreg_CloseKey(tctx, b2, &hive_handle);
5056 talloc_free(p2);
5058 return ret;
5061 static bool test_Forms_winreg(struct torture_context *tctx,
5062 struct dcerpc_binding_handle *b,
5063 struct policy_handle *handle,
5064 bool print_server,
5065 const char *printer_name)
5067 struct dcerpc_pipe *p2;
5068 bool ret = true;
5069 struct policy_handle hive_handle;
5070 struct dcerpc_binding_handle *b2;
5072 torture_assert_ntstatus_ok(tctx,
5073 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5074 "could not open winreg pipe");
5075 b2 = p2->binding_handle;
5077 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5079 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5081 test_winreg_CloseKey(tctx, b2, &hive_handle);
5083 talloc_free(p2);
5085 return ret;
5088 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5089 struct dcerpc_pipe *p,
5090 struct policy_handle *handle,
5091 const char *printer_name)
5093 struct dcerpc_binding_handle *b = p->binding_handle;
5094 struct dcerpc_pipe *p2;
5095 bool ret = true;
5096 struct policy_handle hive_handle;
5097 struct dcerpc_binding_handle *b2;
5099 torture_assert_ntstatus_ok(tctx,
5100 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5101 "could not open winreg pipe");
5102 b2 = p2->binding_handle;
5104 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5106 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5108 test_winreg_CloseKey(tctx, b2, &hive_handle);
5110 talloc_free(p2);
5112 return ret;
5115 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5116 struct dcerpc_pipe *p,
5117 struct policy_handle *handle,
5118 const char *printer_name,
5119 const char *driver_name,
5120 const char *environment)
5122 struct dcerpc_binding_handle *b = p->binding_handle;
5123 struct dcerpc_pipe *p2;
5124 bool ret = true;
5125 struct policy_handle hive_handle;
5126 struct dcerpc_binding_handle *b2;
5128 torture_assert_ntstatus_ok(tctx,
5129 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5130 "could not open winreg pipe");
5131 b2 = p2->binding_handle;
5133 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5135 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
5137 test_winreg_CloseKey(tctx, b2, &hive_handle);
5139 talloc_free(p2);
5141 return ret;
5144 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5145 struct dcerpc_binding_handle *b,
5146 const char *environment)
5148 struct dcerpc_pipe *p2;
5149 bool ret = true;
5150 struct policy_handle hive_handle;
5151 struct dcerpc_binding_handle *b2;
5153 torture_assert_ntstatus_ok(tctx,
5154 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5155 "could not open winreg pipe");
5156 b2 = p2->binding_handle;
5158 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5160 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5162 test_winreg_CloseKey(tctx, b2, &hive_handle);
5164 talloc_free(p2);
5166 return ret;
5169 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5170 struct dcerpc_pipe *p,
5171 struct policy_handle *handle,
5172 const char *printer_name)
5174 struct spoolss_SetPrinterInfoCtr info_ctr;
5175 struct spoolss_DevmodeContainer devmode_ctr;
5176 struct sec_desc_buf secdesc_ctr;
5177 union spoolss_SetPrinterInfo sinfo;
5178 union spoolss_PrinterInfo info;
5179 struct dcerpc_binding_handle *b = p->binding_handle;
5180 const char *pname;
5182 ZERO_STRUCT(info_ctr);
5183 ZERO_STRUCT(devmode_ctr);
5184 ZERO_STRUCT(secdesc_ctr);
5186 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5188 torture_assert(tctx,
5189 test_GetPrinter_level(tctx, b, handle, 2, &info),
5190 "failed to query Printer level 2");
5192 torture_assert(tctx,
5193 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5194 "failed to convert");
5196 info_ctr.level = 2;
5197 info_ctr.info = sinfo;
5199 #define TEST_SZ(wname, iname) \
5200 do {\
5201 enum winreg_Type type;\
5202 uint8_t *data;\
5203 uint32_t needed;\
5204 DATA_BLOB blob;\
5205 const char *str;\
5206 torture_assert(tctx,\
5207 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5208 "failed to query");\
5209 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5210 blob = data_blob_const(data, needed);\
5211 torture_assert(tctx,\
5212 pull_reg_sz(tctx, &blob, &str),\
5213 "failed to pull REG_SZ");\
5214 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5215 } while(0);
5218 #define TEST_SET_SZ(wname, iname, val) \
5219 do {\
5220 enum winreg_Type type;\
5221 uint8_t *data;\
5222 uint32_t needed;\
5223 DATA_BLOB blob;\
5224 const char *str;\
5225 sinfo.info2->iname = val;\
5226 torture_assert(tctx,\
5227 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5228 "failed to call SetPrinter");\
5229 torture_assert(tctx,\
5230 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5231 "failed to query");\
5232 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5233 blob = data_blob_const(data, needed);\
5234 torture_assert(tctx,\
5235 pull_reg_sz(tctx, &blob, &str),\
5236 "failed to pull REG_SZ");\
5237 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5238 } while(0);
5240 #define TEST_SET_DWORD(wname, iname, val) \
5241 do {\
5242 enum winreg_Type type;\
5243 uint8_t *data;\
5244 uint32_t needed;\
5245 uint32_t value;\
5246 sinfo.info2->iname = val;\
5247 torture_assert(tctx,\
5248 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5249 "failed to call SetPrinter");\
5250 torture_assert(tctx,\
5251 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5252 "failed to query");\
5253 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5254 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5255 value = IVAL(data, 0); \
5256 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5257 } while(0);
5259 TEST_SET_SZ("description", comment, "newval");
5260 TEST_SET_SZ("location", location, "newval");
5261 /* TEST_SET_DWORD("priority", priority, 25); */
5263 torture_assert(tctx,
5264 test_GetPrinter_level(tctx, b, handle, 2, &info),
5265 "failed to query Printer level 2");
5267 TEST_SZ("description", info.info2.comment);
5268 /* TEST_SZ("driverName", info.info2.drivername); */
5269 TEST_SZ("location", info.info2.location);
5271 pname = strrchr(info.info2.printername, '\\');
5272 if (pname == NULL) {
5273 pname = info.info2.printername;
5274 } else {
5275 pname++;
5277 /* TEST_SZ("printerName", pname); */
5278 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5279 /* TEST_SZ("printShareName", info.info2.sharename); */
5281 /* FIXME gd: complete the list */
5283 #undef TEST_SZ
5284 #undef TEST_SET_SZ
5285 #undef TEST_DWORD
5287 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5289 return true;
5292 static bool test_print_processors_winreg(struct torture_context *tctx,
5293 void *private_data)
5295 struct test_spoolss_context *ctx =
5296 talloc_get_type_abort(private_data, struct test_spoolss_context);
5297 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5298 struct dcerpc_binding_handle *b = p->binding_handle;
5300 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5303 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5304 struct dcerpc_binding_handle *b,
5305 struct policy_handle *handle,
5306 uint32_t *change_id)
5308 enum winreg_Type type;
5309 uint8_t *data;
5310 uint32_t needed;
5312 torture_assert(tctx,
5313 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5314 "failed to call GetPrinterData");
5316 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5317 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5319 *change_id = IVAL(data, 0);
5321 return true;
5324 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5325 struct dcerpc_pipe *p,
5326 struct policy_handle *handle,
5327 uint32_t *change_id)
5329 enum winreg_Type type;
5330 uint8_t *data;
5331 uint32_t needed;
5333 torture_assert(tctx,
5334 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5335 "failed to call GetPrinterData");
5337 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5338 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5340 *change_id = IVAL(data, 0);
5342 return true;
5345 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5346 struct dcerpc_binding_handle *b,
5347 struct policy_handle *handle,
5348 uint32_t *change_id)
5350 union spoolss_PrinterInfo info;
5352 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5353 "failed to query Printer level 0");
5355 *change_id = info.info0.change_id;
5357 return true;
5360 static bool test_ChangeID(struct torture_context *tctx,
5361 struct dcerpc_pipe *p,
5362 struct policy_handle *handle)
5364 uint32_t change_id, change_id_ex, change_id_info;
5365 uint32_t change_id2, change_id_ex2, change_id_info2;
5366 union spoolss_PrinterInfo info;
5367 const char *comment;
5368 struct dcerpc_binding_handle *b = p->binding_handle;
5370 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5372 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5373 "failed to query for ChangeID");
5374 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5375 "failed to query for ChangeID");
5376 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5377 "failed to query for ChangeID");
5379 torture_assert_int_equal(tctx, change_id, change_id_ex,
5380 "change_ids should all be equal");
5381 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5382 "change_ids should all be equal");
5385 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5387 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5388 "failed to query for ChangeID");
5389 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5390 "failed to query Printer level 2");
5391 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5392 "failed to query for ChangeID");
5393 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5394 "failed to query for ChangeID");
5395 torture_assert_int_equal(tctx, change_id, change_id_ex,
5396 "change_id should not have changed");
5397 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5398 "change_id should not have changed");
5401 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5403 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5404 "failed to query for ChangeID");
5405 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5406 "failed to query for ChangeID");
5407 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5408 "failed to query for ChangeID");
5409 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5410 "failed to query Printer level 2");
5411 comment = talloc_strdup(tctx, info.info2.comment);
5414 struct spoolss_SetPrinterInfoCtr info_ctr;
5415 struct spoolss_DevmodeContainer devmode_ctr;
5416 struct sec_desc_buf secdesc_ctr;
5417 union spoolss_SetPrinterInfo sinfo;
5419 ZERO_STRUCT(info_ctr);
5420 ZERO_STRUCT(devmode_ctr);
5421 ZERO_STRUCT(secdesc_ctr);
5424 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5425 sinfo.info2->comment = "torture_comment";
5427 info_ctr.level = 2;
5428 info_ctr.info = sinfo;
5430 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5431 "failed to call SetPrinter");
5433 sinfo.info2->comment = comment;
5435 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5436 "failed to call SetPrinter");
5440 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5441 "failed to query for ChangeID");
5442 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5443 "failed to query for ChangeID");
5444 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5445 "failed to query for ChangeID");
5447 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5448 "change_ids should all be equal");
5449 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5450 "change_ids should all be equal");
5452 torture_assert(tctx, (change_id < change_id2),
5453 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5454 change_id2, change_id));
5455 torture_assert(tctx, (change_id_ex < change_id_ex2),
5456 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5457 change_id_ex2, change_id_ex));
5458 torture_assert(tctx, (change_id_info < change_id_info2),
5459 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5460 change_id_info2, change_id_info));
5462 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5464 return true;
5467 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5468 struct dcerpc_pipe *p,
5469 struct policy_handle *handle)
5471 NTSTATUS status;
5472 struct dcerpc_binding *b;
5473 struct dcerpc_pipe *p2;
5474 struct spoolss_ClosePrinter cp;
5476 /* only makes sense on SMB */
5477 if (p->conn->transport.transport != NCACN_NP) {
5478 return true;
5481 torture_comment(tctx, "Testing close on secondary pipe\n");
5483 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5484 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5486 status = dcerpc_secondary_connection(p, &p2, b);
5487 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5489 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5490 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5492 cp.in.handle = handle;
5493 cp.out.handle = handle;
5495 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5496 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5497 "ERROR: Allowed close on secondary connection");
5499 talloc_free(p2);
5501 return true;
5504 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5505 struct dcerpc_binding_handle *b, const char *name)
5507 NTSTATUS status;
5508 struct spoolss_OpenPrinter op;
5509 struct spoolss_OpenPrinterEx opEx;
5510 struct policy_handle handle;
5511 bool ret = true;
5513 op.in.printername = name;
5514 op.in.datatype = NULL;
5515 op.in.devmode_ctr.devmode= NULL;
5516 op.in.access_mask = 0;
5517 op.out.handle = &handle;
5519 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5521 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5522 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5523 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5524 "unexpected result");
5526 if (W_ERROR_IS_OK(op.out.result)) {
5527 ret &=test_ClosePrinter(tctx, b, &handle);
5530 opEx.in.printername = name;
5531 opEx.in.datatype = NULL;
5532 opEx.in.devmode_ctr.devmode = NULL;
5533 opEx.in.access_mask = 0;
5534 opEx.in.level = 1;
5535 opEx.in.userlevel.level1 = NULL;
5536 opEx.out.handle = &handle;
5538 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5540 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5541 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5542 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5543 "unexpected result");
5545 if (W_ERROR_IS_OK(opEx.out.result)) {
5546 ret &=test_ClosePrinter(tctx, b, &handle);
5549 return ret;
5552 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5553 void *private_data)
5555 struct test_spoolss_context *ctx =
5556 talloc_get_type_abort(private_data, struct test_spoolss_context);
5558 const char *badnames[] = {
5559 "__INVALID_PRINTER__",
5560 "\\\\__INVALID_HOST__",
5562 "\\\\\\",
5563 "\\\\\\__INVALID_PRINTER__"
5565 const char *badname;
5566 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5567 const char *server_name = dcerpc_server_name(p);
5568 struct dcerpc_binding_handle *b = p->binding_handle;
5569 int i;
5571 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5572 torture_assert(tctx,
5573 test_OpenPrinter_badname(tctx, b, badnames[i]),
5574 "");
5577 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5578 torture_assert(tctx,
5579 test_OpenPrinter_badname(tctx, b, badname),
5580 "");
5582 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5583 torture_assert(tctx,
5584 test_OpenPrinter_badname(tctx, b, badname),
5585 "");
5587 return true;
5590 static bool test_OpenPrinter(struct torture_context *tctx,
5591 struct dcerpc_pipe *p,
5592 const char *name,
5593 const char *environment)
5595 NTSTATUS status;
5596 struct spoolss_OpenPrinter r;
5597 struct policy_handle handle;
5598 bool ret = true;
5599 struct dcerpc_binding_handle *b = p->binding_handle;
5601 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5602 r.in.datatype = NULL;
5603 r.in.devmode_ctr.devmode= NULL;
5604 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5605 r.out.handle = &handle;
5607 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5609 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5611 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5613 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5615 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5616 ret = false;
5619 if (!torture_setting_bool(tctx, "samba3", false)) {
5620 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5621 ret = false;
5625 if (!test_ClosePrinter(tctx, b, &handle)) {
5626 ret = false;
5629 return ret;
5632 static bool call_OpenPrinterEx(struct torture_context *tctx,
5633 struct dcerpc_pipe *p,
5634 const char *name,
5635 struct spoolss_DeviceMode *devmode,
5636 struct policy_handle *handle)
5638 struct spoolss_OpenPrinterEx r;
5639 struct spoolss_UserLevel1 userlevel1;
5640 NTSTATUS status;
5641 struct dcerpc_binding_handle *b = p->binding_handle;
5643 if (name && name[0]) {
5644 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5645 dcerpc_server_name(p), name);
5646 } else {
5647 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5648 dcerpc_server_name(p));
5651 r.in.datatype = NULL;
5652 r.in.devmode_ctr.devmode= devmode;
5653 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5654 r.in.level = 1;
5655 r.in.userlevel.level1 = &userlevel1;
5656 r.out.handle = handle;
5658 userlevel1.size = 1234;
5659 userlevel1.client = "hello";
5660 userlevel1.user = "spottyfoot!";
5661 userlevel1.build = 1;
5662 userlevel1.major = 2;
5663 userlevel1.minor = 3;
5664 userlevel1.processor = 4;
5666 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5668 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5670 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5672 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5674 return true;
5677 static bool test_printer_rename(struct torture_context *tctx,
5678 void *private_data)
5680 struct torture_printer_context *t =
5681 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5682 struct dcerpc_pipe *p = t->spoolss_pipe;
5684 bool ret = true;
5685 union spoolss_PrinterInfo info;
5686 union spoolss_SetPrinterInfo sinfo;
5687 struct spoolss_SetPrinterInfoCtr info_ctr;
5688 struct spoolss_DevmodeContainer devmode_ctr;
5689 struct sec_desc_buf secdesc_ctr;
5690 const char *printer_name;
5691 const char *printer_name_orig;
5692 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5693 struct policy_handle new_handle;
5694 const char *q;
5695 struct dcerpc_binding_handle *b = p->binding_handle;
5697 ZERO_STRUCT(devmode_ctr);
5698 ZERO_STRUCT(secdesc_ctr);
5700 torture_comment(tctx, "Testing Printer rename operations\n");
5702 torture_assert(tctx,
5703 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5704 "failed to call GetPrinter level 2");
5706 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5708 q = strrchr(info.info2.printername, '\\');
5709 if (q) {
5710 torture_warning(tctx,
5711 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5714 torture_assert(tctx,
5715 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5717 sinfo.info2->printername = printer_name_new;
5719 info_ctr.level = 2;
5720 info_ctr.info = sinfo;
5722 torture_assert(tctx,
5723 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5724 "failed to call SetPrinter level 2");
5726 torture_assert(tctx,
5727 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5728 "failed to call GetPrinter level 2");
5730 printer_name = talloc_strdup(tctx, info.info2.printername);
5732 q = strrchr(info.info2.printername, '\\');
5733 if (q) {
5734 torture_warning(tctx,
5735 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5736 q++;
5737 printer_name = q;
5740 torture_assert_str_equal(tctx, printer_name, printer_name_new,
5741 "new printer name was not set");
5743 /* samba currently cannot fully rename printers */
5744 if (!torture_setting_bool(tctx, "samba3", false)) {
5745 torture_assert(tctx,
5746 test_OpenPrinter_badname(tctx, b, printer_name_orig),
5747 "still can open printer with oldname after rename");
5748 } else {
5749 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5752 torture_assert(tctx,
5753 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5754 "failed to open printer with new name");
5756 torture_assert(tctx,
5757 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5758 "failed to call GetPrinter level 2");
5760 /* FIXME: we openend with servername! */
5761 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5762 dcerpc_server_name(p), printer_name_new);
5764 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5765 "new printer name was not set");
5767 torture_assert(tctx,
5768 test_ClosePrinter(tctx, b, &new_handle),
5769 "failed to close printer");
5771 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5773 return ret;
5777 static bool test_OpenPrinterEx(struct torture_context *tctx,
5778 struct dcerpc_pipe *p,
5779 const char *name,
5780 const char *environment)
5782 struct policy_handle handle;
5783 bool ret = true;
5784 struct dcerpc_binding_handle *b = p->binding_handle;
5786 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5787 return false;
5790 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5791 ret = false;
5794 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5795 ret = false;
5798 if (!test_EnumForms_all(tctx, b, &handle, false)) {
5799 ret = false;
5802 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5803 ret = false;
5806 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5807 ret = false;
5810 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5811 ret = false;
5814 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5815 ret = false;
5818 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5819 ret = false;
5822 if (!test_printer_all_keys(tctx, b, &handle)) {
5823 ret = false;
5826 if (!test_PausePrinter(tctx, b, &handle)) {
5827 ret = false;
5830 if (!test_DoPrintTest(tctx, b, &handle)) {
5831 ret = false;
5834 if (!test_ResumePrinter(tctx, b, &handle)) {
5835 ret = false;
5838 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5839 ret = false;
5842 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5843 ret = false;
5846 if (!torture_setting_bool(tctx, "samba3", false)) {
5847 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5848 ret = false;
5852 if (!test_ClosePrinter(tctx, b, &handle)) {
5853 ret = false;
5856 return ret;
5859 static bool test_EnumPrinters_old(struct torture_context *tctx,
5860 void *private_data)
5862 struct test_spoolss_context *ctx =
5863 talloc_get_type_abort(private_data, struct test_spoolss_context);
5864 struct spoolss_EnumPrinters r;
5865 NTSTATUS status;
5866 uint16_t levels[] = {1, 2, 4, 5};
5867 int i;
5868 bool ret = true;
5869 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5870 struct dcerpc_binding_handle *b = p->binding_handle;
5872 for (i=0;i<ARRAY_SIZE(levels);i++) {
5873 union spoolss_PrinterInfo *info;
5874 int j;
5875 uint32_t needed;
5876 uint32_t count;
5878 r.in.flags = PRINTER_ENUM_LOCAL;
5879 r.in.server = "";
5880 r.in.level = levels[i];
5881 r.in.buffer = NULL;
5882 r.in.offered = 0;
5883 r.out.needed = &needed;
5884 r.out.count = &count;
5885 r.out.info = &info;
5887 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5889 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5890 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5892 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5893 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5894 r.in.buffer = &blob;
5895 r.in.offered = needed;
5896 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5899 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5901 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5903 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
5905 if (!info) {
5906 torture_comment(tctx, "No printers returned\n");
5907 return true;
5910 for (j=0;j<count;j++) {
5911 if (r.in.level == 1) {
5912 char *unc = talloc_strdup(tctx, info[j].info1.name);
5913 char *slash, *name;
5914 name = unc;
5915 if (unc[0] == '\\' && unc[1] == '\\') {
5916 unc +=2;
5918 slash = strchr(unc, '\\');
5919 if (slash) {
5920 slash++;
5921 name = slash;
5923 if (!test_OpenPrinter(tctx, p, name, ctx->environment)) {
5924 ret = false;
5926 if (!test_OpenPrinterEx(tctx, p, name, ctx->environment)) {
5927 ret = false;
5933 return ret;
5936 static bool test_GetPrinterDriver(struct torture_context *tctx,
5937 struct dcerpc_binding_handle *b,
5938 struct policy_handle *handle,
5939 const char *driver_name)
5941 struct spoolss_GetPrinterDriver r;
5942 uint32_t needed;
5944 r.in.handle = handle;
5945 r.in.architecture = "W32X86";
5946 r.in.level = 1;
5947 r.in.buffer = NULL;
5948 r.in.offered = 0;
5949 r.out.needed = &needed;
5951 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5953 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5954 "failed to call GetPrinterDriver");
5955 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5956 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5957 r.in.buffer = &blob;
5958 r.in.offered = needed;
5959 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5960 "failed to call GetPrinterDriver");
5963 torture_assert_werr_ok(tctx, r.out.result,
5964 "failed to call GetPrinterDriver");
5966 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
5968 return true;
5971 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5972 struct dcerpc_binding_handle *b,
5973 struct policy_handle *handle,
5974 const char *driver_name,
5975 const char *architecture,
5976 uint32_t level,
5977 uint32_t client_major_version,
5978 uint32_t client_minor_version,
5979 union spoolss_DriverInfo *info_p,
5980 WERROR *result_p)
5983 struct spoolss_GetPrinterDriver2 r;
5984 uint32_t needed;
5985 uint32_t server_major_version;
5986 uint32_t server_minor_version;
5988 r.in.handle = handle;
5989 r.in.architecture = architecture;
5990 r.in.client_major_version = client_major_version;
5991 r.in.client_minor_version = client_minor_version;
5992 r.in.buffer = NULL;
5993 r.in.offered = 0;
5994 r.in.level = level;
5995 r.out.needed = &needed;
5996 r.out.server_major_version = &server_major_version;
5997 r.out.server_minor_version = &server_minor_version;
5999 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6000 driver_name, r.in.level);
6002 torture_assert_ntstatus_ok(tctx,
6003 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6004 "failed to call GetPrinterDriver2");
6005 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6006 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6007 r.in.buffer = &blob;
6008 r.in.offered = needed;
6009 torture_assert_ntstatus_ok(tctx,
6010 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6011 "failed to call GetPrinterDriver2");
6014 if (result_p) {
6015 *result_p = r.out.result;
6018 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6019 switch (r.in.level) {
6020 case 101:
6021 case 8:
6022 torture_comment(tctx,
6023 "level %d not implemented, not considering as an error\n",
6024 r.in.level);
6025 return true;
6026 default:
6027 break;
6031 torture_assert_werr_ok(tctx, r.out.result,
6032 "failed to call GetPrinterDriver2");
6034 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6036 if (info_p) {
6037 *info_p = *r.out.info;
6040 return true;
6043 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6044 struct dcerpc_binding_handle *b,
6045 struct policy_handle *handle,
6046 const char *driver_name,
6047 const char *architecture)
6049 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6050 int i;
6053 for (i=0;i<ARRAY_SIZE(levels);i++) {
6055 torture_assert(tctx,
6056 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6057 "");
6060 return true;
6063 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6064 void *private_data)
6066 struct test_spoolss_context *ctx =
6067 talloc_get_type_abort(private_data, struct test_spoolss_context);
6068 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6069 int i;
6070 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6071 struct dcerpc_binding_handle *b = p->binding_handle;
6072 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6074 for (i=0;i<ARRAY_SIZE(levels);i++) {
6076 uint32_t count;
6077 union spoolss_DriverInfo *info;
6079 torture_assert(tctx,
6080 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6081 "failed to enumerate drivers");
6083 if (!info) {
6084 torture_comment(tctx, "No printer drivers returned\n");
6085 break;
6089 return true;
6092 static bool test_DeletePrinter(struct torture_context *tctx,
6093 struct dcerpc_binding_handle *b,
6094 struct policy_handle *handle)
6096 struct spoolss_DeletePrinter r;
6098 torture_comment(tctx, "Testing DeletePrinter\n");
6100 r.in.handle = handle;
6102 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6103 "failed to delete printer");
6104 torture_assert_werr_ok(tctx, r.out.result,
6105 "failed to delete printer");
6107 return true;
6110 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6111 struct dcerpc_binding_handle *b,
6112 uint32_t flags,
6113 uint32_t level,
6114 const char *name,
6115 bool *found)
6117 struct spoolss_EnumPrinters e;
6118 uint32_t count;
6119 union spoolss_PrinterInfo *info;
6120 uint32_t needed;
6121 int i;
6123 *found = false;
6125 e.in.flags = flags;
6126 e.in.server = NULL;
6127 e.in.level = level;
6128 e.in.buffer = NULL;
6129 e.in.offered = 0;
6130 e.out.count = &count;
6131 e.out.info = &info;
6132 e.out.needed = &needed;
6134 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6135 "failed to enum printers");
6137 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6138 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6139 e.in.buffer = &blob;
6140 e.in.offered = needed;
6142 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6143 "failed to enum printers");
6146 torture_assert_werr_ok(tctx, e.out.result,
6147 "failed to enum printers");
6149 for (i=0; i < count; i++) {
6151 const char *current = NULL;
6152 const char *q;
6154 switch (level) {
6155 case 1:
6156 current = info[i].info1.name;
6157 break;
6160 if (strequal(current, name)) {
6161 *found = true;
6162 break;
6165 q = strrchr(current, '\\');
6166 if (q) {
6167 if (!e.in.server) {
6168 torture_warning(tctx,
6169 "server returns printername %s incl. servername although we did not set servername", current);
6171 q++;
6172 if (strequal(q, name)) {
6173 *found = true;
6174 break;
6179 return true;
6182 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6183 struct dcerpc_pipe *p,
6184 const char *printername,
6185 bool ex)
6187 WERROR result;
6188 struct spoolss_AddPrinter r;
6189 struct spoolss_AddPrinterEx rex;
6190 struct spoolss_SetPrinterInfoCtr info_ctr;
6191 struct spoolss_SetPrinterInfo1 info1;
6192 struct spoolss_DevmodeContainer devmode_ctr;
6193 struct sec_desc_buf secdesc_ctr;
6194 struct spoolss_UserLevelCtr userlevel_ctr;
6195 struct policy_handle handle;
6196 bool found = false;
6197 struct dcerpc_binding_handle *b = p->binding_handle;
6199 ZERO_STRUCT(devmode_ctr);
6200 ZERO_STRUCT(secdesc_ctr);
6201 ZERO_STRUCT(userlevel_ctr);
6202 ZERO_STRUCT(info1);
6204 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6205 ex ? "Ex":"", printername);
6207 /* try to add printer to wellknown printer list (level 1) */
6209 userlevel_ctr.level = 1;
6211 info_ctr.info.info1 = &info1;
6212 info_ctr.level = 1;
6214 rex.in.server = NULL;
6215 rex.in.info_ctr = &info_ctr;
6216 rex.in.devmode_ctr = &devmode_ctr;
6217 rex.in.secdesc_ctr = &secdesc_ctr;
6218 rex.in.userlevel_ctr = &userlevel_ctr;
6219 rex.out.handle = &handle;
6221 r.in.server = NULL;
6222 r.in.info_ctr = &info_ctr;
6223 r.in.devmode_ctr = &devmode_ctr;
6224 r.in.secdesc_ctr = &secdesc_ctr;
6225 r.out.handle = &handle;
6227 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6228 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6229 "failed to add printer");
6230 result = ex ? rex.out.result : r.out.result;
6231 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6232 "unexpected result code");
6234 info1.name = printername;
6235 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6237 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6238 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6239 "failed to add printer");
6240 result = ex ? rex.out.result : r.out.result;
6241 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6242 "unexpected result code");
6244 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6245 better do a real check to see the printer is really there */
6247 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6248 PRINTER_ENUM_NETWORK, 1,
6249 printername,
6250 &found),
6251 "failed to enum printers");
6253 torture_assert(tctx, found, "failed to find newly added printer");
6255 info1.flags = 0;
6257 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6258 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6259 "failed to add printer");
6260 result = ex ? rex.out.result : r.out.result;
6261 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6262 "unexpected result code");
6264 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6265 better do a real check to see the printer has really been removed
6266 from the well known printer list */
6268 found = false;
6270 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6271 PRINTER_ENUM_NETWORK, 1,
6272 printername,
6273 &found),
6274 "failed to enum printers");
6275 #if 0
6276 torture_assert(tctx, !found, "printer still in well known printer list");
6277 #endif
6278 return true;
6281 static bool test_AddPrinter_normal(struct torture_context *tctx,
6282 struct dcerpc_pipe *p,
6283 struct policy_handle *handle_p,
6284 const char *printername,
6285 const char *drivername,
6286 const char *portname,
6287 struct spoolss_DeviceMode *devmode,
6288 bool ex)
6290 WERROR result;
6291 struct spoolss_AddPrinter r;
6292 struct spoolss_AddPrinterEx rex;
6293 struct spoolss_SetPrinterInfoCtr info_ctr;
6294 struct spoolss_SetPrinterInfo2 info2;
6295 struct spoolss_DevmodeContainer devmode_ctr;
6296 struct sec_desc_buf secdesc_ctr;
6297 struct spoolss_UserLevelCtr userlevel_ctr;
6298 struct policy_handle handle;
6299 bool found = false;
6300 bool existing_printer_deleted = false;
6301 struct dcerpc_binding_handle *b = p->binding_handle;
6303 ZERO_STRUCT(devmode_ctr);
6304 ZERO_STRUCT(secdesc_ctr);
6305 ZERO_STRUCT(userlevel_ctr);
6307 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6308 ex ? "Ex":"", printername);
6310 devmode_ctr.devmode = devmode;
6312 userlevel_ctr.level = 1;
6314 rex.in.server = NULL;
6315 rex.in.info_ctr = &info_ctr;
6316 rex.in.devmode_ctr = &devmode_ctr;
6317 rex.in.secdesc_ctr = &secdesc_ctr;
6318 rex.in.userlevel_ctr = &userlevel_ctr;
6319 rex.out.handle = &handle;
6321 r.in.server = NULL;
6322 r.in.info_ctr = &info_ctr;
6323 r.in.devmode_ctr = &devmode_ctr;
6324 r.in.secdesc_ctr = &secdesc_ctr;
6325 r.out.handle = &handle;
6327 again:
6329 /* try to add printer to printer list (level 2) */
6331 ZERO_STRUCT(info2);
6333 info_ctr.info.info2 = &info2;
6334 info_ctr.level = 2;
6336 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6337 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6338 "failed to add printer");
6339 result = ex ? rex.out.result : r.out.result;
6340 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6341 "unexpected result code");
6343 info2.printername = printername;
6345 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6346 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6347 "failed to add printer");
6348 result = ex ? rex.out.result : r.out.result;
6350 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6351 struct policy_handle printer_handle;
6353 if (existing_printer_deleted) {
6354 torture_fail(tctx, "already deleted printer still existing?");
6357 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6358 "failed to open printer handle");
6360 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6361 "failed to delete printer");
6363 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6364 "failed to close server handle");
6366 existing_printer_deleted = true;
6368 goto again;
6371 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6372 "unexpected result code");
6374 info2.portname = portname;
6376 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6377 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6378 "failed to add printer");
6379 result = ex ? rex.out.result : r.out.result;
6380 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6381 "unexpected result code");
6383 info2.drivername = drivername;
6385 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6386 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6387 "failed to add printer");
6388 result = ex ? rex.out.result : r.out.result;
6390 /* w2k8r2 allows to add printer w/o defining printprocessor */
6392 if (!W_ERROR_IS_OK(result)) {
6393 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6394 "unexpected result code");
6396 info2.printprocessor = "winprint";
6398 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6399 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6400 "failed to add printer");
6401 result = ex ? rex.out.result : r.out.result;
6402 torture_assert_werr_ok(tctx, result,
6403 "failed to add printer");
6406 *handle_p = handle;
6408 /* we are paranoid, really check if the printer is there now */
6410 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6411 PRINTER_ENUM_LOCAL, 1,
6412 printername,
6413 &found),
6414 "failed to enum printers");
6415 torture_assert(tctx, found, "failed to find newly added printer");
6417 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6418 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6419 "failed to add printer");
6420 result = ex ? rex.out.result : r.out.result;
6421 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6422 "unexpected result code");
6424 return true;
6427 static bool test_printer_info(struct torture_context *tctx,
6428 void *private_data)
6430 struct torture_printer_context *t =
6431 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6432 struct dcerpc_pipe *p = t->spoolss_pipe;
6433 struct dcerpc_binding_handle *b = p->binding_handle;
6435 bool ret = true;
6437 if (torture_setting_bool(tctx, "samba3", false)) {
6438 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6441 if (!test_PrinterInfo(tctx, b, &t->handle)) {
6442 ret = false;
6445 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
6446 ret = false;
6449 return ret;
6452 static bool test_EnumPrinterKey(struct torture_context *tctx,
6453 struct dcerpc_binding_handle *b,
6454 struct policy_handle *handle,
6455 const char *key_name,
6456 const char ***array)
6458 struct spoolss_EnumPrinterKey r;
6459 uint32_t needed = 0;
6460 union spoolss_KeyNames key_buffer;
6461 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6462 uint32_t _ndr_size;
6463 int i;
6465 r.in.handle = handle;
6466 r.in.key_name = key_name;
6467 r.out.key_buffer = &key_buffer;
6468 r.out.needed = &needed;
6469 r.out._ndr_size = &_ndr_size;
6471 for (i=0; i < ARRAY_SIZE(offered); i++) {
6473 if (offered[i] < 0 && needed) {
6474 if (needed <= 4) {
6475 continue;
6477 r.in.offered = needed + offered[i];
6478 } else {
6479 r.in.offered = offered[i];
6482 ZERO_STRUCT(key_buffer);
6484 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6486 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6487 "failed to call EnumPrinterKey");
6488 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6490 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6491 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6492 _ndr_size, r.in.offered/2));
6494 r.in.offered = needed;
6495 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6496 "failed to call EnumPrinterKey");
6499 if (offered[i] > 0) {
6500 torture_assert_werr_ok(tctx, r.out.result,
6501 "failed to call EnumPrinterKey");
6504 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6505 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6506 _ndr_size, r.in.offered/2));
6508 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6509 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6511 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6512 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6514 if (key_buffer.string_array) {
6515 uint32_t calc_needed = 0;
6516 int s;
6517 for (s=0; key_buffer.string_array[s]; s++) {
6518 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6520 if (!key_buffer.string_array[0]) {
6521 calc_needed += 2;
6523 calc_needed += 2;
6525 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6526 "EnumPrinterKey unexpected size");
6530 if (array) {
6531 *array = key_buffer.string_array;
6534 return true;
6537 bool test_printer_all_keys(struct torture_context *tctx,
6538 struct dcerpc_binding_handle *b,
6539 struct policy_handle *handle)
6541 const char **key_array = NULL;
6542 int i;
6544 torture_comment(tctx, "Testing Printer Keys\n");
6546 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6547 "failed to call test_EnumPrinterKey");
6549 for (i=0; key_array && key_array[i]; i++) {
6550 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6551 "failed to call test_EnumPrinterKey");
6553 for (i=0; key_array && key_array[i]; i++) {
6554 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6555 "failed to call test_EnumPrinterDataEx");
6558 torture_comment(tctx, "Printer Keys test succeeded\n\n");
6560 return true;
6563 static bool test_csetprinter(struct torture_context *tctx,
6564 void *private_data)
6566 struct torture_printer_context *t =
6567 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6568 struct dcerpc_pipe *p = t->spoolss_pipe;
6570 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
6571 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6572 const char *portname = t->info2.portname;
6574 union spoolss_PrinterInfo info;
6575 struct policy_handle new_handle, new_handle2;
6576 struct dcerpc_binding_handle *b = p->binding_handle;
6578 torture_comment(tctx, "Testing c_setprinter\n");
6580 torture_assert(tctx,
6581 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6582 "failed to get level 0 printer info");
6583 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6584 info.info0.c_setprinter);
6586 /* check if c_setprinter on 1st handle increases after a printer has
6587 * been added */
6589 torture_assert(tctx,
6590 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6591 "failed to add new printer");
6592 torture_assert(tctx,
6593 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6594 "failed to get level 0 printer info");
6595 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6596 info.info0.c_setprinter);
6598 /* check if c_setprinter on new handle increases after a printer has
6599 * been added */
6601 torture_assert(tctx,
6602 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6603 "failed to get level 0 printer info");
6604 torture_comment(tctx, "csetprinter on created handle: %d\n",
6605 info.info0.c_setprinter);
6607 /* open the new printer and check if c_setprinter increases */
6609 torture_assert(tctx,
6610 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6611 "failed to open created printer");
6612 torture_assert(tctx,
6613 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6614 "failed to get level 0 printer info");
6615 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6616 info.info0.c_setprinter);
6618 /* cleanup */
6620 torture_assert(tctx,
6621 test_ClosePrinter(tctx, b, &new_handle2),
6622 "failed to close printer");
6623 torture_assert(tctx,
6624 test_DeletePrinter(tctx, b, &new_handle),
6625 "failed to delete new printer");
6627 return true;
6630 static bool compose_local_driver_directory(struct torture_context *tctx,
6631 const char *environment,
6632 const char *local_dir,
6633 const char **path)
6635 char *p;
6637 p = strrchr(local_dir, '/');
6638 if (!p) {
6639 return NULL;
6641 p++;
6643 if (strequal(environment, "Windows x64")) {
6644 if (!strequal(p, "x64")) {
6645 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6647 } else if (strequal(environment, "Windows NT x86")) {
6648 if (!strequal(p, "i386")) {
6649 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6651 } else {
6652 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6655 return true;
6658 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6659 const char *devicename)
6661 struct spoolss_DeviceMode *r;
6663 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6664 if (r == NULL) {
6665 return NULL;
6668 r->devicename = talloc_strdup(r, devicename);
6669 r->specversion = DMSPEC_NT4_AND_ABOVE;
6670 r->driverversion = 0x0600;
6671 r->size = 0x00dc;
6672 r->__driverextra_length = 0;
6673 r->fields = DEVMODE_FORMNAME |
6674 DEVMODE_TTOPTION |
6675 DEVMODE_PRINTQUALITY |
6676 DEVMODE_DEFAULTSOURCE |
6677 DEVMODE_COPIES |
6678 DEVMODE_SCALE |
6679 DEVMODE_PAPERSIZE |
6680 DEVMODE_ORIENTATION;
6681 r->orientation = DMORIENT_PORTRAIT;
6682 r->papersize = DMPAPER_LETTER;
6683 r->paperlength = 0;
6684 r->paperwidth = 0;
6685 r->scale = 100;
6686 r->copies = 55;
6687 r->defaultsource = DMBIN_FORMSOURCE;
6688 r->printquality = DMRES_HIGH;
6689 r->color = DMRES_MONOCHROME;
6690 r->duplex = DMDUP_SIMPLEX;
6691 r->yresolution = 0;
6692 r->ttoption = DMTT_SUBDEV;
6693 r->collate = DMCOLLATE_FALSE;
6694 r->formname = talloc_strdup(r, "Letter");
6696 return r;
6699 static bool test_architecture_buffer(struct torture_context *tctx,
6700 void *private_data)
6702 struct test_spoolss_context *ctx =
6703 talloc_get_type_abort(private_data, struct test_spoolss_context);
6705 struct spoolss_OpenPrinterEx r;
6706 struct spoolss_UserLevel1 u1;
6707 struct policy_handle handle;
6708 uint32_t architectures[] = {
6709 PROCESSOR_ARCHITECTURE_INTEL,
6710 PROCESSOR_ARCHITECTURE_IA64,
6711 PROCESSOR_ARCHITECTURE_AMD64
6713 uint32_t needed[3];
6714 int i;
6715 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6716 struct dcerpc_binding_handle *b = p->binding_handle;
6718 for (i=0; i < ARRAY_SIZE(architectures); i++) {
6720 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6722 u1.size = 0;
6723 u1.client = NULL;
6724 u1.user = NULL;
6725 u1.build = 0;
6726 u1.major = 3;
6727 u1.minor = 0;
6728 u1.processor = architectures[i];
6730 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6731 r.in.datatype = NULL;
6732 r.in.devmode_ctr.devmode= NULL;
6733 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6734 r.in.level = 1;
6735 r.in.userlevel.level1 = &u1;
6736 r.out.handle = &handle;
6738 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6739 torture_assert_werr_ok(tctx, r.out.result, "");
6742 struct spoolss_EnumPrinters e;
6743 uint32_t count;
6744 union spoolss_PrinterInfo *info;
6746 e.in.flags = PRINTER_ENUM_LOCAL;
6747 e.in.server = NULL;
6748 e.in.level = 2;
6749 e.in.buffer = NULL;
6750 e.in.offered = 0;
6751 e.out.count = &count;
6752 e.out.info = &info;
6753 e.out.needed = &needed[i];
6755 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6756 #if 0
6757 torture_comment(tctx, "needed was %d\n", needed[i]);
6758 #endif
6761 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6764 for (i=1; i < ARRAY_SIZE(architectures); i++) {
6765 if (needed[i-1] != needed[i]) {
6766 torture_fail(tctx,
6767 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6768 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6772 return true;
6775 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
6776 void *private_data)
6778 struct test_spoolss_context *ctx =
6779 talloc_get_type_abort(private_data, struct test_spoolss_context);
6780 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6781 struct dcerpc_binding_handle *b = p->binding_handle;
6783 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
6786 static bool test_PrintServer_Forms(struct torture_context *tctx,
6787 void *private_data)
6789 struct test_spoolss_context *ctx =
6790 talloc_get_type_abort(private_data, struct test_spoolss_context);
6791 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6792 struct dcerpc_binding_handle *b = p->binding_handle;
6794 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
6797 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
6798 void *private_data)
6800 struct test_spoolss_context *ctx =
6801 talloc_get_type_abort(private_data, struct test_spoolss_context);
6802 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6803 struct dcerpc_binding_handle *b = p->binding_handle;
6805 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
6808 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
6810 NTSTATUS status;
6812 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
6814 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
6816 torture_assert(tctx,
6817 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
6818 "failed to open printserver");
6819 torture_assert(tctx,
6820 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
6821 "failed to get environment");
6823 return true;
6826 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
6828 struct test_spoolss_context *t;
6830 *data = t = talloc_zero(tctx, struct test_spoolss_context);
6832 return torture_rpc_spoolss_setup_common(tctx, t);
6835 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
6837 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
6839 return true;
6842 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
6844 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
6845 bool ret;
6847 ret = torture_rpc_spoolss_teardown_common(tctx, t);
6848 talloc_free(t);
6850 return ret;
6853 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
6855 struct dcerpc_pipe *p;
6856 struct dcerpc_binding_handle *b;
6857 const char *server_name_slash;
6858 const char *driver_name;
6859 const char *printer_name;
6860 const char *port_name;
6862 torture_assert_ntstatus_ok(tctx,
6863 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
6864 "Error connecting to server");
6866 p = t->spoolss_pipe;
6867 b = p->binding_handle;
6868 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6870 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
6871 t->driver.info8.driver_name = TORTURE_DRIVER;
6872 t->driver.info8.driver_path = "pscript5.dll";
6873 t->driver.info8.data_file = "cups6.ppd";
6874 t->driver.info8.config_file = "ps5ui.dll";
6875 t->driver.info8.help_file = "pscript.hlp";
6876 t->driver.info8.default_datatype = "RAW";
6877 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
6878 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6879 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6880 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6881 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6882 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6883 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6884 t->driver.info8.dependent_files->string[5] = "cups6.ini";
6885 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6886 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6888 t->driver.local.driver_directory= "/usr/share/cups/drivers";
6890 t->info2.drivername = "Microsoft XPS Document Writer";
6891 t->info2.portname = "LPT1:";
6893 printer_name = t->info2.printername;
6894 port_name = t->info2.portname;
6896 torture_assert(tctx,
6897 fillup_printserver_info(tctx, p, &t->driver),
6898 "failed to fillup printserver info");
6900 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6902 torture_assert(tctx,
6903 compose_local_driver_directory(tctx, t->driver.remote.environment,
6904 t->driver.local.driver_directory,
6905 &t->driver.local.driver_directory),
6906 "failed to compose local driver directory");
6908 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6909 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
6910 t->info2.drivername, t->driver.remote.environment);
6911 t->have_driver = true;
6912 goto try_add;
6915 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6916 t->info2.drivername, t->driver.remote.environment);
6917 torture_comment(tctx, "trying to upload own driver\n");
6919 if (!directory_exist(t->driver.local.driver_directory)) {
6920 torture_warning(tctx, "no local driver is available!");
6921 t->have_driver = false;
6922 goto try_add;
6925 torture_assert(tctx,
6926 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6927 "failed to upload printer driver");
6929 torture_assert(tctx,
6930 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
6931 "failed to add driver");
6933 t->added_driver = true;
6934 t->have_driver = true;
6936 try_add:
6937 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6939 if (t->wellknown) {
6940 torture_assert(tctx,
6941 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
6942 "failed to add wellknown printer");
6943 } else {
6944 torture_assert(tctx,
6945 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
6946 "failed to add printer");
6949 return true;
6952 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
6954 struct torture_printer_context *t;
6956 *data = t = talloc_zero(tctx, struct torture_printer_context);
6958 t->ex = false;
6959 t->wellknown = false;
6960 t->info2.printername = TORTURE_PRINTER;
6961 t->devmode = NULL;
6963 return torture_rpc_spoolss_printer_setup_common(tctx, t);
6966 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
6968 struct torture_printer_context *t;
6970 *data = t = talloc_zero(tctx, struct torture_printer_context);
6972 t->ex = true;
6973 t->wellknown = false;
6974 t->info2.printername = TORTURE_PRINTER_EX;
6975 t->devmode = NULL;
6977 return torture_rpc_spoolss_printer_setup_common(tctx, t);
6980 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
6982 struct torture_printer_context *t;
6984 *data = t = talloc_zero(tctx, struct torture_printer_context);
6986 t->ex = false;
6987 t->wellknown = true;
6988 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
6989 t->devmode = NULL;
6991 if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
6992 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
6995 return torture_rpc_spoolss_printer_setup_common(tctx, t);
6998 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7000 struct torture_printer_context *t;
7002 *data = t = talloc_zero(tctx, struct torture_printer_context);
7004 t->ex = true;
7005 t->wellknown = true;
7006 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7007 t->devmode = NULL;
7009 if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7010 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7013 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7016 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7018 struct torture_printer_context *t;
7020 *data = t = talloc_zero(tctx, struct torture_printer_context);
7022 t->ex = true;
7023 t->wellknown = false;
7024 t->info2.printername = TORTURE_PRINTER_EX;
7025 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7027 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7030 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7032 bool found = false;
7033 struct dcerpc_pipe *p = t->spoolss_pipe;
7034 struct dcerpc_binding_handle *b;
7035 const char *printer_name = t->info2.printername;
7037 if (t->added_driver) {
7038 torture_assert(tctx,
7039 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7040 "failed to remove printer driver");
7043 if (p) {
7044 b = p->binding_handle;
7047 if (!t->wellknown) {
7048 torture_assert(tctx,
7049 test_DeletePrinter(tctx, b, &t->handle),
7050 "failed to delete printer");
7052 torture_assert(tctx,
7053 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7054 printer_name, &found),
7055 "failed to enumerate printers");
7057 torture_assert(tctx, !found, "deleted printer still there");
7060 return true;
7063 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7065 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7066 bool ret;
7068 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7069 talloc_free(t);
7071 return ret;
7074 static bool test_print_test(struct torture_context *tctx,
7075 void *private_data)
7077 struct torture_printer_context *t =
7078 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7079 struct dcerpc_pipe *p = t->spoolss_pipe;
7080 struct dcerpc_binding_handle *b = p->binding_handle;
7082 torture_assert(tctx,
7083 test_PausePrinter(tctx, b, &t->handle),
7084 "failed to pause printer");
7086 torture_assert(tctx,
7087 test_DoPrintTest(tctx, b, &t->handle),
7088 "failed to do print test");
7090 torture_assert(tctx,
7091 test_ResumePrinter(tctx, b, &t->handle),
7092 "failed to resume printer");
7094 return true;
7097 static bool test_print_test_extended(struct torture_context *tctx,
7098 void *private_data)
7100 struct torture_printer_context *t =
7101 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7102 struct dcerpc_pipe *p = t->spoolss_pipe;
7103 struct dcerpc_binding_handle *b = p->binding_handle;
7104 bool ret = true;
7106 torture_assert(tctx,
7107 test_PausePrinter(tctx, b, &t->handle),
7108 "failed to pause printer");
7110 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7111 if (ret == false) {
7112 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7113 if (torture_setting_bool(tctx, "samba3", false)) {
7114 torture_comment(tctx, "non-critical for samba3\n");
7115 ret = true;
7116 tctx->last_result = TORTURE_SKIP;
7120 torture_assert(tctx,
7121 test_ResumePrinter(tctx, b, &t->handle),
7122 "failed to resume printer");
7124 return ret;
7127 static bool test_printer_sd(struct torture_context *tctx,
7128 void *private_data)
7130 struct torture_printer_context *t =
7131 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7132 struct dcerpc_pipe *p = t->spoolss_pipe;
7133 struct dcerpc_binding_handle *b = p->binding_handle;
7135 torture_assert(tctx,
7136 test_PrinterInfo_SD(tctx, b, &t->handle),
7137 "failed to test security descriptors");
7139 return true;
7142 static bool test_printer_dm(struct torture_context *tctx,
7143 void *private_data)
7145 struct torture_printer_context *t =
7146 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7147 struct dcerpc_pipe *p = t->spoolss_pipe;
7149 torture_assert(tctx,
7150 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7151 "failed to test devicemodes");
7153 return true;
7156 static bool test_printer_info_winreg(struct torture_context *tctx,
7157 void *private_data)
7159 struct torture_printer_context *t =
7160 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7161 struct dcerpc_pipe *p = t->spoolss_pipe;
7163 torture_assert(tctx,
7164 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7165 "failed to test printer info winreg");
7167 return true;
7170 static bool test_printer_change_id(struct torture_context *tctx,
7171 void *private_data)
7173 struct torture_printer_context *t =
7174 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7175 struct dcerpc_pipe *p = t->spoolss_pipe;
7177 torture_assert(tctx,
7178 test_ChangeID(tctx, p, &t->handle),
7179 "failed to test change id");
7181 return true;
7184 static bool test_printer_keys(struct torture_context *tctx,
7185 void *private_data)
7187 struct torture_printer_context *t =
7188 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7189 struct dcerpc_pipe *p = t->spoolss_pipe;
7190 struct dcerpc_binding_handle *b = p->binding_handle;
7192 torture_assert(tctx,
7193 test_printer_all_keys(tctx, b, &t->handle),
7194 "failed to test printer keys");
7196 return true;
7199 static bool test_printer_data_consistency(struct torture_context *tctx,
7200 void *private_data)
7202 struct torture_printer_context *t =
7203 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7204 struct dcerpc_pipe *p = t->spoolss_pipe;
7206 torture_assert(tctx,
7207 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7208 "failed to test printer data consistency");
7210 return true;
7213 static bool test_printer_data_keys(struct torture_context *tctx,
7214 void *private_data)
7216 struct torture_printer_context *t =
7217 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7218 struct dcerpc_pipe *p = t->spoolss_pipe;
7220 torture_assert(tctx,
7221 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7222 "failed to test printer data keys");
7224 return true;
7227 static bool test_printer_data_set(struct torture_context *tctx,
7228 void *private_data)
7230 struct torture_printer_context *t =
7231 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7232 struct dcerpc_pipe *p = t->spoolss_pipe;
7234 torture_assert(tctx,
7235 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7236 "failed to test printer data set");
7238 return true;
7241 static bool test_printer_data_winreg(struct torture_context *tctx,
7242 void *private_data)
7244 struct torture_printer_context *t =
7245 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7246 struct dcerpc_pipe *p = t->spoolss_pipe;
7248 torture_assert(tctx,
7249 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7250 "failed to test printer data winreg");
7252 return true;
7255 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7256 void *private_data)
7258 struct torture_printer_context *t =
7259 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7260 struct dcerpc_pipe *p = t->spoolss_pipe;
7262 torture_assert(tctx,
7263 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7264 "failed to test printer data winreg dsspooler");
7266 return true;
7269 static bool test_driver_info_winreg(struct torture_context *tctx,
7270 void *private_data)
7272 struct torture_printer_context *t =
7273 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7274 struct dcerpc_pipe *p = t->spoolss_pipe;
7275 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7277 if (!t->have_driver) {
7278 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7281 torture_assert(tctx,
7282 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
7283 "failed to test driver info winreg");
7285 return true;
7288 void torture_tcase_printer(struct torture_tcase *tcase)
7290 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7291 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7292 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7293 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7294 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7295 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7296 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7297 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7298 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7299 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7300 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7301 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7302 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7303 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7304 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7305 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7308 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7310 struct torture_suite *suite = torture_suite_create(mem_ctx, "PRINTER");
7311 struct torture_tcase *tcase;
7313 tcase = torture_suite_add_tcase(suite, "addprinter");
7315 torture_tcase_set_fixture(tcase,
7316 torture_rpc_spoolss_printer_setup,
7317 torture_rpc_spoolss_printer_teardown);
7319 torture_tcase_printer(tcase);
7321 tcase = torture_suite_add_tcase(suite, "addprinterex");
7323 torture_tcase_set_fixture(tcase,
7324 torture_rpc_spoolss_printerex_setup,
7325 torture_rpc_spoolss_printer_teardown);
7327 torture_tcase_printer(tcase);
7329 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7331 torture_tcase_set_fixture(tcase,
7332 torture_rpc_spoolss_printerwkn_setup,
7333 torture_rpc_spoolss_printer_teardown);
7335 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7337 torture_tcase_set_fixture(tcase,
7338 torture_rpc_spoolss_printerexwkn_setup,
7339 torture_rpc_spoolss_printer_teardown);
7341 #if 0
7342 /* test is not correct */
7343 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7345 torture_tcase_set_fixture(tcase,
7346 torture_rpc_spoolss_printerdm_setup,
7347 torture_rpc_spoolss_printer_teardown);
7349 torture_tcase_printer(tcase);
7350 #endif
7351 return suite;
7354 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7356 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
7357 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
7359 torture_tcase_set_fixture(tcase,
7360 torture_rpc_spoolss_setup,
7361 torture_rpc_spoolss_teardown);
7363 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7364 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7365 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7366 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7367 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7368 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7369 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7370 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7371 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7372 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7373 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7374 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7375 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7376 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7377 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7378 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7379 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7380 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7381 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7383 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7385 return suite;
7388 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7389 struct dcerpc_binding_handle *b,
7390 const char *server,
7391 const char *environment,
7392 const char **dir_p)
7394 struct spoolss_GetPrinterDriverDirectory r;
7395 uint32_t needed;
7397 r.in.server = server;
7398 r.in.environment = environment;
7399 r.in.level = 1;
7400 r.in.buffer = NULL;
7401 r.in.offered = 0;
7402 r.out.needed = &needed;
7404 torture_assert_ntstatus_ok(tctx,
7405 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7406 "failed to query driver directory");
7408 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7409 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7410 r.in.buffer = &blob;
7411 r.in.offered = needed;
7413 torture_assert_ntstatus_ok(tctx,
7414 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7415 "failed to query driver directory");
7418 torture_assert_werr_ok(tctx, r.out.result,
7419 "failed to query driver directory");
7421 if (dir_p) {
7422 *dir_p = r.out.info->info1.directory_name;
7425 return true;
7428 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7430 if (info_ctr == NULL) {
7431 return NULL;
7434 switch (info_ctr->level) {
7435 case 1:
7436 return info_ctr->info.info1->driver_name;
7437 case 2:
7438 return info_ctr->info.info2->driver_name;
7439 case 3:
7440 return info_ctr->info.info3->driver_name;
7441 case 4:
7442 return info_ctr->info.info4->driver_name;
7443 case 6:
7444 return info_ctr->info.info6->driver_name;
7445 case 8:
7446 return info_ctr->info.info8->driver_name;
7447 default:
7448 return NULL;
7452 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7454 if (info_ctr == NULL) {
7455 return NULL;
7458 switch (info_ctr->level) {
7459 case 2:
7460 return info_ctr->info.info2->architecture;
7461 case 3:
7462 return info_ctr->info.info3->architecture;
7463 case 4:
7464 return info_ctr->info.info4->architecture;
7465 case 6:
7466 return info_ctr->info.info6->architecture;
7467 case 8:
7468 return info_ctr->info.info8->architecture;
7469 default:
7470 return NULL;
7475 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7476 struct dcerpc_binding_handle *b,
7477 const char *servername,
7478 struct spoolss_AddDriverInfoCtr *info_ctr,
7479 WERROR expected_result)
7481 struct spoolss_AddPrinterDriver r;
7482 const char *drivername = get_driver_from_info(info_ctr);
7483 const char *environment = get_environment_from_info(info_ctr);
7485 r.in.servername = servername;
7486 r.in.info_ctr = info_ctr;
7488 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
7489 drivername, info_ctr->level, environment);
7491 torture_assert_ntstatus_ok(tctx,
7492 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
7493 "spoolss_AddPrinterDriver failed");
7494 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7495 "spoolss_AddPrinterDriver failed with unexpected result");
7497 return true;
7501 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
7502 struct dcerpc_binding_handle *b,
7503 const char *servername,
7504 struct spoolss_AddDriverInfoCtr *info_ctr,
7505 uint32_t flags,
7506 WERROR expected_result)
7508 struct spoolss_AddPrinterDriverEx r;
7509 const char *drivername = get_driver_from_info(info_ctr);
7510 const char *environment = get_environment_from_info(info_ctr);
7512 r.in.servername = servername;
7513 r.in.info_ctr = info_ctr;
7514 r.in.flags = flags;
7516 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
7517 drivername, info_ctr->level, environment);
7519 torture_assert_ntstatus_ok(tctx,
7520 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7521 "AddPrinterDriverEx failed");
7522 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7523 "AddPrinterDriverEx failed with unexpected result");
7525 return true;
7528 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7529 struct dcerpc_binding_handle *b,
7530 const char *server_name,
7531 struct spoolss_AddDriverInfo8 *r,
7532 uint32_t flags,
7533 bool ex)
7535 struct spoolss_AddDriverInfoCtr info_ctr;
7536 struct spoolss_AddDriverInfo1 info1;
7538 ZERO_STRUCT(info1);
7540 info_ctr.level = 1;
7541 info_ctr.info.info1 = &info1;
7543 if (ex) {
7544 torture_assert(tctx,
7545 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7546 "failed to test AddPrinterDriverEx level 1");
7547 } else {
7548 torture_assert(tctx,
7549 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7550 "failed to test AddPrinterDriver level 1");
7553 info1.driver_name = r->driver_name;
7555 if (ex) {
7556 torture_assert(tctx,
7557 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7558 "failed to test AddPrinterDriverEx level 1");
7559 } else {
7560 torture_assert(tctx,
7561 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7562 "failed to test AddPrinterDriver level 1");
7565 return true;
7568 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7569 struct dcerpc_binding_handle *b,
7570 const char *server_name,
7571 struct spoolss_AddDriverInfo8 *r,
7572 uint32_t flags,
7573 bool ex)
7575 struct spoolss_AddDriverInfoCtr info_ctr;
7576 struct spoolss_AddDriverInfo2 info2;
7578 ZERO_STRUCT(info2);
7580 info_ctr.level = 2;
7581 info_ctr.info.info2 = &info2;
7583 if (ex) {
7584 torture_assert(tctx,
7585 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7586 "failed to test AddPrinterDriverEx level 2");
7587 } else {
7588 torture_assert(tctx,
7589 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7590 "failed to test AddPrinterDriver level 2");
7593 info2.driver_name = r->driver_name;
7595 if (ex) {
7596 torture_assert(tctx,
7597 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7598 "failed to test AddPrinterDriverEx level 2");
7599 } else {
7600 torture_assert(tctx,
7601 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7602 "failed to test AddPrinterDriver level 2");
7605 info2.version = r->version;
7607 if (ex) {
7608 torture_assert(tctx,
7609 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7610 "failed to test AddPrinterDriverEx level 2");
7611 } else {
7612 torture_assert(tctx,
7613 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7614 "failed to test AddPrinterDriver level 2");
7617 info2.architecture = r->architecture;
7619 if (ex) {
7620 torture_assert(tctx,
7621 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7622 "failed to test AddPrinterDriverEx level 2");
7623 } else {
7624 torture_assert(tctx,
7625 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7626 "failed to test AddPrinterDriver level 2");
7629 info2.driver_path = r->driver_path;
7631 if (ex) {
7632 torture_assert(tctx,
7633 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7634 "failed to test AddPrinterDriverEx level 2");
7635 } else {
7636 torture_assert(tctx,
7637 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7638 "failed to test AddPrinterDriver level 2");
7641 info2.data_file = r->data_file;
7643 if (ex) {
7644 torture_assert(tctx,
7645 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7646 "failed to test AddPrinterDriverEx level 2");
7647 } else {
7648 torture_assert(tctx,
7649 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7650 "failed to test AddPrinterDriver level 2");
7653 info2.config_file = r->config_file;
7655 if (ex) {
7656 torture_assert(tctx,
7657 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7658 "failed to test AddPrinterDriverEx");
7661 if (ex) {
7662 torture_assert(tctx,
7663 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7664 "failed to test AddPrinterDriverEx level 2");
7665 } else {
7666 torture_assert(tctx,
7667 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7668 "failed to test AddPrinterDriver level 2");
7671 torture_assert(tctx,
7672 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7673 "failed to find added printer driver");
7675 return true;
7678 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7679 struct dcerpc_binding_handle *b,
7680 const char *server_name,
7681 struct spoolss_AddDriverInfo8 *r,
7682 uint32_t flags,
7683 bool ex)
7685 struct spoolss_AddDriverInfoCtr info_ctr;
7686 struct spoolss_AddDriverInfo3 info3;
7688 info3.driver_name = r->driver_name;
7689 info3.version = r->version;
7690 info3.architecture = r->architecture;
7691 info3.driver_path = r->driver_path;
7692 info3.data_file = r->data_file;
7693 info3.config_file = r->config_file;
7694 info3.help_file = r->help_file;
7695 info3.monitor_name = r->monitor_name;
7696 info3.default_datatype = r->default_datatype;
7697 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7698 info3.dependent_files = r->dependent_files;
7700 info_ctr.level = 3;
7701 info_ctr.info.info3 = &info3;
7703 if (ex) {
7704 torture_assert(tctx,
7705 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7706 "failed to test AddPrinterDriverEx level 3");
7707 } else {
7708 torture_assert(tctx,
7709 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7710 "failed to test AddPrinterDriver level 3");
7713 torture_assert(tctx,
7714 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7715 "failed to find added printer driver");
7717 return true;
7720 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7721 struct dcerpc_binding_handle *b,
7722 const char *server_name,
7723 struct spoolss_AddDriverInfo8 *r,
7724 uint32_t flags,
7725 bool ex)
7727 struct spoolss_AddDriverInfoCtr info_ctr;
7728 struct spoolss_AddDriverInfo4 info4;
7730 info4.version = r->version;
7731 info4.driver_name = r->driver_name;
7732 info4.architecture = r->architecture;
7733 info4.driver_path = r->driver_path;
7734 info4.data_file = r->data_file;
7735 info4.config_file = r->config_file;
7736 info4.help_file = r->help_file;
7737 info4.monitor_name = r->monitor_name;
7738 info4.default_datatype = r->default_datatype;
7739 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7740 info4.dependent_files = r->dependent_files;
7741 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7742 info4.previous_names = r->previous_names;
7744 info_ctr.level = 4;
7745 info_ctr.info.info4 = &info4;
7747 if (ex) {
7748 torture_assert(tctx,
7749 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7750 "failed to test AddPrinterDriverEx level 4");
7751 } else {
7752 torture_assert(tctx,
7753 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7754 "failed to test AddPrinterDriver level 4");
7757 torture_assert(tctx,
7758 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7759 "failed to find added printer driver");
7761 return true;
7764 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7765 struct dcerpc_binding_handle *b,
7766 const char *server_name,
7767 struct spoolss_AddDriverInfo8 *r,
7768 uint32_t flags,
7769 bool ex)
7771 struct spoolss_AddDriverInfoCtr info_ctr;
7772 struct spoolss_AddDriverInfo6 info6;
7774 info6.version = r->version;
7775 info6.driver_name = r->driver_name;
7776 info6.architecture = r->architecture;
7777 info6.driver_path = r->driver_path;
7778 info6.data_file = r->data_file;
7779 info6.config_file = r->config_file;
7780 info6.help_file = r->help_file;
7781 info6.monitor_name = r->monitor_name;
7782 info6.default_datatype = r->default_datatype;
7783 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7784 info6.dependent_files = r->dependent_files;
7785 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7786 info6.previous_names = r->previous_names;
7787 info6.driver_date = r->driver_date;
7788 info6.driver_version = r->driver_version;
7789 info6.manufacturer_name = r->manufacturer_name;
7790 info6.manufacturer_url = r->manufacturer_url;
7791 info6.hardware_id = r->hardware_id;
7792 info6.provider = r->provider;
7794 info_ctr.level = 6;
7795 info_ctr.info.info6 = &info6;
7797 if (ex) {
7798 torture_assert(tctx,
7799 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7800 "failed to test AddPrinterDriverEx level 6");
7801 } else {
7802 torture_assert(tctx,
7803 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7804 "failed to test AddPrinterDriver level 6");
7807 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7809 if (!ex) {
7810 return true;
7813 torture_assert(tctx,
7814 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7815 "failed to find added printer driver");
7817 return true;
7820 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7821 struct dcerpc_binding_handle *b,
7822 const char *server_name,
7823 struct spoolss_AddDriverInfo8 *r,
7824 uint32_t flags,
7825 bool ex)
7827 struct spoolss_AddDriverInfoCtr info_ctr;
7829 info_ctr.level = 8;
7830 info_ctr.info.info8 = r;
7832 if (ex) {
7833 torture_assert(tctx,
7834 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7835 "failed to test AddPrinterDriverEx level 8");
7836 } else {
7837 torture_assert(tctx,
7838 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7839 "failed to test AddPrinterDriver level 8");
7842 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7844 if (!ex) {
7845 return true;
7848 torture_assert(tctx,
7849 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7850 "failed to find added printer driver");
7852 return true;
7855 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7856 struct dcerpc_binding_handle *b,
7857 const char *server,
7858 const char *driver,
7859 const char *environment,
7860 WERROR expected_result)
7862 struct spoolss_DeletePrinterDriver r;
7864 r.in.server = server;
7865 r.in.architecture = environment;
7866 r.in.driver = driver;
7868 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7870 torture_assert_ntstatus_ok(tctx,
7871 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7872 "DeletePrinterDriver failed");
7873 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7874 "DeletePrinterDriver failed with unexpected result");
7876 return true;
7879 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7880 struct dcerpc_binding_handle *b,
7881 const char *server,
7882 const char *driver,
7883 const char *environment,
7884 uint32_t delete_flags,
7885 uint32_t version,
7886 WERROR expected_result)
7888 struct spoolss_DeletePrinterDriverEx r;
7890 r.in.server = server;
7891 r.in.architecture = environment;
7892 r.in.driver = driver;
7893 r.in.delete_flags = delete_flags;
7894 r.in.version = version;
7896 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7898 torture_assert_ntstatus_ok(tctx,
7899 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7900 "DeletePrinterDriverEx failed");
7901 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7902 "DeletePrinterDriverEx failed with unexpected result");
7904 return true;
7907 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7908 struct dcerpc_binding_handle *b,
7909 const char *server_name,
7910 const char *driver,
7911 const char *environment)
7913 torture_assert(tctx,
7914 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7915 "failed to delete driver");
7917 torture_assert(tctx,
7918 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
7919 "failed to delete driver");
7921 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7922 torture_fail(tctx, "deleted driver still enumerated");
7925 torture_assert(tctx,
7926 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
7927 "2nd delete failed");
7929 return true;
7932 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7933 struct dcerpc_binding_handle *b,
7934 const char *server_name,
7935 const char *driver,
7936 const char *environment,
7937 uint32_t delete_flags,
7938 uint32_t version)
7940 torture_assert(tctx,
7941 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7942 "failed to delete driver");
7944 torture_assert(tctx,
7945 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7946 "failed to delete driver");
7948 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7949 torture_fail(tctx, "deleted driver still enumerated");
7952 torture_assert(tctx,
7953 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7954 "2nd delete failed");
7956 return true;
7959 static bool test_PrinterDriver_args(struct torture_context *tctx,
7960 struct dcerpc_binding_handle *b,
7961 const char *server_name,
7962 uint32_t level,
7963 struct spoolss_AddDriverInfo8 *r,
7964 uint32_t add_flags,
7965 uint32_t delete_flags,
7966 uint32_t delete_version,
7967 bool ex)
7969 bool ret = true;
7971 switch (level) {
7972 case 1:
7973 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7974 break;
7975 case 2:
7976 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7977 break;
7978 case 3:
7979 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7980 break;
7981 case 4:
7982 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7983 break;
7984 case 6:
7985 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7986 break;
7987 case 8:
7988 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7989 break;
7990 default:
7991 return false;
7994 if (ret == false) {
7995 return ret;
7998 if (level == 1) {
7999 return ret;
8002 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8004 if (!ex && (level == 6 || level == 8)) {
8005 return ret;
8008 if (ex) {
8009 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8010 } else {
8011 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8015 static bool fillup_printserver_info(struct torture_context *tctx,
8016 struct dcerpc_pipe *p,
8017 struct torture_driver_context *d)
8019 struct policy_handle server_handle;
8020 struct dcerpc_binding_handle *b = p->binding_handle;
8021 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8023 torture_assert(tctx,
8024 test_OpenPrinter_server(tctx, p, &server_handle),
8025 "failed to open printserver");
8026 torture_assert(tctx,
8027 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8028 "failed to get environment");
8029 torture_assert(tctx,
8030 test_ClosePrinter(tctx, b, &server_handle),
8031 "failed to close printserver");
8033 torture_assert(tctx,
8034 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8035 d->local.environment ? d->local.environment : d->remote.environment,
8036 &d->remote.driver_directory),
8037 "failed to get driver directory");
8039 return true;
8042 static const char *driver_directory_dir(const char *driver_directory)
8044 char *p;
8046 p = strrchr(driver_directory, '\\');
8047 if (p) {
8048 return p+1;
8051 return NULL;
8054 static const char *driver_directory_share(struct torture_context *tctx,
8055 const char *driver_directory)
8057 const char *p;
8058 char *tok;
8060 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8061 driver_directory += 2;
8064 p = talloc_strdup(tctx, driver_directory);
8066 torture_assert(tctx,
8067 next_token_talloc(tctx, &p, &tok, "\\"),
8068 "cannot explode uri");
8069 torture_assert(tctx,
8070 next_token_talloc(tctx, &p, &tok, "\\"),
8071 "cannot explode uri");
8073 return tok;
8076 static bool upload_printer_driver_file(struct torture_context *tctx,
8077 struct smbcli_state *cli,
8078 struct torture_driver_context *d,
8079 const char *file_name)
8081 XFILE *f;
8082 int fnum;
8083 uint8_t *buf;
8084 int maxwrite = 64512;
8085 off_t nread = 0;
8086 size_t start = 0;
8087 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8088 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8089 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8091 if (!file_name) {
8092 return true;
8095 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8097 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8098 if (fnum == -1) {
8099 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8102 f = x_fopen(local_name, O_RDONLY, 0);
8103 if (f == NULL) {
8104 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8107 buf = talloc_array(tctx, uint8_t, maxwrite);
8108 if (!buf) {
8109 return false;
8112 while (!x_feof(f)) {
8113 int n = maxwrite;
8114 int ret;
8116 if ((n = x_fread(buf, 1, n, f)) < 1) {
8117 if((n == 0) && x_feof(f))
8118 break; /* Empty local file. */
8120 torture_warning(tctx,
8121 "failed to read file: %s\n", strerror(errno));
8122 break;
8125 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8127 if (n != ret) {
8128 torture_warning(tctx,
8129 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8130 break;
8133 nread += n;
8136 x_fclose(f);
8138 torture_assert_ntstatus_ok(tctx,
8139 smbcli_close(cli->tree, fnum),
8140 "failed to close file");
8142 return true;
8145 static bool connect_printer_driver_share(struct torture_context *tctx,
8146 const char *server_name,
8147 const char *share_name,
8148 struct smbcli_state **cli)
8150 struct smbcli_options smb_options;
8151 struct smbcli_session_options smb_session_options;
8153 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8154 share_name, server_name);
8156 lp_smbcli_options(tctx->lp_ctx, &smb_options);
8157 lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8159 torture_assert_ntstatus_ok(tctx,
8160 smbcli_full_connection(tctx, cli, server_name,
8161 lp_smb_ports(tctx->lp_ctx),
8162 share_name, NULL,
8163 lp_socket_options(tctx->lp_ctx),
8164 cmdline_credentials,
8165 lp_resolve_context(tctx->lp_ctx),
8166 tctx->ev,
8167 &smb_options,
8168 &smb_session_options,
8169 lp_gensec_settings(tctx, tctx->lp_ctx)),
8170 "failed to open driver share");
8172 return true;
8175 static bool upload_printer_driver(struct torture_context *tctx,
8176 const char *server_name,
8177 struct torture_driver_context *d)
8179 struct smbcli_state *cli;
8180 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8181 int i;
8183 torture_assert(tctx,
8184 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8185 "failed to connect to driver share");
8187 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8188 server_name, share_name);
8190 torture_assert(tctx,
8191 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8192 "failed to upload driver_path");
8193 torture_assert(tctx,
8194 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8195 "failed to upload data_file");
8196 torture_assert(tctx,
8197 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8198 "failed to upload config_file");
8199 torture_assert(tctx,
8200 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8201 "failed to upload help_file");
8202 if (d->info8.dependent_files) {
8203 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8204 torture_assert(tctx,
8205 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8206 "failed to upload dependent_files");
8210 talloc_free(cli);
8212 return true;
8215 static bool remove_printer_driver_file(struct torture_context *tctx,
8216 struct smbcli_state *cli,
8217 struct torture_driver_context *d,
8218 const char *file_name)
8220 const char *remote_name;
8221 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8223 if (!file_name) {
8224 return true;
8227 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8229 torture_comment(tctx, "Removing %s\n", remote_name);
8231 torture_assert_ntstatus_ok(tctx,
8232 smbcli_unlink(cli->tree, remote_name),
8233 "failed to unlink");
8235 return true;
8238 static bool remove_printer_driver(struct torture_context *tctx,
8239 const char *server_name,
8240 struct torture_driver_context *d)
8242 struct smbcli_state *cli;
8243 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8244 int i;
8246 torture_assert(tctx,
8247 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8248 "failed to connect to driver share");
8250 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8251 server_name, share_name);
8253 torture_assert(tctx,
8254 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8255 "failed to remove driver_path");
8256 torture_assert(tctx,
8257 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8258 "failed to remove data_file");
8259 torture_assert(tctx,
8260 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8261 "failed to remove config_file");
8262 torture_assert(tctx,
8263 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8264 "failed to remove help_file");
8265 if (d->info8.dependent_files) {
8266 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8267 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8268 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8269 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8270 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8271 continue;
8273 torture_assert(tctx,
8274 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8275 "failed to remove dependent_files");
8279 talloc_free(cli);
8281 return true;
8285 static bool test_add_driver_arg(struct torture_context *tctx,
8286 struct dcerpc_pipe *p,
8287 struct torture_driver_context *d)
8289 bool ret = true;
8290 struct dcerpc_binding_handle *b = p->binding_handle;
8291 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8292 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8293 int i;
8294 struct spoolss_AddDriverInfo8 info8;
8295 uint32_t add_flags = APD_COPY_NEW_FILES;
8296 uint32_t delete_flags = 0;
8298 ZERO_STRUCT(info8);
8300 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8301 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8303 torture_assert(tctx,
8304 fillup_printserver_info(tctx, p, d),
8305 "failed to fillup printserver info");
8307 if (!directory_exist(d->local.driver_directory)) {
8308 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8311 torture_assert(tctx,
8312 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8313 "failed to upload printer driver");
8315 info8.version = d->info8.version;
8316 info8.driver_name = d->info8.driver_name;
8317 info8.architecture = d->local.environment;
8318 info8.driver_path = d->info8.driver_path;
8319 info8.data_file = d->info8.data_file;
8320 info8.config_file = d->info8.config_file;
8322 for (i=0; i < ARRAY_SIZE(levels); i++) {
8324 if (torture_setting_bool(tctx, "samba3", false)) {
8325 switch (levels[i]) {
8326 case 2:
8327 case 4:
8328 case 8:
8329 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8330 continue;
8331 default:
8332 break;
8336 torture_comment(tctx,
8337 "Testing PrinterDriver%s '%s' add & delete level %d\n",
8338 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8340 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8343 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8344 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8345 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8347 for (i=0; i < ARRAY_SIZE(levels); i++) {
8349 if (torture_setting_bool(tctx, "samba3", false)) {
8350 switch (levels[i]) {
8351 case 2:
8352 case 4:
8353 case 8:
8354 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8355 continue;
8356 default:
8357 break;
8362 torture_comment(tctx,
8363 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8364 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8366 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8369 torture_assert(tctx,
8370 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8371 "failed to remove printer driver");
8373 torture_comment(tctx, "\n");
8375 return ret;
8378 static bool test_add_driver_ex_64(struct torture_context *tctx,
8379 struct dcerpc_pipe *p,
8380 void *private_data)
8382 struct torture_driver_context *d =
8383 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8385 d->local.environment = talloc_strdup(d, "Windows x64");
8386 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8387 d->info8.driver_name = TORTURE_DRIVER_EX;
8388 d->ex = true;
8390 return test_add_driver_arg(tctx, p, d);
8393 static bool test_add_driver_ex_32(struct torture_context *tctx,
8394 struct dcerpc_pipe *p,
8395 void *private_data)
8397 struct torture_driver_context *d =
8398 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8400 d->local.environment = talloc_strdup(d, "Windows NT x86");
8401 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8402 d->info8.driver_name = TORTURE_DRIVER_EX;
8403 d->ex = true;
8405 return test_add_driver_arg(tctx, p, d);
8408 static bool test_add_driver_64(struct torture_context *tctx,
8409 struct dcerpc_pipe *p,
8410 void *private_data)
8412 struct torture_driver_context *d =
8413 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8415 d->local.environment = talloc_strdup(d, "Windows x64");
8416 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8417 d->info8.driver_name = TORTURE_DRIVER;
8418 d->ex = false;
8420 return test_add_driver_arg(tctx, p, d);
8423 static bool test_add_driver_32(struct torture_context *tctx,
8424 struct dcerpc_pipe *p,
8425 void *private_data)
8427 struct torture_driver_context *d =
8428 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8430 d->local.environment = talloc_strdup(d, "Windows NT x86");
8431 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8432 d->info8.driver_name = TORTURE_DRIVER;
8433 d->ex = false;
8435 return test_add_driver_arg(tctx, p, d);
8438 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
8440 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
8442 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
8443 "driver", &ndr_table_spoolss);
8444 struct torture_driver_context *t;
8446 t = talloc_zero(mem_ctx, struct torture_driver_context);
8448 t->info8.version = SPOOLSS_DRIVER_VERSION_200X;
8449 t->info8.driver_name = NULL;
8450 t->info8.architecture = NULL;
8451 t->info8.driver_path = talloc_strdup(t, "pscript5.dll");
8452 t->info8.data_file = talloc_strdup(t, "cups6.ppd");
8453 t->info8.config_file = talloc_strdup(t, "cupsui6.dll");
8455 torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
8456 torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
8458 torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
8459 torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
8461 return suite;