s4-smbtorture: convert RPC-SPOOLSS into a torture suite.
[Samba/ekacnet.git] / source4 / torture / rpc / spoolss.c
blob6d046907dfdb4b64cc22f0986e47e38a20b99b45
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 spoolss_SetPrinterInfo2 info2;
100 struct torture_driver_context driver;
101 bool ex;
102 bool wellknown;
103 bool added_driver;
104 bool have_driver;
105 struct spoolss_DeviceMode *devmode;
108 static bool upload_printer_driver(struct torture_context *tctx,
109 const char *server_name,
110 struct torture_driver_context *d);
111 static bool remove_printer_driver(struct torture_context *tctx,
112 const char *server_name,
113 struct torture_driver_context *d);
114 static bool fillup_printserver_info(struct torture_context *tctx,
115 struct dcerpc_pipe *p,
116 struct torture_driver_context *d);
117 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
118 struct dcerpc_binding_handle *b,
119 const char *server_name,
120 struct spoolss_AddDriverInfo8 *r,
121 uint32_t flags,
122 bool ex);
124 #define COMPARE_STRING(tctx, c,r,e) \
125 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
127 /* not every compiler supports __typeof__() */
128 #if (__GNUC__ >= 3)
129 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
130 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
131 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
133 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
134 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
136 } while(0)
137 #else
138 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
139 #endif
141 #define COMPARE_UINT32(tctx, c, r, e) do {\
142 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
143 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
144 } while(0)
146 #define COMPARE_UINT64(tctx, c, r, e) do {\
147 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
148 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
149 } while(0)
152 #define COMPARE_NTTIME(tctx, c, r, e) do {\
153 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
154 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
155 } while(0)
157 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
158 int __i; \
159 if (!c.e && !r.e) { \
160 break; \
162 if (c.e && !r.e) { \
163 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
165 if (!c.e && r.e) { \
166 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
168 for (__i=0;c.e[__i] != NULL; __i++) { \
169 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
171 } while(0)
173 #define CHECK_ALIGN(size, n) do {\
174 if (size % n) {\
175 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
176 size, n, size + n - (size % n));\
178 } while(0)
180 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
182 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
183 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
184 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
185 uint32_t round_size = DO_ROUND(size, align);\
186 if (round_size != needed) {\
187 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
188 CHECK_ALIGN(size, align);\
191 } while(0)
193 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
194 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
195 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
196 uint32_t round_size = DO_ROUND(size, align);\
197 if (round_size != needed) {\
198 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
199 CHECK_ALIGN(size, align);\
202 } while(0)
204 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
205 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
206 uint32_t size = ndr_size_##fn(info, level, 0);\
207 uint32_t round_size = DO_ROUND(size, align);\
208 if (round_size != needed) {\
209 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
210 CHECK_ALIGN(size, align);\
213 } while(0)
215 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
216 const union spoolss_PrinterInfo *i,
217 uint32_t level,
218 union spoolss_SetPrinterInfo *s)
220 switch (level) {
221 case 0:
222 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
223 break;
224 case 2:
225 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
226 s->info2->servername = i->info2.servername;
227 s->info2->printername = i->info2.printername;
228 s->info2->sharename = i->info2.sharename;
229 s->info2->portname = i->info2.portname;
230 s->info2->drivername = i->info2.drivername;
231 s->info2->comment = i->info2.comment;
232 s->info2->location = i->info2.location;
233 s->info2->devmode_ptr = 0;
234 s->info2->sepfile = i->info2.sepfile;
235 s->info2->printprocessor = i->info2.printprocessor;
236 s->info2->datatype = i->info2.datatype;
237 s->info2->parameters = i->info2.parameters;
238 s->info2->secdesc_ptr = 0;
239 s->info2->attributes = i->info2.attributes;
240 s->info2->priority = i->info2.priority;
241 s->info2->defaultpriority = i->info2.defaultpriority;
242 s->info2->starttime = i->info2.starttime;
243 s->info2->untiltime = i->info2.untiltime;
244 s->info2->status = i->info2.status;
245 s->info2->cjobs = i->info2.cjobs;
246 s->info2->averageppm = i->info2.averageppm;
247 break;
248 case 3:
249 case 4:
250 case 5:
251 case 6:
252 case 7:
253 case 8:
254 case 9:
255 default:
256 return false;
259 return true;
262 static bool test_OpenPrinter_server(struct torture_context *tctx,
263 struct dcerpc_pipe *p,
264 struct policy_handle *server_handle)
266 NTSTATUS status;
267 struct spoolss_OpenPrinter op;
268 struct dcerpc_binding_handle *b = p->binding_handle;
270 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
271 op.in.datatype = NULL;
272 op.in.devmode_ctr.devmode= NULL;
273 op.in.access_mask = 0;
274 op.out.handle = server_handle;
276 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
278 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
279 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
280 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
282 return true;
285 static bool test_EnumPorts(struct torture_context *tctx,
286 void *private_data)
288 struct test_spoolss_context *ctx =
289 talloc_get_type_abort(private_data, struct test_spoolss_context);
290 struct dcerpc_pipe *p = ctx->spoolss_pipe;
291 struct dcerpc_binding_handle *b = p->binding_handle;
292 NTSTATUS status;
293 struct spoolss_EnumPorts r;
294 uint16_t levels[] = { 1, 2 };
295 int i, j;
297 for (i=0;i<ARRAY_SIZE(levels);i++) {
298 int level = levels[i];
299 DATA_BLOB blob;
300 uint32_t needed;
301 uint32_t count;
302 union spoolss_PortInfo *info;
304 r.in.servername = "";
305 r.in.level = level;
306 r.in.buffer = NULL;
307 r.in.offered = 0;
308 r.out.needed = &needed;
309 r.out.count = &count;
310 r.out.info = &info;
312 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
314 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
315 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
316 if (W_ERROR_IS_OK(r.out.result)) {
317 /* TODO: do some more checks here */
318 continue;
320 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
321 "EnumPorts unexpected return code");
323 blob = data_blob_talloc_zero(ctx, needed);
324 r.in.buffer = &blob;
325 r.in.offered = needed;
327 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
328 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
330 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
332 torture_assert(tctx, info, "EnumPorts returned no info");
334 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
336 ctx->port_count[level] = count;
337 ctx->ports[level] = info;
340 for (i=1;i<ARRAY_SIZE(levels);i++) {
341 int level = levels[i];
342 int old_level = levels[i-1];
343 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
344 "EnumPorts invalid value");
346 /* if the array sizes are not the same we would maybe segfault in the following code */
348 for (i=0;i<ARRAY_SIZE(levels);i++) {
349 int level = levels[i];
350 for (j=0;j<ctx->port_count[level];j++) {
351 union spoolss_PortInfo *cur = &ctx->ports[level][j];
352 union spoolss_PortInfo *ref = &ctx->ports[2][j];
353 switch (level) {
354 case 1:
355 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
356 break;
357 case 2:
358 /* level 2 is our reference, and it makes no sense to compare it to itself */
359 break;
364 return true;
367 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
368 void *private_data)
370 struct test_spoolss_context *ctx =
371 talloc_get_type_abort(private_data, struct test_spoolss_context);
373 NTSTATUS status;
374 struct dcerpc_pipe *p = ctx->spoolss_pipe;
375 struct dcerpc_binding_handle *b = p->binding_handle;
376 struct spoolss_GetPrintProcessorDirectory r;
377 struct {
378 uint16_t level;
379 const char *server;
380 } levels[] = {{
381 .level = 1,
382 .server = NULL
384 .level = 1,
385 .server = ""
387 .level = 78,
388 .server = ""
390 .level = 1,
391 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
393 .level = 1024,
394 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
397 int i;
398 uint32_t needed;
400 for (i=0;i<ARRAY_SIZE(levels);i++) {
401 int level = levels[i].level;
402 DATA_BLOB blob;
404 r.in.server = levels[i].server;
405 r.in.environment = ctx->environment;
406 r.in.level = level;
407 r.in.buffer = NULL;
408 r.in.offered = 0;
409 r.out.needed = &needed;
411 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
413 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
414 torture_assert_ntstatus_ok(tctx, status,
415 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
416 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
417 "GetPrintProcessorDirectory unexpected return code");
419 blob = data_blob_talloc_zero(tctx, needed);
420 r.in.buffer = &blob;
421 r.in.offered = needed;
423 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
424 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
426 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
428 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
431 return true;
435 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
436 void *private_data)
438 struct test_spoolss_context *ctx =
439 talloc_get_type_abort(private_data, struct test_spoolss_context);
441 NTSTATUS status;
442 struct dcerpc_pipe *p = ctx->spoolss_pipe;
443 struct dcerpc_binding_handle *b = p->binding_handle;
444 struct spoolss_GetPrinterDriverDirectory r;
445 struct {
446 uint16_t level;
447 const char *server;
448 } levels[] = {{
449 .level = 1,
450 .server = NULL
452 .level = 1,
453 .server = ""
455 .level = 78,
456 .server = ""
458 .level = 1,
459 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
461 .level = 1024,
462 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
465 int i;
466 uint32_t needed;
468 for (i=0;i<ARRAY_SIZE(levels);i++) {
469 int level = levels[i].level;
470 DATA_BLOB blob;
472 r.in.server = levels[i].server;
473 r.in.environment = ctx->environment;
474 r.in.level = level;
475 r.in.buffer = NULL;
476 r.in.offered = 0;
477 r.out.needed = &needed;
479 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
481 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
482 torture_assert_ntstatus_ok(tctx, status,
483 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
484 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
485 "GetPrinterDriverDirectory unexpected return code");
487 blob = data_blob_talloc_zero(tctx, needed);
488 r.in.buffer = &blob;
489 r.in.offered = needed;
491 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
492 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
494 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
496 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
499 return true;
502 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
503 struct dcerpc_binding_handle *b,
504 const char *server_name,
505 const char *environment,
506 uint32_t level,
507 uint32_t *count_p,
508 union spoolss_DriverInfo **info_p)
510 struct spoolss_EnumPrinterDrivers r;
511 uint32_t needed;
512 uint32_t count;
513 union spoolss_DriverInfo *info;
515 r.in.server = server_name;
516 r.in.environment = environment;
517 r.in.level = level;
518 r.in.buffer = NULL;
519 r.in.offered = 0;
520 r.out.needed = &needed;
521 r.out.count = &count;
522 r.out.info = &info;
524 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
525 r.in.environment, r.in.level);
527 torture_assert_ntstatus_ok(tctx,
528 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
529 "EnumPrinterDrivers failed");
530 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
531 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
532 r.in.buffer = &blob;
533 r.in.offered = needed;
535 torture_assert_ntstatus_ok(tctx,
536 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
537 "EnumPrinterDrivers failed");
540 torture_assert_werr_ok(tctx, r.out.result,
541 "EnumPrinterDrivers failed");
543 if (count_p) {
544 *count_p = count;
546 if (info_p) {
547 *info_p = info;
550 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
552 return true;
556 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
557 struct dcerpc_binding_handle *b,
558 const char *server_name,
559 const char *environment,
560 uint32_t level,
561 const char *driver_name)
563 uint32_t count;
564 union spoolss_DriverInfo *info;
565 int i;
567 torture_assert(tctx,
568 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
569 "failed to enumerate printer drivers");
571 for (i=0; i < count; i++) {
572 const char *driver_name_ret;
573 switch (level) {
574 case 1:
575 driver_name_ret = info[i].info1.driver_name;
576 break;
577 case 2:
578 driver_name_ret = info[i].info2.driver_name;
579 break;
580 case 3:
581 driver_name_ret = info[i].info3.driver_name;
582 break;
583 case 4:
584 driver_name_ret = info[i].info4.driver_name;
585 break;
586 case 5:
587 driver_name_ret = info[i].info5.driver_name;
588 break;
589 case 6:
590 driver_name_ret = info[i].info6.driver_name;
591 break;
592 case 7:
593 driver_name_ret = info[i].info7.driver_name;
594 break;
595 case 8:
596 driver_name_ret = info[i].info8.driver_name;
597 break;
598 default:
599 break;
601 if (strequal(driver_name, driver_name_ret)) {
602 return true;
606 return false;
609 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
610 void *private_data)
612 struct test_spoolss_context *ctx =
613 talloc_get_type_abort(private_data, struct test_spoolss_context);
614 struct dcerpc_pipe *p = ctx->spoolss_pipe;
615 struct dcerpc_binding_handle *b = p->binding_handle;
616 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
617 int i, j, a;
619 /* FIXME: gd, come back and fix "" as server, and handle
620 * priority of returned error codes in torture test and samba 3
621 * server */
622 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
623 const char *environments[2];
625 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
626 environments[1] = ctx->environment;
628 for (a=0;a<ARRAY_SIZE(environments);a++) {
630 for (i=0;i<ARRAY_SIZE(levels);i++) {
631 int level = levels[i];
632 uint32_t count;
633 union spoolss_DriverInfo *info;
635 torture_assert(tctx,
636 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
637 "failed to enumerate drivers");
639 ctx->driver_count[level] = count;
640 ctx->drivers[level] = info;
643 for (i=1;i<ARRAY_SIZE(levels);i++) {
644 int level = levels[i];
645 int old_level = levels[i-1];
647 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
648 "EnumPrinterDrivers invalid value");
651 for (i=0;i<ARRAY_SIZE(levels);i++) {
652 int level = levels[i];
654 for (j=0;j<ctx->driver_count[level];j++) {
655 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
656 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
658 switch (level) {
659 case 1:
660 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
661 break;
662 case 2:
663 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
664 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
665 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
666 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
667 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
668 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
669 break;
670 case 3:
671 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
672 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
673 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
674 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
675 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
676 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
677 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
678 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
679 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
680 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
681 break;
682 case 4:
683 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
684 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
685 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
686 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
687 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
688 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
689 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
690 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
691 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
692 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
693 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
694 break;
695 case 5:
696 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
697 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
698 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
699 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
700 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
701 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
702 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
703 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
704 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
705 break;
706 case 6:
707 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
708 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
709 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
710 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
711 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
712 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
713 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
714 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
715 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
716 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
717 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
718 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
719 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
720 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
721 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
722 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
723 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
724 break;
725 case 8:
726 /* level 8 is our reference, and it makes no sense to compare it to itself */
727 break;
733 return true;
736 static bool test_EnumMonitors(struct torture_context *tctx,
737 void *private_data)
739 struct test_spoolss_context *ctx =
740 talloc_get_type_abort(private_data, struct test_spoolss_context);
741 struct dcerpc_pipe *p = ctx->spoolss_pipe;
742 struct dcerpc_binding_handle *b = p->binding_handle;
743 NTSTATUS status;
744 struct spoolss_EnumMonitors r;
745 uint16_t levels[] = { 1, 2 };
746 int i, j;
748 for (i=0;i<ARRAY_SIZE(levels);i++) {
749 int level = levels[i];
750 DATA_BLOB blob;
751 uint32_t needed;
752 uint32_t count;
753 union spoolss_MonitorInfo *info;
755 r.in.servername = "";
756 r.in.level = level;
757 r.in.buffer = NULL;
758 r.in.offered = 0;
759 r.out.needed = &needed;
760 r.out.count = &count;
761 r.out.info = &info;
763 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
765 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
766 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
767 if (W_ERROR_IS_OK(r.out.result)) {
768 /* TODO: do some more checks here */
769 continue;
771 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
772 "EnumMonitors failed");
774 blob = data_blob_talloc_zero(ctx, needed);
775 r.in.buffer = &blob;
776 r.in.offered = needed;
778 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
779 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
781 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
783 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
785 ctx->monitor_count[level] = count;
786 ctx->monitors[level] = info;
789 for (i=1;i<ARRAY_SIZE(levels);i++) {
790 int level = levels[i];
791 int old_level = levels[i-1];
792 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
793 "EnumMonitors invalid value");
796 for (i=0;i<ARRAY_SIZE(levels);i++) {
797 int level = levels[i];
798 for (j=0;j<ctx->monitor_count[level];j++) {
799 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
800 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
801 switch (level) {
802 case 1:
803 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
804 break;
805 case 2:
806 /* level 2 is our reference, and it makes no sense to compare it to itself */
807 break;
812 return true;
815 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
816 struct dcerpc_binding_handle *b,
817 const char *environment,
818 uint32_t level,
819 uint32_t *count_p,
820 union spoolss_PrintProcessorInfo **info_p)
822 struct spoolss_EnumPrintProcessors r;
823 DATA_BLOB blob;
824 uint32_t needed;
825 uint32_t count;
826 union spoolss_PrintProcessorInfo *info;
828 r.in.servername = "";
829 r.in.environment = environment;
830 r.in.level = level;
831 r.in.buffer = NULL;
832 r.in.offered = 0;
833 r.out.needed = &needed;
834 r.out.count = &count;
835 r.out.info = &info;
837 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
839 torture_assert_ntstatus_ok(tctx,
840 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
841 "EnumPrintProcessors failed");
842 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
843 blob = data_blob_talloc_zero(tctx, needed);
844 r.in.buffer = &blob;
845 r.in.offered = needed;
846 torture_assert_ntstatus_ok(tctx,
847 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
848 "EnumPrintProcessors failed");
850 torture_assert_werr_ok(tctx, r.out.result,
851 "EnumPrintProcessors failed");
853 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
855 if (count_p) {
856 *count_p = count;
858 if (info_p) {
859 *info_p = info;
862 return true;
865 static bool test_EnumPrintProcessors(struct torture_context *tctx,
866 void *private_data)
868 struct test_spoolss_context *ctx =
869 talloc_get_type_abort(private_data, struct test_spoolss_context);
871 uint16_t levels[] = { 1 };
872 int i, j;
873 struct dcerpc_pipe *p = ctx->spoolss_pipe;
874 struct dcerpc_binding_handle *b = p->binding_handle;
876 for (i=0;i<ARRAY_SIZE(levels);i++) {
877 int level = levels[i];
878 union spoolss_PrintProcessorInfo *info;
879 uint32_t count;
881 torture_assert(tctx,
882 test_EnumPrintProcessors_level(tctx, b, ctx->environment, level, &count, &info),
883 "test_EnumPrintProcessors_level failed");
885 ctx->print_processor_count[level] = count;
886 ctx->print_processors[level] = info;
889 for (i=1;i<ARRAY_SIZE(levels);i++) {
890 int level = levels[i];
891 int old_level = levels[i-1];
892 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
893 "EnumPrintProcessors failed");
896 for (i=0;i<ARRAY_SIZE(levels);i++) {
897 int level = levels[i];
898 for (j=0;j<ctx->print_processor_count[level];j++) {
899 #if 0
900 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
901 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
902 #endif
903 switch (level) {
904 case 1:
905 /* level 1 is our reference, and it makes no sense to compare it to itself */
906 break;
911 return true;
914 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
915 void *private_data)
917 struct test_spoolss_context *ctx =
918 talloc_get_type_abort(private_data, struct test_spoolss_context);
920 NTSTATUS status;
921 struct spoolss_EnumPrintProcDataTypes r;
922 uint16_t levels[] = { 1 };
923 int i;
924 struct dcerpc_pipe *p = ctx->spoolss_pipe;
925 struct dcerpc_binding_handle *b = p->binding_handle;
927 for (i=0;i<ARRAY_SIZE(levels);i++) {
928 int level = levels[i];
929 DATA_BLOB blob;
930 uint32_t needed;
931 uint32_t count;
932 union spoolss_PrintProcDataTypesInfo *info;
934 r.in.servername = "";
935 r.in.print_processor_name = "winprint";
936 r.in.level = level;
937 r.in.buffer = NULL;
938 r.in.offered = 0;
939 r.out.needed = &needed;
940 r.out.count = &count;
941 r.out.info = &info;
943 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
945 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
946 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
947 if (W_ERROR_IS_OK(r.out.result)) {
948 /* TODO: do some more checks here */
949 continue;
951 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
952 "EnumPrintProcDataTypes unexpected return code");
954 blob = data_blob_talloc_zero(tctx, needed);
955 r.in.buffer = &blob;
956 r.in.offered = needed;
958 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
959 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
961 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
963 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, needed, 4);
967 return true;
971 static bool test_EnumPrinters(struct torture_context *tctx,
972 void *private_data)
974 struct test_spoolss_context *ctx =
975 talloc_get_type_abort(private_data, struct test_spoolss_context);
976 struct dcerpc_pipe *p = ctx->spoolss_pipe;
977 struct dcerpc_binding_handle *b = p->binding_handle;
978 struct spoolss_EnumPrinters r;
979 NTSTATUS status;
980 uint16_t levels[] = { 0, 1, 2, 4, 5 };
981 int i, j;
983 for (i=0;i<ARRAY_SIZE(levels);i++) {
984 int level = levels[i];
985 DATA_BLOB blob;
986 uint32_t needed;
987 uint32_t count;
988 union spoolss_PrinterInfo *info;
990 r.in.flags = PRINTER_ENUM_LOCAL;
991 r.in.server = "";
992 r.in.level = level;
993 r.in.buffer = NULL;
994 r.in.offered = 0;
995 r.out.needed = &needed;
996 r.out.count = &count;
997 r.out.info = &info;
999 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1001 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1002 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1003 if (W_ERROR_IS_OK(r.out.result)) {
1004 /* TODO: do some more checks here */
1005 continue;
1007 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1008 "EnumPrinters unexpected return code");
1010 blob = data_blob_talloc_zero(ctx, needed);
1011 r.in.buffer = &blob;
1012 r.in.offered = needed;
1014 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1015 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1017 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1019 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1021 ctx->printer_count[level] = count;
1022 ctx->printers[level] = info;
1025 for (i=1;i<ARRAY_SIZE(levels);i++) {
1026 int level = levels[i];
1027 int old_level = levels[i-1];
1028 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1029 "EnumPrinters invalid value");
1032 for (i=0;i<ARRAY_SIZE(levels);i++) {
1033 int level = levels[i];
1034 for (j=0;j<ctx->printer_count[level];j++) {
1035 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1036 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1037 switch (level) {
1038 case 0:
1039 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1040 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1041 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1042 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1043 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1044 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1045 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1046 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1047 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1048 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1049 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1050 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1051 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1052 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1053 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1054 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1055 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1056 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1057 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1058 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1059 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1060 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1061 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1062 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1063 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1064 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1065 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1066 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1067 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1068 break;
1069 case 1:
1070 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1071 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1072 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1073 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1074 break;
1075 case 2:
1076 /* level 2 is our reference, and it makes no sense to compare it to itself */
1077 break;
1078 case 4:
1079 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1080 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1081 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1082 break;
1083 case 5:
1084 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1085 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1086 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1087 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1088 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1089 break;
1094 /* TODO:
1095 * - verify that the port of a printer was in the list returned by EnumPorts
1098 return true;
1101 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1102 struct dcerpc_binding_handle *b,
1103 struct policy_handle *handle,
1104 const char *driver_name,
1105 const char *environment);
1107 bool test_GetPrinter_level(struct torture_context *tctx,
1108 struct dcerpc_binding_handle *b,
1109 struct policy_handle *handle,
1110 uint32_t level,
1111 union spoolss_PrinterInfo *info)
1113 struct spoolss_GetPrinter r;
1114 uint32_t needed;
1116 r.in.handle = handle;
1117 r.in.level = level;
1118 r.in.buffer = NULL;
1119 r.in.offered = 0;
1120 r.out.needed = &needed;
1122 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1124 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1125 "GetPrinter failed");
1127 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1128 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1129 r.in.buffer = &blob;
1130 r.in.offered = needed;
1132 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1133 "GetPrinter failed");
1136 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1138 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1140 if (info && r.out.info) {
1141 *info = *r.out.info;
1144 return true;
1148 static bool test_GetPrinter(struct torture_context *tctx,
1149 struct dcerpc_binding_handle *b,
1150 struct policy_handle *handle,
1151 const char *environment)
1153 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1154 int i;
1156 for (i=0;i<ARRAY_SIZE(levels);i++) {
1158 union spoolss_PrinterInfo info;
1160 ZERO_STRUCT(info);
1162 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1163 "failed to call GetPrinter");
1165 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1166 torture_assert(tctx,
1167 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1168 "failed to call test_GetPrinterDriver2");
1172 return true;
1175 static bool test_SetPrinter(struct torture_context *tctx,
1176 struct dcerpc_binding_handle *b,
1177 struct policy_handle *handle,
1178 struct spoolss_SetPrinterInfoCtr *info_ctr,
1179 struct spoolss_DevmodeContainer *devmode_ctr,
1180 struct sec_desc_buf *secdesc_ctr,
1181 enum spoolss_PrinterControl command)
1183 struct spoolss_SetPrinter r;
1185 r.in.handle = handle;
1186 r.in.info_ctr = info_ctr;
1187 r.in.devmode_ctr = devmode_ctr;
1188 r.in.secdesc_ctr = secdesc_ctr;
1189 r.in.command = command;
1191 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1193 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1194 "failed to call SetPrinter");
1195 torture_assert_werr_ok(tctx, r.out.result,
1196 "failed to call SetPrinter");
1198 return true;
1201 static bool test_SetPrinter_errors(struct torture_context *tctx,
1202 struct dcerpc_binding_handle *b,
1203 struct policy_handle *handle)
1205 struct spoolss_SetPrinter r;
1206 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1207 int i;
1209 struct spoolss_SetPrinterInfoCtr info_ctr;
1210 struct spoolss_DevmodeContainer devmode_ctr;
1211 struct sec_desc_buf secdesc_ctr;
1213 info_ctr.level = 0;
1214 info_ctr.info.info0 = NULL;
1216 ZERO_STRUCT(devmode_ctr);
1217 ZERO_STRUCT(secdesc_ctr);
1219 r.in.handle = handle;
1220 r.in.info_ctr = &info_ctr;
1221 r.in.devmode_ctr = &devmode_ctr;
1222 r.in.secdesc_ctr = &secdesc_ctr;
1223 r.in.command = 0;
1225 torture_comment(tctx, "Testing SetPrinter all zero\n");
1227 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1228 "failed to call SetPrinter");
1229 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1230 "failed to call SetPrinter");
1232 again:
1233 for (i=0; i < ARRAY_SIZE(levels); i++) {
1235 struct spoolss_SetPrinterInfo0 info0;
1236 struct spoolss_SetPrinterInfo1 info1;
1237 struct spoolss_SetPrinterInfo2 info2;
1238 struct spoolss_SetPrinterInfo3 info3;
1239 struct spoolss_SetPrinterInfo4 info4;
1240 struct spoolss_SetPrinterInfo5 info5;
1241 struct spoolss_SetPrinterInfo6 info6;
1242 struct spoolss_SetPrinterInfo7 info7;
1243 struct spoolss_SetPrinterInfo8 info8;
1244 struct spoolss_SetPrinterInfo9 info9;
1247 info_ctr.level = levels[i];
1248 switch (levels[i]) {
1249 case 0:
1250 ZERO_STRUCT(info0);
1251 info_ctr.info.info0 = &info0;
1252 break;
1253 case 1:
1254 ZERO_STRUCT(info1);
1255 info_ctr.info.info1 = &info1;
1256 break;
1257 case 2:
1258 ZERO_STRUCT(info2);
1259 info_ctr.info.info2 = &info2;
1260 break;
1261 case 3:
1262 ZERO_STRUCT(info3);
1263 info_ctr.info.info3 = &info3;
1264 break;
1265 case 4:
1266 ZERO_STRUCT(info4);
1267 info_ctr.info.info4 = &info4;
1268 break;
1269 case 5:
1270 ZERO_STRUCT(info5);
1271 info_ctr.info.info5 = &info5;
1272 break;
1273 case 6:
1274 ZERO_STRUCT(info6);
1275 info_ctr.info.info6 = &info6;
1276 break;
1277 case 7:
1278 ZERO_STRUCT(info7);
1279 info_ctr.info.info7 = &info7;
1280 break;
1281 case 8:
1282 ZERO_STRUCT(info8);
1283 info_ctr.info.info8 = &info8;
1284 break;
1285 case 9:
1286 ZERO_STRUCT(info9);
1287 info_ctr.info.info9 = &info9;
1288 break;
1291 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1292 info_ctr.level, r.in.command);
1294 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1295 "failed to call SetPrinter");
1297 switch (r.in.command) {
1298 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1299 /* is ignored for all levels other then 0 */
1300 if (info_ctr.level > 0) {
1301 /* ignored then */
1302 break;
1304 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1305 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1306 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1307 if (info_ctr.level > 0) {
1308 /* is invalid for all levels other then 0 */
1309 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1310 "unexpected error code returned");
1311 continue;
1312 } else {
1313 torture_assert_werr_ok(tctx, r.out.result,
1314 "failed to call SetPrinter with non 0 command");
1315 continue;
1317 break;
1319 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1320 /* FIXME: gd needs further investigation */
1321 default:
1322 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1323 "unexpected error code returned");
1324 continue;
1327 switch (info_ctr.level) {
1328 case 1:
1329 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1330 "unexpected error code returned");
1331 break;
1332 case 2:
1333 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1334 "unexpected error code returned");
1335 break;
1336 case 3:
1337 case 4:
1338 case 5:
1339 case 7:
1340 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1341 "unexpected error code returned");
1342 break;
1343 case 9:
1344 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1345 "unexpected error code returned");
1346 break;
1347 default:
1348 torture_assert_werr_ok(tctx, r.out.result,
1349 "failed to call SetPrinter");
1350 break;
1354 if (r.in.command < 5) {
1355 r.in.command++;
1356 goto again;
1359 return true;
1362 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1364 if ((r->level == 2) && (r->info.info2)) {
1365 r->info.info2->secdesc_ptr = 0;
1366 r->info.info2->devmode_ptr = 0;
1370 static bool test_PrinterInfo(struct torture_context *tctx,
1371 struct dcerpc_binding_handle *b,
1372 struct policy_handle *handle)
1374 NTSTATUS status;
1375 struct spoolss_SetPrinter s;
1376 struct spoolss_GetPrinter q;
1377 struct spoolss_GetPrinter q0;
1378 struct spoolss_SetPrinterInfoCtr info_ctr;
1379 union spoolss_PrinterInfo info;
1380 struct spoolss_DevmodeContainer devmode_ctr;
1381 struct sec_desc_buf secdesc_ctr;
1382 uint32_t needed;
1383 bool ret = true;
1384 int i;
1386 uint32_t status_list[] = {
1387 /* these do not stick
1388 PRINTER_STATUS_PAUSED,
1389 PRINTER_STATUS_ERROR,
1390 PRINTER_STATUS_PENDING_DELETION, */
1391 PRINTER_STATUS_PAPER_JAM,
1392 PRINTER_STATUS_PAPER_OUT,
1393 PRINTER_STATUS_MANUAL_FEED,
1394 PRINTER_STATUS_PAPER_PROBLEM,
1395 PRINTER_STATUS_OFFLINE,
1396 PRINTER_STATUS_IO_ACTIVE,
1397 PRINTER_STATUS_BUSY,
1398 PRINTER_STATUS_PRINTING,
1399 PRINTER_STATUS_OUTPUT_BIN_FULL,
1400 PRINTER_STATUS_NOT_AVAILABLE,
1401 PRINTER_STATUS_WAITING,
1402 PRINTER_STATUS_PROCESSING,
1403 PRINTER_STATUS_INITIALIZING,
1404 PRINTER_STATUS_WARMING_UP,
1405 PRINTER_STATUS_TONER_LOW,
1406 PRINTER_STATUS_NO_TONER,
1407 PRINTER_STATUS_PAGE_PUNT,
1408 PRINTER_STATUS_USER_INTERVENTION,
1409 PRINTER_STATUS_OUT_OF_MEMORY,
1410 PRINTER_STATUS_DOOR_OPEN,
1411 PRINTER_STATUS_SERVER_UNKNOWN,
1412 PRINTER_STATUS_POWER_SAVE,
1413 /* these do not stick
1414 0x02000000,
1415 0x04000000,
1416 0x08000000,
1417 0x10000000,
1418 0x20000000,
1419 0x40000000,
1420 0x80000000 */
1422 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1423 uint32_t attribute_list[] = {
1424 PRINTER_ATTRIBUTE_QUEUED,
1425 /* fails with WERR_INVALID_DATATYPE:
1426 PRINTER_ATTRIBUTE_DIRECT, */
1427 /* does not stick
1428 PRINTER_ATTRIBUTE_DEFAULT, */
1429 PRINTER_ATTRIBUTE_SHARED,
1430 /* does not stick
1431 PRINTER_ATTRIBUTE_NETWORK, */
1432 PRINTER_ATTRIBUTE_HIDDEN,
1433 PRINTER_ATTRIBUTE_LOCAL,
1434 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1435 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1436 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1437 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1438 /* does not stick
1439 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1440 /* fails with WERR_INVALID_DATATYPE:
1441 PRINTER_ATTRIBUTE_RAW_ONLY, */
1442 /* these do not stick
1443 PRINTER_ATTRIBUTE_PUBLISHED,
1444 PRINTER_ATTRIBUTE_FAX,
1445 PRINTER_ATTRIBUTE_TS,
1446 0x00010000,
1447 0x00020000,
1448 0x00040000,
1449 0x00080000,
1450 0x00100000,
1451 0x00200000,
1452 0x00400000,
1453 0x00800000,
1454 0x01000000,
1455 0x02000000,
1456 0x04000000,
1457 0x08000000,
1458 0x10000000,
1459 0x20000000,
1460 0x40000000,
1461 0x80000000 */
1464 ZERO_STRUCT(devmode_ctr);
1465 ZERO_STRUCT(secdesc_ctr);
1467 s.in.handle = handle;
1468 s.in.command = 0;
1469 s.in.info_ctr = &info_ctr;
1470 s.in.devmode_ctr = &devmode_ctr;
1471 s.in.secdesc_ctr = &secdesc_ctr;
1473 q.in.handle = handle;
1474 q.out.info = &info;
1475 q0 = q;
1477 #define TESTGETCALL(call, r) \
1478 r.in.buffer = NULL; \
1479 r.in.offered = 0;\
1480 r.out.needed = &needed; \
1481 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1482 if (!NT_STATUS_IS_OK(status)) { \
1483 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1484 r.in.level, nt_errstr(status), __location__); \
1485 ret = false; \
1486 break; \
1488 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1489 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1490 r.in.buffer = &blob; \
1491 r.in.offered = needed; \
1493 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1494 if (!NT_STATUS_IS_OK(status)) { \
1495 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1496 r.in.level, nt_errstr(status), __location__); \
1497 ret = false; \
1498 break; \
1500 if (!W_ERROR_IS_OK(r.out.result)) { \
1501 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1502 r.in.level, win_errstr(r.out.result), __location__); \
1503 ret = false; \
1504 break; \
1508 #define TESTSETCALL_EXP(call, r, err) \
1509 clear_info2(&info_ctr);\
1510 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1511 if (!NT_STATUS_IS_OK(status)) { \
1512 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1513 r.in.info_ctr->level, nt_errstr(status), __location__); \
1514 ret = false; \
1515 break; \
1517 if (!W_ERROR_IS_OK(err)) { \
1518 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1519 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1520 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1521 ret = false; \
1523 break; \
1525 if (!W_ERROR_IS_OK(r.out.result)) { \
1526 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1527 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1528 ret = false; \
1529 break; \
1532 #define TESTSETCALL(call, r) \
1533 TESTSETCALL_EXP(call, r, WERR_OK)
1535 #define STRING_EQUAL(s1, s2, field) \
1536 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1537 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1538 #field, s2, __location__); \
1539 ret = false; \
1540 break; \
1543 #define MEM_EQUAL(s1, s2, length, field) \
1544 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1545 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1546 #field, (const char *)s2, __location__); \
1547 ret = false; \
1548 break; \
1551 #define INT_EQUAL(i1, i2, field) \
1552 if (i1 != i2) { \
1553 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1554 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1555 ret = false; \
1556 break; \
1559 #define SD_EQUAL(sd1, sd2, field) \
1560 if (!security_descriptor_equal(sd1, sd2)) { \
1561 torture_comment(tctx, "Failed to set %s (%s)\n", \
1562 #field, __location__); \
1563 ret = false; \
1564 break; \
1567 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1568 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1569 q.in.level = lvl1; \
1570 TESTGETCALL(GetPrinter, q) \
1571 info_ctr.level = lvl1; \
1572 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1573 info_ctr.info.info ## lvl1->field1 = value;\
1574 TESTSETCALL_EXP(SetPrinter, s, err) \
1575 info_ctr.info.info ## lvl1->field1 = ""; \
1576 TESTGETCALL(GetPrinter, q) \
1577 info_ctr.info.info ## lvl1->field1 = value; \
1578 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1579 q.in.level = lvl2; \
1580 TESTGETCALL(GetPrinter, q) \
1581 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1582 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1583 } while (0)
1585 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1586 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1587 } while (0);
1589 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1590 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1591 q.in.level = lvl1; \
1592 TESTGETCALL(GetPrinter, q) \
1593 info_ctr.level = lvl1; \
1594 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1595 info_ctr.info.info ## lvl1->field1 = value; \
1596 TESTSETCALL(SetPrinter, s) \
1597 info_ctr.info.info ## lvl1->field1 = 0; \
1598 TESTGETCALL(GetPrinter, q) \
1599 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1600 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1601 q.in.level = lvl2; \
1602 TESTGETCALL(GetPrinter, q) \
1603 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1604 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1605 } while (0)
1607 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1608 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1609 } while (0)
1611 q0.in.level = 0;
1612 do { TESTGETCALL(GetPrinter, q0) } while (0);
1614 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1615 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1617 /* level 0 printername does not stick */
1618 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1619 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1620 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1621 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1622 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1623 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1624 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1625 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1626 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1627 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1628 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1629 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1630 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1631 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1632 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1634 /* servername can be set but does not stick
1635 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1636 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1637 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1640 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1641 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1642 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1643 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1644 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1646 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1647 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1648 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1649 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1650 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1651 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1652 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1653 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1654 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1655 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1657 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1658 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1659 attribute_list[i],
1660 (attribute_list[i] | default_attribute)
1661 ); */
1662 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1663 attribute_list[i],
1664 (attribute_list[i] | default_attribute)
1666 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1667 attribute_list[i],
1668 (attribute_list[i] | default_attribute)
1670 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1671 attribute_list[i],
1672 (attribute_list[i] | default_attribute)
1674 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1675 attribute_list[i],
1676 (attribute_list[i] | default_attribute)
1677 ); */
1678 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1679 attribute_list[i],
1680 (attribute_list[i] | default_attribute)
1682 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1683 attribute_list[i],
1684 (attribute_list[i] | default_attribute)
1686 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1687 attribute_list[i],
1688 (attribute_list[i] | default_attribute)
1690 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1691 attribute_list[i],
1692 (attribute_list[i] | default_attribute)
1693 ); */
1694 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1695 attribute_list[i],
1696 (attribute_list[i] | default_attribute)
1698 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1699 attribute_list[i],
1700 (attribute_list[i] | default_attribute)
1702 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1703 attribute_list[i],
1704 (attribute_list[i] | default_attribute)
1708 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1709 /* level 2 sets do not stick
1710 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1711 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1712 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1713 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1714 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1715 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1718 /* priorities need to be between 0 and 99
1719 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1720 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1721 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1722 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1723 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1724 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1725 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1726 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1727 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1729 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1730 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1732 /* does not stick
1733 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1734 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1736 /* does not stick
1737 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1738 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1740 /* FIXME: gd also test devmode and secdesc behavior */
1743 /* verify composition of level 1 description field */
1744 const char *description;
1745 const char *tmp;
1747 q0.in.level = 1;
1748 do { TESTGETCALL(GetPrinter, q0) } while (0);
1750 description = talloc_strdup(tctx, q0.out.info->info1.description);
1752 q0.in.level = 2;
1753 do { TESTGETCALL(GetPrinter, q0) } while (0);
1755 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1756 q0.out.info->info2.printername,
1757 q0.out.info->info2.drivername,
1758 q0.out.info->info2.location);
1760 do { STRING_EQUAL(description, tmp, "description")} while (0);
1763 return ret;
1766 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1767 do { struct dom_sid *__got = (got), *__expected = (expected); \
1768 if (!dom_sid_equal(__got, __expected)) { \
1769 torture_result(torture_ctx, TORTURE_FAIL, \
1770 __location__": "#got" was %s, expected %s: %s", \
1771 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1772 return false; \
1774 } while(0)
1776 static bool test_security_descriptor_equal(struct torture_context *tctx,
1777 const struct security_descriptor *sd1,
1778 const struct security_descriptor *sd2)
1780 if (sd1 == sd2) {
1781 return true;
1784 if (!sd1 || !sd2) {
1785 torture_comment(tctx, "%s\n", __location__);
1786 return false;
1789 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1790 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1792 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1793 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1795 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1796 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1797 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1798 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1799 return false;
1801 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1802 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1803 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1804 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1805 return false;
1808 return true;
1811 static bool test_sd_set_level(struct torture_context *tctx,
1812 struct dcerpc_binding_handle *b,
1813 struct policy_handle *handle,
1814 uint32_t level,
1815 struct security_descriptor *sd)
1817 struct spoolss_SetPrinterInfoCtr info_ctr;
1818 struct spoolss_DevmodeContainer devmode_ctr;
1819 struct sec_desc_buf secdesc_ctr;
1820 union spoolss_SetPrinterInfo sinfo;
1822 ZERO_STRUCT(devmode_ctr);
1823 ZERO_STRUCT(secdesc_ctr);
1825 switch (level) {
1826 case 2: {
1827 union spoolss_PrinterInfo info;
1828 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1829 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1831 info_ctr.level = 2;
1832 info_ctr.info = sinfo;
1834 break;
1836 case 3: {
1837 struct spoolss_SetPrinterInfo3 info3;
1839 info3.sec_desc_ptr = 0;
1841 info_ctr.level = 3;
1842 info_ctr.info.info3 = &info3;
1844 break;
1846 default:
1847 return false;
1850 secdesc_ctr.sd = sd;
1852 torture_assert(tctx,
1853 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1855 return true;
1858 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1859 struct dcerpc_binding_handle *b,
1860 struct policy_handle *handle)
1862 union spoolss_PrinterInfo info;
1863 struct security_descriptor *sd1, *sd2;
1864 int i;
1866 /* just compare level 2 and level 3 */
1868 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1870 sd1 = info.info2.secdesc;
1872 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1874 sd2 = info.info3.secdesc;
1876 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1877 "SD level 2 != SD level 3");
1880 /* query level 2, set level 2, query level 2 */
1882 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1884 sd1 = info.info2.secdesc;
1886 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1888 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1890 sd2 = info.info2.secdesc;
1891 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1892 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1893 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1896 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1897 "SD level 2 != SD level 2 after SD has been set via level 2");
1900 /* query level 2, set level 3, query level 2 */
1902 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1904 sd1 = info.info2.secdesc;
1906 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1908 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1910 sd2 = info.info2.secdesc;
1912 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1913 "SD level 2 != SD level 2 after SD has been set via level 3");
1915 /* set modified sd level 3, query level 2 */
1917 for (i=0; i < 93; i++) {
1918 struct security_ace a;
1919 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1920 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1921 a.flags = 0;
1922 a.size = 0; /* autogenerated */
1923 a.access_mask = 0;
1924 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1925 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1928 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1930 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd2 = info.info2.secdesc;
1933 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1934 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1935 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1938 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1939 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1942 return true;
1946 * wrapper call that saves original sd, runs tests, and restores sd
1949 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1950 struct dcerpc_binding_handle *b,
1951 struct policy_handle *handle)
1953 union spoolss_PrinterInfo info;
1954 struct security_descriptor *sd;
1955 bool ret = true;
1957 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1959 /* save original sd */
1961 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1962 "failed to get initial security descriptor");
1964 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1966 /* run tests */
1968 ret = test_PrinterInfo_SDs(tctx, b, handle);
1970 /* restore original sd */
1972 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1973 "failed to restore initial security descriptor");
1975 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1976 ret ? "succeeded" : "failed");
1979 return ret;
1982 static bool test_devmode_set_level(struct torture_context *tctx,
1983 struct dcerpc_binding_handle *b,
1984 struct policy_handle *handle,
1985 uint32_t level,
1986 struct spoolss_DeviceMode *devmode)
1988 struct spoolss_SetPrinterInfoCtr info_ctr;
1989 struct spoolss_DevmodeContainer devmode_ctr;
1990 struct sec_desc_buf secdesc_ctr;
1991 union spoolss_SetPrinterInfo sinfo;
1993 ZERO_STRUCT(devmode_ctr);
1994 ZERO_STRUCT(secdesc_ctr);
1996 switch (level) {
1997 case 2: {
1998 union spoolss_PrinterInfo info;
1999 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2000 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2002 info_ctr.level = 2;
2003 info_ctr.info = sinfo;
2005 break;
2007 case 8: {
2008 struct spoolss_SetPrinterInfo8 info8;
2010 info8.devmode_ptr = 0;
2012 info_ctr.level = 8;
2013 info_ctr.info.info8 = &info8;
2015 break;
2017 default:
2018 return false;
2021 devmode_ctr.devmode = devmode;
2023 torture_assert(tctx,
2024 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2026 return true;
2030 static bool test_devicemode_equal(struct torture_context *tctx,
2031 const struct spoolss_DeviceMode *d1,
2032 const struct spoolss_DeviceMode *d2)
2034 if (d1 == d2) {
2035 return true;
2038 if (!d1 || !d2) {
2039 torture_comment(tctx, "%s\n", __location__);
2040 return false;
2042 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2043 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2044 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2045 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2046 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2047 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2048 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2049 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2050 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2051 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2052 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2053 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2054 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2055 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2056 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2057 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2058 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2059 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2060 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2061 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2062 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2063 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2064 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2065 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2066 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2067 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2068 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2069 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2070 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2071 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2072 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2073 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2074 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2075 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2076 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2078 return true;
2081 static bool test_devicemode_full(struct torture_context *tctx,
2082 struct dcerpc_binding_handle *b,
2083 struct policy_handle *handle)
2085 struct spoolss_SetPrinter s;
2086 struct spoolss_GetPrinter q;
2087 struct spoolss_GetPrinter q0;
2088 struct spoolss_SetPrinterInfoCtr info_ctr;
2089 struct spoolss_SetPrinterInfo8 info8;
2090 union spoolss_PrinterInfo info;
2091 struct spoolss_DevmodeContainer devmode_ctr;
2092 struct sec_desc_buf secdesc_ctr;
2093 uint32_t needed;
2094 bool ret = true;
2095 NTSTATUS status;
2097 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2098 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2099 q.in.level = lvl1; \
2100 TESTGETCALL(GetPrinter, q) \
2101 info_ctr.level = lvl1; \
2102 if (lvl1 == 2) {\
2103 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2104 } else if (lvl1 == 8) {\
2105 info_ctr.info.info ## lvl1 = &info8; \
2107 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2108 devmode_ctr.devmode->field1 = value; \
2109 TESTSETCALL(SetPrinter, s) \
2110 TESTGETCALL(GetPrinter, q) \
2111 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2112 q.in.level = lvl2; \
2113 TESTGETCALL(GetPrinter, q) \
2114 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2115 } while (0)
2117 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2118 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2119 } while (0)
2121 ZERO_STRUCT(devmode_ctr);
2122 ZERO_STRUCT(secdesc_ctr);
2123 ZERO_STRUCT(info8);
2125 s.in.handle = handle;
2126 s.in.command = 0;
2127 s.in.info_ctr = &info_ctr;
2128 s.in.devmode_ctr = &devmode_ctr;
2129 s.in.secdesc_ctr = &secdesc_ctr;
2131 q.in.handle = handle;
2132 q.out.info = &info;
2133 q0 = q;
2135 #if 0
2136 const char *devicename;/* [charset(UTF16)] */
2137 enum spoolss_DeviceModeSpecVersion specversion;
2138 uint16_t driverversion;
2139 uint16_t size;
2140 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2141 uint32_t fields;
2142 #endif
2144 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2145 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2146 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2147 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2148 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2149 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2150 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2151 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2152 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2153 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2154 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2155 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2156 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2157 #if 0
2158 const char *formname;/* [charset(UTF16)] */
2159 #endif
2160 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2161 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2162 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2163 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2164 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2165 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2166 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2167 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2168 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2169 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2170 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2171 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2172 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2173 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2175 return ret;
2178 static bool call_OpenPrinterEx(struct torture_context *tctx,
2179 struct dcerpc_pipe *p,
2180 const char *name,
2181 struct spoolss_DeviceMode *devmode,
2182 struct policy_handle *handle);
2184 static bool test_ClosePrinter(struct torture_context *tctx,
2185 struct dcerpc_binding_handle *b,
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 static 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_matrix(struct torture_context *tctx,
4801 struct dcerpc_pipe *p,
4802 struct policy_handle *handle,
4803 const char *printername,
4804 struct dcerpc_binding_handle *winreg_handle,
4805 struct policy_handle *hive_handle)
4807 struct dcerpc_binding_handle *b = p->binding_handle;
4808 const char *value_name = "dog";
4809 const char *keys[] = {
4810 "torturedataex",
4811 "torture data ex",
4812 #if 0
4813 /* FIXME: not working with s3 atm. */
4814 "torturedataex_with_subkey\\subkey",
4815 "torturedataex_with_subkey\\subkey:0",
4816 "torturedataex_with_subkey\\subkey:1",
4817 "torturedataex_with_subkey\\subkey\\subsubkey",
4818 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4819 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4820 #endif
4821 "torture,data",
4822 #if 0
4823 /* FIXME: not working with s3 atm. */
4825 "torture,data,ex",
4826 "torture,data\\ex",
4827 "torture\\data,ex"
4828 #endif
4830 enum winreg_Type types[] = {
4831 REG_SZ,
4832 REG_MULTI_SZ,
4833 REG_DWORD,
4834 REG_BINARY
4836 const char *str = "abcdefghi";
4837 int i, t, s;
4840 for (i=0; i < ARRAY_SIZE(keys); i++) {
4841 for (t=0; t < ARRAY_SIZE(types); t++) {
4842 for (s=0; s < strlen(str); s++) {
4844 char *c;
4845 const char *key;
4846 enum winreg_Type type;
4847 const char *string = talloc_strndup(tctx, str, s);
4848 const char *array[2];
4849 DATA_BLOB blob = data_blob_string_const(string);
4850 const char **subkeys;
4851 DATA_BLOB data;
4852 uint8_t *data_out;
4853 uint32_t needed, offered = 0;
4854 uint32_t ecount;
4855 struct spoolss_PrinterEnumValues *einfo;
4857 array[0] = talloc_strdup(tctx, string);
4858 array[1] = NULL;
4860 if (types[t] == REG_DWORD) {
4861 s = 0xffff;
4864 if (torture_setting_bool(tctx, "samba3", false)) {
4865 if ((types[t] == REG_MULTI_SZ) && s == 0) {
4866 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4867 continue;
4871 switch (types[t]) {
4872 case REG_BINARY:
4873 data = blob;
4874 offered = blob.length;
4875 break;
4876 case REG_DWORD:
4877 data = data_blob_talloc(tctx, NULL, 4);
4878 SIVAL(data.data, 0, 0x12345678);
4879 offered = 4;
4880 break;
4881 case REG_SZ:
4882 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
4883 type = REG_SZ;
4884 offered = data.length;
4885 /*strlen_m_term(data.string)*2;*/
4886 break;
4887 case REG_MULTI_SZ:
4888 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
4889 type = REG_MULTI_SZ;
4890 offered = data.length;
4891 break;
4892 default:
4893 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4896 torture_assert(tctx,
4897 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
4898 "failed to call SetPrinterDataEx");
4900 torture_assert(tctx,
4901 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4902 "failed to call GetPrinterDataEx");
4904 torture_assert(tctx,
4905 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4906 "failed to call EnumPrinterDataEx");
4908 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4909 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4910 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4912 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4913 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4914 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4915 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4916 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4917 if (einfo[0].data_length > 0) {
4918 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4921 if (winreg_handle && hive_handle) {
4922 enum winreg_Type w_type;
4923 uint32_t w_size;
4924 uint32_t w_length;
4925 uint8_t *w_data;
4927 torture_assert(tctx,
4928 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4929 printername, keys[i], value_name,
4930 &w_type, &w_size, &w_length, &w_data), "");
4932 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4933 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4934 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4935 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4938 key = talloc_strdup(tctx, keys[i]);
4940 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4941 return false;
4944 c = strchr(key, '\\');
4945 if (c) {
4946 int k;
4948 /* we have subkeys */
4950 *c = 0;
4952 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4953 return false;
4956 for (k=0; subkeys && subkeys[k]; k++) {
4958 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4960 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4961 return false;
4965 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4966 return false;
4969 } else {
4970 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4971 return false;
4978 return true;
4981 static bool test_PrinterData_winreg(struct torture_context *tctx,
4982 struct dcerpc_pipe *p,
4983 struct policy_handle *handle,
4984 const char *printer_name)
4986 struct dcerpc_binding_handle *b = p->binding_handle;
4987 struct dcerpc_pipe *p2;
4988 bool ret = true;
4989 struct policy_handle hive_handle;
4990 struct dcerpc_binding_handle *b2;
4992 torture_assert_ntstatus_ok(tctx,
4993 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4994 "could not open winreg pipe");
4995 b2 = p2->binding_handle;
4997 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4999 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5000 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5002 test_winreg_CloseKey(tctx, b2, &hive_handle);
5004 talloc_free(p2);
5006 return ret;
5009 static bool test_Forms_winreg(struct torture_context *tctx,
5010 struct dcerpc_binding_handle *b,
5011 struct policy_handle *handle,
5012 bool print_server,
5013 const char *printer_name)
5015 struct dcerpc_pipe *p2;
5016 bool ret = true;
5017 struct policy_handle hive_handle;
5018 struct dcerpc_binding_handle *b2;
5020 torture_assert_ntstatus_ok(tctx,
5021 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5022 "could not open winreg pipe");
5023 b2 = p2->binding_handle;
5025 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5027 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5029 test_winreg_CloseKey(tctx, b2, &hive_handle);
5031 talloc_free(p2);
5033 return ret;
5036 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5037 struct dcerpc_pipe *p,
5038 struct policy_handle *handle,
5039 const char *printer_name)
5041 struct dcerpc_binding_handle *b = p->binding_handle;
5042 struct dcerpc_pipe *p2;
5043 bool ret = true;
5044 struct policy_handle hive_handle;
5045 struct dcerpc_binding_handle *b2;
5047 torture_assert_ntstatus_ok(tctx,
5048 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5049 "could not open winreg pipe");
5050 b2 = p2->binding_handle;
5052 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5054 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5056 test_winreg_CloseKey(tctx, b2, &hive_handle);
5058 talloc_free(p2);
5060 return ret;
5063 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5064 struct dcerpc_pipe *p,
5065 struct policy_handle *handle,
5066 const char *printer_name,
5067 const char *driver_name,
5068 const char *environment)
5070 struct dcerpc_binding_handle *b = p->binding_handle;
5071 struct dcerpc_pipe *p2;
5072 bool ret = true;
5073 struct policy_handle hive_handle;
5074 struct dcerpc_binding_handle *b2;
5076 torture_assert_ntstatus_ok(tctx,
5077 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5078 "could not open winreg pipe");
5079 b2 = p2->binding_handle;
5081 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5083 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
5085 test_winreg_CloseKey(tctx, b2, &hive_handle);
5087 talloc_free(p2);
5089 return ret;
5092 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5093 struct dcerpc_binding_handle *b,
5094 const char *environment)
5096 struct dcerpc_pipe *p2;
5097 bool ret = true;
5098 struct policy_handle hive_handle;
5099 struct dcerpc_binding_handle *b2;
5101 torture_assert_ntstatus_ok(tctx,
5102 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5103 "could not open winreg pipe");
5104 b2 = p2->binding_handle;
5106 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5108 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5110 test_winreg_CloseKey(tctx, b2, &hive_handle);
5112 talloc_free(p2);
5114 return ret;
5117 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5118 struct dcerpc_pipe *p,
5119 struct policy_handle *handle,
5120 const char *printer_name)
5122 struct spoolss_SetPrinterInfoCtr info_ctr;
5123 struct spoolss_DevmodeContainer devmode_ctr;
5124 struct sec_desc_buf secdesc_ctr;
5125 union spoolss_SetPrinterInfo sinfo;
5126 union spoolss_PrinterInfo info;
5127 struct dcerpc_binding_handle *b = p->binding_handle;
5128 const char *pname;
5130 ZERO_STRUCT(info_ctr);
5131 ZERO_STRUCT(devmode_ctr);
5132 ZERO_STRUCT(secdesc_ctr);
5134 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5136 torture_assert(tctx,
5137 test_GetPrinter_level(tctx, b, handle, 2, &info),
5138 "failed to query Printer level 2");
5140 torture_assert(tctx,
5141 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5142 "failed to convert");
5144 info_ctr.level = 2;
5145 info_ctr.info = sinfo;
5147 #define TEST_SZ(wname, iname) \
5148 do {\
5149 enum winreg_Type type;\
5150 uint8_t *data;\
5151 uint32_t needed;\
5152 DATA_BLOB blob;\
5153 const char *str;\
5154 torture_assert(tctx,\
5155 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5156 "failed to query");\
5157 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5158 blob = data_blob_const(data, needed);\
5159 torture_assert(tctx,\
5160 pull_reg_sz(tctx, &blob, &str),\
5161 "failed to pull REG_SZ");\
5162 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5163 } while(0);
5166 #define TEST_SET_SZ(wname, iname, val) \
5167 do {\
5168 enum winreg_Type type;\
5169 uint8_t *data;\
5170 uint32_t needed;\
5171 DATA_BLOB blob;\
5172 const char *str;\
5173 sinfo.info2->iname = val;\
5174 torture_assert(tctx,\
5175 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5176 "failed to call SetPrinter");\
5177 torture_assert(tctx,\
5178 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5179 "failed to query");\
5180 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5181 blob = data_blob_const(data, needed);\
5182 torture_assert(tctx,\
5183 pull_reg_sz(tctx, &blob, &str),\
5184 "failed to pull REG_SZ");\
5185 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5186 } while(0);
5188 #define TEST_SET_DWORD(wname, iname, val) \
5189 do {\
5190 enum winreg_Type type;\
5191 uint8_t *data;\
5192 uint32_t needed;\
5193 uint32_t value;\
5194 sinfo.info2->iname = val;\
5195 torture_assert(tctx,\
5196 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5197 "failed to call SetPrinter");\
5198 torture_assert(tctx,\
5199 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5200 "failed to query");\
5201 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5202 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5203 value = IVAL(data, 0); \
5204 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5205 } while(0);
5207 TEST_SET_SZ("description", comment, "newval");
5208 TEST_SET_SZ("location", location, "newval");
5209 /* TEST_SET_DWORD("priority", priority, 25); */
5211 torture_assert(tctx,
5212 test_GetPrinter_level(tctx, b, handle, 2, &info),
5213 "failed to query Printer level 2");
5215 TEST_SZ("description", info.info2.comment);
5216 /* TEST_SZ("driverName", info.info2.drivername); */
5217 TEST_SZ("location", info.info2.location);
5219 pname = strrchr(info.info2.printername, '\\');
5220 if (pname == NULL) {
5221 pname = info.info2.printername;
5222 } else {
5223 pname++;
5225 /* TEST_SZ("printerName", pname); */
5226 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5227 /* TEST_SZ("printShareName", info.info2.sharename); */
5229 /* FIXME gd: complete the list */
5231 #undef TEST_SZ
5232 #undef TEST_SET_SZ
5233 #undef TEST_DWORD
5235 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5237 return true;
5240 static bool test_print_processors_winreg(struct torture_context *tctx,
5241 void *private_data)
5243 struct test_spoolss_context *ctx =
5244 talloc_get_type_abort(private_data, struct test_spoolss_context);
5245 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5246 struct dcerpc_binding_handle *b = p->binding_handle;
5248 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5251 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5252 struct dcerpc_binding_handle *b,
5253 struct policy_handle *handle,
5254 uint32_t *change_id)
5256 enum winreg_Type type;
5257 uint8_t *data;
5258 uint32_t needed;
5260 torture_assert(tctx,
5261 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5262 "failed to call GetPrinterData");
5264 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5265 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5267 *change_id = IVAL(data, 0);
5269 return true;
5272 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5273 struct dcerpc_pipe *p,
5274 struct policy_handle *handle,
5275 uint32_t *change_id)
5277 enum winreg_Type type;
5278 uint8_t *data;
5279 uint32_t needed;
5281 torture_assert(tctx,
5282 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5283 "failed to call GetPrinterData");
5285 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5286 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5288 *change_id = IVAL(data, 0);
5290 return true;
5293 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5294 struct dcerpc_binding_handle *b,
5295 struct policy_handle *handle,
5296 uint32_t *change_id)
5298 union spoolss_PrinterInfo info;
5300 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5301 "failed to query Printer level 0");
5303 *change_id = info.info0.change_id;
5305 return true;
5308 static bool test_ChangeID(struct torture_context *tctx,
5309 struct dcerpc_pipe *p,
5310 struct policy_handle *handle)
5312 uint32_t change_id, change_id_ex, change_id_info;
5313 uint32_t change_id2, change_id_ex2, change_id_info2;
5314 union spoolss_PrinterInfo info;
5315 const char *comment;
5316 struct dcerpc_binding_handle *b = p->binding_handle;
5318 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5320 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5321 "failed to query for ChangeID");
5322 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5323 "failed to query for ChangeID");
5324 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5325 "failed to query for ChangeID");
5327 torture_assert_int_equal(tctx, change_id, change_id_ex,
5328 "change_ids should all be equal");
5329 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5330 "change_ids should all be equal");
5333 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5335 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5336 "failed to query for ChangeID");
5337 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5338 "failed to query Printer level 2");
5339 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5340 "failed to query for ChangeID");
5341 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5342 "failed to query for ChangeID");
5343 torture_assert_int_equal(tctx, change_id, change_id_ex,
5344 "change_id should not have changed");
5345 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5346 "change_id should not have changed");
5349 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5351 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5352 "failed to query for ChangeID");
5353 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5354 "failed to query for ChangeID");
5355 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5356 "failed to query for ChangeID");
5357 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5358 "failed to query Printer level 2");
5359 comment = talloc_strdup(tctx, info.info2.comment);
5362 struct spoolss_SetPrinterInfoCtr info_ctr;
5363 struct spoolss_DevmodeContainer devmode_ctr;
5364 struct sec_desc_buf secdesc_ctr;
5365 union spoolss_SetPrinterInfo sinfo;
5367 ZERO_STRUCT(info_ctr);
5368 ZERO_STRUCT(devmode_ctr);
5369 ZERO_STRUCT(secdesc_ctr);
5372 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5373 sinfo.info2->comment = "torture_comment";
5375 info_ctr.level = 2;
5376 info_ctr.info = sinfo;
5378 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5379 "failed to call SetPrinter");
5381 sinfo.info2->comment = comment;
5383 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5384 "failed to call SetPrinter");
5388 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5389 "failed to query for ChangeID");
5390 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5391 "failed to query for ChangeID");
5392 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5393 "failed to query for ChangeID");
5395 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5396 "change_ids should all be equal");
5397 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5398 "change_ids should all be equal");
5400 torture_assert(tctx, (change_id < change_id2),
5401 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5402 change_id2, change_id));
5403 torture_assert(tctx, (change_id_ex < change_id_ex2),
5404 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5405 change_id_ex2, change_id_ex));
5406 torture_assert(tctx, (change_id_info < change_id_info2),
5407 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5408 change_id_info2, change_id_info));
5410 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5412 return true;
5415 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5416 struct dcerpc_pipe *p,
5417 struct policy_handle *handle)
5419 NTSTATUS status;
5420 struct dcerpc_binding *b;
5421 struct dcerpc_pipe *p2;
5422 struct spoolss_ClosePrinter cp;
5424 /* only makes sense on SMB */
5425 if (p->conn->transport.transport != NCACN_NP) {
5426 return true;
5429 torture_comment(tctx, "Testing close on secondary pipe\n");
5431 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5432 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5434 status = dcerpc_secondary_connection(p, &p2, b);
5435 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5437 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5438 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5440 cp.in.handle = handle;
5441 cp.out.handle = handle;
5443 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5444 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5445 "ERROR: Allowed close on secondary connection");
5447 talloc_free(p2);
5449 return true;
5452 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5453 struct dcerpc_binding_handle *b, const char *name)
5455 NTSTATUS status;
5456 struct spoolss_OpenPrinter op;
5457 struct spoolss_OpenPrinterEx opEx;
5458 struct policy_handle handle;
5459 bool ret = true;
5461 op.in.printername = name;
5462 op.in.datatype = NULL;
5463 op.in.devmode_ctr.devmode= NULL;
5464 op.in.access_mask = 0;
5465 op.out.handle = &handle;
5467 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5469 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5470 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5471 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5472 "unexpected result");
5474 if (W_ERROR_IS_OK(op.out.result)) {
5475 ret &=test_ClosePrinter(tctx, b, &handle);
5478 opEx.in.printername = name;
5479 opEx.in.datatype = NULL;
5480 opEx.in.devmode_ctr.devmode = NULL;
5481 opEx.in.access_mask = 0;
5482 opEx.in.level = 1;
5483 opEx.in.userlevel.level1 = NULL;
5484 opEx.out.handle = &handle;
5486 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5488 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5489 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5490 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5491 "unexpected result");
5493 if (W_ERROR_IS_OK(opEx.out.result)) {
5494 ret &=test_ClosePrinter(tctx, b, &handle);
5497 return ret;
5500 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5501 void *private_data)
5503 struct test_spoolss_context *ctx =
5504 talloc_get_type_abort(private_data, struct test_spoolss_context);
5506 const char *badnames[] = {
5507 "__INVALID_PRINTER__",
5508 "\\\\__INVALID_HOST__",
5510 "\\\\\\",
5511 "\\\\\\__INVALID_PRINTER__"
5513 const char *badname;
5514 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5515 const char *server_name = dcerpc_server_name(p);
5516 struct dcerpc_binding_handle *b = p->binding_handle;
5517 int i;
5519 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5520 torture_assert(tctx,
5521 test_OpenPrinter_badname(tctx, b, badnames[i]),
5522 "");
5525 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5526 torture_assert(tctx,
5527 test_OpenPrinter_badname(tctx, b, badname),
5528 "");
5530 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5531 torture_assert(tctx,
5532 test_OpenPrinter_badname(tctx, b, badname),
5533 "");
5535 return true;
5538 static bool test_OpenPrinter(struct torture_context *tctx,
5539 struct dcerpc_pipe *p,
5540 const char *name,
5541 const char *environment)
5543 NTSTATUS status;
5544 struct spoolss_OpenPrinter r;
5545 struct policy_handle handle;
5546 bool ret = true;
5547 struct dcerpc_binding_handle *b = p->binding_handle;
5549 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5550 r.in.datatype = NULL;
5551 r.in.devmode_ctr.devmode= NULL;
5552 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5553 r.out.handle = &handle;
5555 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5557 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5559 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5561 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5563 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5564 ret = false;
5567 if (!torture_setting_bool(tctx, "samba3", false)) {
5568 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5569 ret = false;
5573 if (!test_ClosePrinter(tctx, b, &handle)) {
5574 ret = false;
5577 return ret;
5580 static bool call_OpenPrinterEx(struct torture_context *tctx,
5581 struct dcerpc_pipe *p,
5582 const char *name,
5583 struct spoolss_DeviceMode *devmode,
5584 struct policy_handle *handle)
5586 struct spoolss_OpenPrinterEx r;
5587 struct spoolss_UserLevel1 userlevel1;
5588 NTSTATUS status;
5589 struct dcerpc_binding_handle *b = p->binding_handle;
5591 if (name && name[0]) {
5592 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5593 dcerpc_server_name(p), name);
5594 } else {
5595 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5596 dcerpc_server_name(p));
5599 r.in.datatype = NULL;
5600 r.in.devmode_ctr.devmode= devmode;
5601 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5602 r.in.level = 1;
5603 r.in.userlevel.level1 = &userlevel1;
5604 r.out.handle = handle;
5606 userlevel1.size = 1234;
5607 userlevel1.client = "hello";
5608 userlevel1.user = "spottyfoot!";
5609 userlevel1.build = 1;
5610 userlevel1.major = 2;
5611 userlevel1.minor = 3;
5612 userlevel1.processor = 4;
5614 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5616 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5618 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5620 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5622 return true;
5625 static bool test_printer_rename(struct torture_context *tctx,
5626 struct dcerpc_pipe *p,
5627 struct policy_handle *handle,
5628 const char *name)
5630 bool ret = true;
5631 union spoolss_PrinterInfo info;
5632 union spoolss_SetPrinterInfo sinfo;
5633 struct spoolss_SetPrinterInfoCtr info_ctr;
5634 struct spoolss_DevmodeContainer devmode_ctr;
5635 struct sec_desc_buf secdesc_ctr;
5636 const char *printer_name;
5637 const char *printer_name_orig;
5638 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5639 struct policy_handle new_handle;
5640 const char *q;
5641 struct dcerpc_binding_handle *b = p->binding_handle;
5643 ZERO_STRUCT(devmode_ctr);
5644 ZERO_STRUCT(secdesc_ctr);
5646 torture_comment(tctx, "Testing Printer rename operations\n");
5648 torture_assert(tctx,
5649 test_GetPrinter_level(tctx, b, handle, 2, &info),
5650 "failed to call GetPrinter level 2");
5652 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5654 q = strrchr(info.info2.printername, '\\');
5655 if (q) {
5656 torture_warning(tctx,
5657 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5660 torture_assert(tctx,
5661 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5663 sinfo.info2->printername = printer_name_new;
5665 info_ctr.level = 2;
5666 info_ctr.info = sinfo;
5668 torture_assert(tctx,
5669 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5670 "failed to call SetPrinter level 2");
5672 torture_assert(tctx,
5673 test_GetPrinter_level(tctx, b, handle, 2, &info),
5674 "failed to call GetPrinter level 2");
5676 printer_name = talloc_strdup(tctx, info.info2.printername);
5678 q = strrchr(info.info2.printername, '\\');
5679 if (q) {
5680 torture_warning(tctx,
5681 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5682 q++;
5683 printer_name = q;
5686 torture_assert_str_equal(tctx, printer_name, printer_name_new,
5687 "new printer name was not set");
5689 /* samba currently cannot fully rename printers */
5690 if (!torture_setting_bool(tctx, "samba3", false)) {
5691 torture_assert(tctx,
5692 test_OpenPrinter_badname(tctx, b, printer_name_orig),
5693 "still can open printer with oldname after rename");
5694 } else {
5695 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5698 torture_assert(tctx,
5699 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5700 "failed to open printer with new name");
5702 torture_assert(tctx,
5703 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5704 "failed to call GetPrinter level 2");
5706 /* FIXME: we openend with servername! */
5707 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5708 dcerpc_server_name(p), printer_name_new);
5710 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5711 "new printer name was not set");
5713 torture_assert(tctx,
5714 test_ClosePrinter(tctx, b, &new_handle),
5715 "failed to close printer");
5717 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5719 return ret;
5723 static bool test_OpenPrinterEx(struct torture_context *tctx,
5724 struct dcerpc_pipe *p,
5725 const char *name,
5726 const char *environment)
5728 struct policy_handle handle;
5729 bool ret = true;
5730 struct dcerpc_binding_handle *b = p->binding_handle;
5732 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5733 return false;
5736 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5737 ret = false;
5740 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5741 ret = false;
5744 if (!test_EnumForms_all(tctx, b, &handle, false)) {
5745 ret = false;
5748 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5749 ret = false;
5752 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5753 ret = false;
5756 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5757 ret = false;
5760 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5761 ret = false;
5764 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5765 ret = false;
5768 if (!test_printer_keys(tctx, b, &handle)) {
5769 ret = false;
5772 if (!test_PausePrinter(tctx, b, &handle)) {
5773 ret = false;
5776 if (!test_DoPrintTest(tctx, b, &handle)) {
5777 ret = false;
5780 if (!test_ResumePrinter(tctx, b, &handle)) {
5781 ret = false;
5784 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5785 ret = false;
5788 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5789 ret = false;
5792 if (!torture_setting_bool(tctx, "samba3", false)) {
5793 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5794 ret = false;
5798 if (!test_ClosePrinter(tctx, b, &handle)) {
5799 ret = false;
5802 return ret;
5805 static bool test_EnumPrinters_old(struct torture_context *tctx,
5806 void *private_data)
5808 struct test_spoolss_context *ctx =
5809 talloc_get_type_abort(private_data, struct test_spoolss_context);
5810 struct spoolss_EnumPrinters r;
5811 NTSTATUS status;
5812 uint16_t levels[] = {1, 2, 4, 5};
5813 int i;
5814 bool ret = true;
5815 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5816 struct dcerpc_binding_handle *b = p->binding_handle;
5818 for (i=0;i<ARRAY_SIZE(levels);i++) {
5819 union spoolss_PrinterInfo *info;
5820 int j;
5821 uint32_t needed;
5822 uint32_t count;
5824 r.in.flags = PRINTER_ENUM_LOCAL;
5825 r.in.server = "";
5826 r.in.level = levels[i];
5827 r.in.buffer = NULL;
5828 r.in.offered = 0;
5829 r.out.needed = &needed;
5830 r.out.count = &count;
5831 r.out.info = &info;
5833 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5835 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5836 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5838 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5839 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5840 r.in.buffer = &blob;
5841 r.in.offered = needed;
5842 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5845 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5847 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5849 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
5851 if (!info) {
5852 torture_comment(tctx, "No printers returned\n");
5853 return true;
5856 for (j=0;j<count;j++) {
5857 if (r.in.level == 1) {
5858 char *unc = talloc_strdup(tctx, info[j].info1.name);
5859 char *slash, *name;
5860 name = unc;
5861 if (unc[0] == '\\' && unc[1] == '\\') {
5862 unc +=2;
5864 slash = strchr(unc, '\\');
5865 if (slash) {
5866 slash++;
5867 name = slash;
5869 if (!test_OpenPrinter(tctx, p, name, ctx->environment)) {
5870 ret = false;
5872 if (!test_OpenPrinterEx(tctx, p, name, ctx->environment)) {
5873 ret = false;
5879 return ret;
5882 static bool test_GetPrinterDriver(struct torture_context *tctx,
5883 struct dcerpc_binding_handle *b,
5884 struct policy_handle *handle,
5885 const char *driver_name)
5887 struct spoolss_GetPrinterDriver r;
5888 uint32_t needed;
5890 r.in.handle = handle;
5891 r.in.architecture = "W32X86";
5892 r.in.level = 1;
5893 r.in.buffer = NULL;
5894 r.in.offered = 0;
5895 r.out.needed = &needed;
5897 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5899 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5900 "failed to call GetPrinterDriver");
5901 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5902 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5903 r.in.buffer = &blob;
5904 r.in.offered = needed;
5905 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5906 "failed to call GetPrinterDriver");
5909 torture_assert_werr_ok(tctx, r.out.result,
5910 "failed to call GetPrinterDriver");
5912 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
5914 return true;
5917 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5918 struct dcerpc_binding_handle *b,
5919 struct policy_handle *handle,
5920 const char *driver_name,
5921 const char *architecture,
5922 uint32_t level,
5923 uint32_t client_major_version,
5924 uint32_t client_minor_version,
5925 union spoolss_DriverInfo *info_p,
5926 WERROR *result_p)
5929 struct spoolss_GetPrinterDriver2 r;
5930 uint32_t needed;
5931 uint32_t server_major_version;
5932 uint32_t server_minor_version;
5934 r.in.handle = handle;
5935 r.in.architecture = architecture;
5936 r.in.client_major_version = client_major_version;
5937 r.in.client_minor_version = client_minor_version;
5938 r.in.buffer = NULL;
5939 r.in.offered = 0;
5940 r.in.level = level;
5941 r.out.needed = &needed;
5942 r.out.server_major_version = &server_major_version;
5943 r.out.server_minor_version = &server_minor_version;
5945 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
5946 driver_name, r.in.level);
5948 torture_assert_ntstatus_ok(tctx,
5949 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5950 "failed to call GetPrinterDriver2");
5951 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5952 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5953 r.in.buffer = &blob;
5954 r.in.offered = needed;
5955 torture_assert_ntstatus_ok(tctx,
5956 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5957 "failed to call GetPrinterDriver2");
5960 if (result_p) {
5961 *result_p = r.out.result;
5964 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
5965 switch (r.in.level) {
5966 case 101:
5967 case 8:
5968 torture_comment(tctx,
5969 "level %d not implemented, not considering as an error\n",
5970 r.in.level);
5971 return true;
5972 default:
5973 break;
5977 torture_assert_werr_ok(tctx, r.out.result,
5978 "failed to call GetPrinterDriver2");
5980 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
5982 if (info_p) {
5983 *info_p = *r.out.info;
5986 return true;
5989 static bool test_GetPrinterDriver2(struct torture_context *tctx,
5990 struct dcerpc_binding_handle *b,
5991 struct policy_handle *handle,
5992 const char *driver_name,
5993 const char *architecture)
5995 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
5996 int i;
5999 for (i=0;i<ARRAY_SIZE(levels);i++) {
6001 torture_assert(tctx,
6002 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6003 "");
6006 return true;
6009 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6010 void *private_data)
6012 struct test_spoolss_context *ctx =
6013 talloc_get_type_abort(private_data, struct test_spoolss_context);
6014 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6015 int i;
6016 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6017 struct dcerpc_binding_handle *b = p->binding_handle;
6018 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6020 for (i=0;i<ARRAY_SIZE(levels);i++) {
6022 uint32_t count;
6023 union spoolss_DriverInfo *info;
6025 torture_assert(tctx,
6026 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6027 "failed to enumerate drivers");
6029 if (!info) {
6030 torture_comment(tctx, "No printer drivers returned\n");
6031 break;
6035 return true;
6038 static bool test_DeletePrinter(struct torture_context *tctx,
6039 struct dcerpc_binding_handle *b,
6040 struct policy_handle *handle)
6042 struct spoolss_DeletePrinter r;
6044 torture_comment(tctx, "Testing DeletePrinter\n");
6046 r.in.handle = handle;
6048 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6049 "failed to delete printer");
6050 torture_assert_werr_ok(tctx, r.out.result,
6051 "failed to delete printer");
6053 return true;
6056 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6057 struct dcerpc_binding_handle *b,
6058 uint32_t flags,
6059 uint32_t level,
6060 const char *name,
6061 bool *found)
6063 struct spoolss_EnumPrinters e;
6064 uint32_t count;
6065 union spoolss_PrinterInfo *info;
6066 uint32_t needed;
6067 int i;
6069 *found = false;
6071 e.in.flags = flags;
6072 e.in.server = NULL;
6073 e.in.level = level;
6074 e.in.buffer = NULL;
6075 e.in.offered = 0;
6076 e.out.count = &count;
6077 e.out.info = &info;
6078 e.out.needed = &needed;
6080 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6081 "failed to enum printers");
6083 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6084 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6085 e.in.buffer = &blob;
6086 e.in.offered = needed;
6088 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6089 "failed to enum printers");
6092 torture_assert_werr_ok(tctx, e.out.result,
6093 "failed to enum printers");
6095 for (i=0; i < count; i++) {
6097 const char *current = NULL;
6098 const char *q;
6100 switch (level) {
6101 case 1:
6102 current = info[i].info1.name;
6103 break;
6106 if (strequal(current, name)) {
6107 *found = true;
6108 break;
6111 q = strrchr(current, '\\');
6112 if (q) {
6113 if (!e.in.server) {
6114 torture_warning(tctx,
6115 "server returns printername %s incl. servername although we did not set servername", current);
6117 q++;
6118 if (strequal(q, name)) {
6119 *found = true;
6120 break;
6125 return true;
6128 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6129 struct dcerpc_pipe *p,
6130 const char *printername,
6131 bool ex)
6133 WERROR result;
6134 struct spoolss_AddPrinter r;
6135 struct spoolss_AddPrinterEx rex;
6136 struct spoolss_SetPrinterInfoCtr info_ctr;
6137 struct spoolss_SetPrinterInfo1 info1;
6138 struct spoolss_DevmodeContainer devmode_ctr;
6139 struct sec_desc_buf secdesc_ctr;
6140 struct spoolss_UserLevelCtr userlevel_ctr;
6141 struct policy_handle handle;
6142 bool found = false;
6143 struct dcerpc_binding_handle *b = p->binding_handle;
6145 ZERO_STRUCT(devmode_ctr);
6146 ZERO_STRUCT(secdesc_ctr);
6147 ZERO_STRUCT(userlevel_ctr);
6148 ZERO_STRUCT(info1);
6150 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6151 ex ? "Ex":"", printername);
6153 /* try to add printer to wellknown printer list (level 1) */
6155 userlevel_ctr.level = 1;
6157 info_ctr.info.info1 = &info1;
6158 info_ctr.level = 1;
6160 rex.in.server = NULL;
6161 rex.in.info_ctr = &info_ctr;
6162 rex.in.devmode_ctr = &devmode_ctr;
6163 rex.in.secdesc_ctr = &secdesc_ctr;
6164 rex.in.userlevel_ctr = &userlevel_ctr;
6165 rex.out.handle = &handle;
6167 r.in.server = NULL;
6168 r.in.info_ctr = &info_ctr;
6169 r.in.devmode_ctr = &devmode_ctr;
6170 r.in.secdesc_ctr = &secdesc_ctr;
6171 r.out.handle = &handle;
6173 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6174 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6175 "failed to add printer");
6176 result = ex ? rex.out.result : r.out.result;
6177 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6178 "unexpected result code");
6180 info1.name = printername;
6181 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6183 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6184 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6185 "failed to add printer");
6186 result = ex ? rex.out.result : r.out.result;
6187 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6188 "unexpected result code");
6190 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6191 better do a real check to see the printer is really there */
6193 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6194 PRINTER_ENUM_NETWORK, 1,
6195 printername,
6196 &found),
6197 "failed to enum printers");
6199 torture_assert(tctx, found, "failed to find newly added printer");
6201 info1.flags = 0;
6203 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6204 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6205 "failed to add printer");
6206 result = ex ? rex.out.result : r.out.result;
6207 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6208 "unexpected result code");
6210 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6211 better do a real check to see the printer has really been removed
6212 from the well known printer list */
6214 found = false;
6216 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6217 PRINTER_ENUM_NETWORK, 1,
6218 printername,
6219 &found),
6220 "failed to enum printers");
6221 #if 0
6222 torture_assert(tctx, !found, "printer still in well known printer list");
6223 #endif
6224 return true;
6227 static bool test_AddPrinter_normal(struct torture_context *tctx,
6228 struct dcerpc_pipe *p,
6229 struct policy_handle *handle_p,
6230 const char *printername,
6231 const char *drivername,
6232 const char *portname,
6233 struct spoolss_DeviceMode *devmode,
6234 bool ex)
6236 WERROR result;
6237 struct spoolss_AddPrinter r;
6238 struct spoolss_AddPrinterEx rex;
6239 struct spoolss_SetPrinterInfoCtr info_ctr;
6240 struct spoolss_SetPrinterInfo2 info2;
6241 struct spoolss_DevmodeContainer devmode_ctr;
6242 struct sec_desc_buf secdesc_ctr;
6243 struct spoolss_UserLevelCtr userlevel_ctr;
6244 struct policy_handle handle;
6245 bool found = false;
6246 bool existing_printer_deleted = false;
6247 struct dcerpc_binding_handle *b = p->binding_handle;
6249 ZERO_STRUCT(devmode_ctr);
6250 ZERO_STRUCT(secdesc_ctr);
6251 ZERO_STRUCT(userlevel_ctr);
6253 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6254 ex ? "Ex":"", printername);
6256 devmode_ctr.devmode = devmode;
6258 userlevel_ctr.level = 1;
6260 rex.in.server = NULL;
6261 rex.in.info_ctr = &info_ctr;
6262 rex.in.devmode_ctr = &devmode_ctr;
6263 rex.in.secdesc_ctr = &secdesc_ctr;
6264 rex.in.userlevel_ctr = &userlevel_ctr;
6265 rex.out.handle = &handle;
6267 r.in.server = NULL;
6268 r.in.info_ctr = &info_ctr;
6269 r.in.devmode_ctr = &devmode_ctr;
6270 r.in.secdesc_ctr = &secdesc_ctr;
6271 r.out.handle = &handle;
6273 again:
6275 /* try to add printer to printer list (level 2) */
6277 ZERO_STRUCT(info2);
6279 info_ctr.info.info2 = &info2;
6280 info_ctr.level = 2;
6282 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6283 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6284 "failed to add printer");
6285 result = ex ? rex.out.result : r.out.result;
6286 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6287 "unexpected result code");
6289 info2.printername = printername;
6291 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6292 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6293 "failed to add printer");
6294 result = ex ? rex.out.result : r.out.result;
6296 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6297 struct policy_handle printer_handle;
6299 if (existing_printer_deleted) {
6300 torture_fail(tctx, "already deleted printer still existing?");
6303 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6304 "failed to open printer handle");
6306 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6307 "failed to delete printer");
6309 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6310 "failed to close server handle");
6312 existing_printer_deleted = true;
6314 goto again;
6317 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6318 "unexpected result code");
6320 info2.portname = portname;
6322 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6323 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6324 "failed to add printer");
6325 result = ex ? rex.out.result : r.out.result;
6326 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6327 "unexpected result code");
6329 info2.drivername = drivername;
6331 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6332 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6333 "failed to add printer");
6334 result = ex ? rex.out.result : r.out.result;
6336 /* w2k8r2 allows to add printer w/o defining printprocessor */
6338 if (!W_ERROR_IS_OK(result)) {
6339 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6340 "unexpected result code");
6342 info2.printprocessor = "winprint";
6344 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6345 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6346 "failed to add printer");
6347 result = ex ? rex.out.result : r.out.result;
6348 torture_assert_werr_ok(tctx, result,
6349 "failed to add printer");
6352 *handle_p = handle;
6354 /* we are paranoid, really check if the printer is there now */
6356 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6357 PRINTER_ENUM_LOCAL, 1,
6358 printername,
6359 &found),
6360 "failed to enum printers");
6361 torture_assert(tctx, found, "failed to find newly added printer");
6363 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6364 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6365 "failed to add printer");
6366 result = ex ? rex.out.result : r.out.result;
6367 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6368 "unexpected result code");
6370 return true;
6373 static bool test_printer_info(struct torture_context *tctx,
6374 struct dcerpc_binding_handle *b,
6375 struct policy_handle *handle)
6377 bool ret = true;
6379 if (torture_setting_bool(tctx, "samba3", false)) {
6380 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6383 if (!test_PrinterInfo(tctx, b, handle)) {
6384 ret = false;
6387 if (!test_SetPrinter_errors(tctx, b, handle)) {
6388 ret = false;
6391 return ret;
6394 static bool test_EnumPrinterKey(struct torture_context *tctx,
6395 struct dcerpc_binding_handle *b,
6396 struct policy_handle *handle,
6397 const char *key_name,
6398 const char ***array)
6400 struct spoolss_EnumPrinterKey r;
6401 uint32_t needed = 0;
6402 union spoolss_KeyNames key_buffer;
6403 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6404 uint32_t _ndr_size;
6405 int i;
6407 r.in.handle = handle;
6408 r.in.key_name = key_name;
6409 r.out.key_buffer = &key_buffer;
6410 r.out.needed = &needed;
6411 r.out._ndr_size = &_ndr_size;
6413 for (i=0; i < ARRAY_SIZE(offered); i++) {
6415 if (offered[i] < 0 && needed) {
6416 if (needed <= 4) {
6417 continue;
6419 r.in.offered = needed + offered[i];
6420 } else {
6421 r.in.offered = offered[i];
6424 ZERO_STRUCT(key_buffer);
6426 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6428 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6429 "failed to call EnumPrinterKey");
6430 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6432 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6433 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6434 _ndr_size, r.in.offered/2));
6436 r.in.offered = needed;
6437 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6438 "failed to call EnumPrinterKey");
6441 if (offered[i] > 0) {
6442 torture_assert_werr_ok(tctx, r.out.result,
6443 "failed to call EnumPrinterKey");
6446 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6447 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6448 _ndr_size, r.in.offered/2));
6450 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6451 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6453 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6454 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6456 if (key_buffer.string_array) {
6457 uint32_t calc_needed = 0;
6458 int s;
6459 for (s=0; key_buffer.string_array[s]; s++) {
6460 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6462 if (!key_buffer.string_array[0]) {
6463 calc_needed += 2;
6465 calc_needed += 2;
6467 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6468 "EnumPrinterKey unexpected size");
6472 if (array) {
6473 *array = key_buffer.string_array;
6476 return true;
6479 bool test_printer_keys(struct torture_context *tctx,
6480 struct dcerpc_binding_handle *b,
6481 struct policy_handle *handle)
6483 const char **key_array = NULL;
6484 int i;
6486 torture_comment(tctx, "Testing Printer Keys\n");
6488 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6489 "failed to call test_EnumPrinterKey");
6491 for (i=0; key_array && key_array[i]; i++) {
6492 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6493 "failed to call test_EnumPrinterKey");
6495 for (i=0; key_array && key_array[i]; i++) {
6496 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6497 "failed to call test_EnumPrinterDataEx");
6500 torture_comment(tctx, "Printer Keys test succeeded\n\n");
6502 return true;
6505 static bool test_one_printer(struct torture_context *tctx,
6506 struct dcerpc_pipe *p,
6507 struct policy_handle *handle,
6508 const char *name,
6509 const char *drivername,
6510 const char *environment,
6511 bool have_driver,
6512 struct spoolss_DeviceMode *devmode)
6514 bool ret = true;
6515 struct dcerpc_binding_handle *b = p->binding_handle;
6517 if (!test_PausePrinter(tctx, b, handle)) {
6518 ret = false;
6521 if (!test_DoPrintTest(tctx, b, handle)) {
6522 ret = false;
6525 if (!test_DoPrintTest_extended(tctx, b, handle)) {
6526 torture_comment(tctx, "extended printing test failed!\n");
6529 if (!test_ResumePrinter(tctx, b, handle)) {
6530 ret = false;
6533 if (!test_printer_info(tctx, b, handle)) {
6534 ret = false;
6537 if (!test_PrinterInfo_SD(tctx, b, handle)) {
6538 ret = false;
6541 if (!test_PrinterInfo_DevMode(tctx, p, handle, name, devmode)) {
6542 ret = false;
6545 if (!test_PrinterInfo_winreg(tctx, p, handle, name)) {
6546 ret = false;
6549 if (!test_ChangeID(tctx, p, handle)) {
6550 ret = false;
6553 if (!test_printer_keys(tctx, b, handle)) {
6554 ret = false;
6557 if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
6558 ret = false;
6561 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
6562 ret = false;
6565 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
6566 ret = false;
6569 if (!test_PrinterData_DsSpooler(tctx, p, handle, name)) {
6570 ret = false;
6573 if (have_driver) {
6574 if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
6575 ret = false;
6579 if (!test_printer_rename(tctx, p, handle, name)) {
6580 ret = false;
6583 return ret;
6586 static bool test_csetprinter(struct torture_context *tctx,
6587 struct dcerpc_pipe *p,
6588 struct policy_handle *handle,
6589 const char *printername,
6590 const char *drivername,
6591 const char *portname)
6593 union spoolss_PrinterInfo info;
6594 struct policy_handle new_handle, new_handle2;
6595 struct dcerpc_binding_handle *b = p->binding_handle;
6597 torture_comment(tctx, "Testing c_setprinter\n");
6599 torture_assert(tctx,
6600 test_GetPrinter_level(tctx, b, handle, 0, &info),
6601 "failed to get level 0 printer info");
6602 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6603 info.info0.c_setprinter);
6605 /* check if c_setprinter on 1st handle increases after a printer has
6606 * been added */
6608 torture_assert(tctx,
6609 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6610 "failed to add new printer");
6611 torture_assert(tctx,
6612 test_GetPrinter_level(tctx, b, handle, 0, &info),
6613 "failed to get level 0 printer info");
6614 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6615 info.info0.c_setprinter);
6617 /* check if c_setprinter on new handle increases after a printer has
6618 * been added */
6620 torture_assert(tctx,
6621 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6622 "failed to get level 0 printer info");
6623 torture_comment(tctx, "csetprinter on created handle: %d\n",
6624 info.info0.c_setprinter);
6626 /* open the new printer and check if c_setprinter increases */
6628 torture_assert(tctx,
6629 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6630 "failed to open created printer");
6631 torture_assert(tctx,
6632 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6633 "failed to get level 0 printer info");
6634 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6635 info.info0.c_setprinter);
6637 /* cleanup */
6639 torture_assert(tctx,
6640 test_ClosePrinter(tctx, b, &new_handle2),
6641 "failed to close printer");
6642 torture_assert(tctx,
6643 test_DeletePrinter(tctx, b, &new_handle),
6644 "failed to delete new printer");
6646 return true;
6649 static bool test_add_printer_args_with_driver(struct torture_context *tctx,
6650 struct dcerpc_pipe *p,
6651 struct torture_printer_context *t)
6653 bool ret = true;
6654 struct policy_handle handle;
6655 bool found = false;
6656 struct dcerpc_binding_handle *b = p->binding_handle;
6657 const char *printer_name = t->info2.printername;
6658 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6659 const char *port_name = t->info2.portname;
6660 const char *printer_name2 = talloc_asprintf(tctx, "%s2", printer_name);
6662 if (t->wellknown) {
6663 torture_assert(tctx,
6664 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
6665 "failed to add wellknown printer");
6666 } else {
6667 torture_assert(tctx,
6668 test_AddPrinter_normal(tctx, p, &handle, printer_name, driver_name, port_name, t->devmode, t->ex),
6669 "failed to add printer");
6672 if (!test_csetprinter(tctx, p, &handle, printer_name2, driver_name, port_name)) {
6673 ret = false;
6676 if (!test_one_printer(tctx, p, &handle, printer_name, driver_name, t->driver.remote.environment, t->have_driver, t->devmode)) {
6677 ret = false;
6680 if (!test_DeletePrinter(tctx, b, &handle)) {
6681 ret = false;
6684 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
6685 printer_name, &found)) {
6686 ret = false;
6689 torture_assert(tctx, !found, "deleted printer still there");
6691 return ret;
6694 static bool compose_local_driver_directory(struct torture_context *tctx,
6695 const char *environment,
6696 const char *local_dir,
6697 const char **path)
6699 char *p;
6701 p = strrchr(local_dir, '/');
6702 if (!p) {
6703 return NULL;
6705 p++;
6707 if (strequal(environment, "Windows x64")) {
6708 if (!strequal(p, "x64")) {
6709 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6711 } else if (strequal(environment, "Windows NT x86")) {
6712 if (!strequal(p, "i386")) {
6713 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6715 } else {
6716 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6719 return true;
6722 static bool test_add_printer_args(struct torture_context *tctx,
6723 struct dcerpc_pipe *p,
6724 struct torture_printer_context *t)
6726 bool ret = true;
6727 struct dcerpc_binding_handle *b = p->binding_handle;
6728 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6730 if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
6731 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
6734 torture_assert(tctx,
6735 fillup_printserver_info(tctx, p, &t->driver),
6736 "failed to fillup printserver info");
6738 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6740 torture_assert(tctx,
6741 compose_local_driver_directory(tctx, t->driver.remote.environment,
6742 t->driver.local.driver_directory,
6743 &t->driver.local.driver_directory),
6744 "failed to compose local driver directory");
6746 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6747 t->have_driver = true;
6748 goto try_run;
6751 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6752 t->info2.drivername, t->driver.remote.environment);
6753 torture_comment(tctx, "trying to upload own driver\n");
6755 if (!directory_exist(t->driver.local.driver_directory)) {
6756 torture_warning(tctx, "no local driver is available!");
6757 t->have_driver = false;
6758 goto try_run;
6761 torture_assert(tctx,
6762 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6763 "failed to upload printer driver");
6765 torture_assert(tctx,
6766 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
6767 "failed to add driver");
6769 t->added_driver = true;
6770 t->have_driver = true;
6772 try_run:
6773 ret = test_add_printer_args_with_driver(tctx, p, t);
6775 if (t->added_driver) {
6776 torture_assert(tctx,
6777 remove_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6778 "failed to remove printer driver");
6781 return ret;
6784 static bool test_add_printer(struct torture_context *tctx,
6785 struct dcerpc_pipe *p,
6786 void *private_data)
6788 struct torture_printer_context *t =
6789 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6791 t->ex = false;
6792 t->wellknown = false;
6793 t->info2.printername = TORTURE_PRINTER;
6795 return test_add_printer_args(tctx, p, t);
6798 static bool test_add_printer_wellknown(struct torture_context *tctx,
6799 struct dcerpc_pipe *p,
6800 void *private_data)
6802 struct torture_printer_context *t =
6803 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6805 t->ex = false;
6806 t->wellknown = true;
6807 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
6808 t->devmode = NULL;
6810 return test_add_printer_args(tctx, p, t);
6813 static bool test_add_printer_ex(struct torture_context *tctx,
6814 struct dcerpc_pipe *p,
6815 void *private_data)
6817 struct torture_printer_context *t =
6818 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6820 t->ex = true;
6821 t->wellknown = false;
6822 t->info2.printername = TORTURE_PRINTER_EX;
6823 t->devmode = NULL;
6825 return test_add_printer_args(tctx, p, t);
6828 static bool test_add_printer_ex_wellknown(struct torture_context *tctx,
6829 struct dcerpc_pipe *p,
6830 void *private_data)
6832 struct torture_printer_context *t =
6833 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6835 t->ex = true;
6836 t->wellknown = true;
6837 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
6838 t->devmode = NULL;
6840 return test_add_printer_args(tctx, p, t);
6843 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6844 const char *devicename)
6846 struct spoolss_DeviceMode *r;
6848 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6849 if (r == NULL) {
6850 return NULL;
6853 r->devicename = talloc_strdup(r, devicename);
6854 r->specversion = DMSPEC_NT4_AND_ABOVE;
6855 r->driverversion = 0x0600;
6856 r->size = 0x00dc;
6857 r->__driverextra_length = 0;
6858 r->fields = DEVMODE_FORMNAME |
6859 DEVMODE_TTOPTION |
6860 DEVMODE_PRINTQUALITY |
6861 DEVMODE_DEFAULTSOURCE |
6862 DEVMODE_COPIES |
6863 DEVMODE_SCALE |
6864 DEVMODE_PAPERSIZE |
6865 DEVMODE_ORIENTATION;
6866 r->orientation = DMORIENT_PORTRAIT;
6867 r->papersize = DMPAPER_LETTER;
6868 r->paperlength = 0;
6869 r->paperwidth = 0;
6870 r->scale = 100;
6871 r->copies = 55;
6872 r->defaultsource = DMBIN_FORMSOURCE;
6873 r->printquality = DMRES_HIGH;
6874 r->color = DMRES_MONOCHROME;
6875 r->duplex = DMDUP_SIMPLEX;
6876 r->yresolution = 0;
6877 r->ttoption = DMTT_SUBDEV;
6878 r->collate = DMCOLLATE_FALSE;
6879 r->formname = talloc_strdup(r, "Letter");
6881 return r;
6884 static bool test_add_printer_with_devmode(struct torture_context *tctx,
6885 struct dcerpc_pipe *p,
6886 void *private_data)
6888 struct torture_printer_context *t =
6889 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6891 t->ex = true;
6892 t->wellknown = false;
6893 t->info2.printername = TORTURE_PRINTER_EX;
6894 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
6896 return test_add_printer_args(tctx, p, t);
6899 static bool test_architecture_buffer(struct torture_context *tctx,
6900 void *private_data)
6902 struct test_spoolss_context *ctx =
6903 talloc_get_type_abort(private_data, struct test_spoolss_context);
6905 struct spoolss_OpenPrinterEx r;
6906 struct spoolss_UserLevel1 u1;
6907 struct policy_handle handle;
6908 uint32_t architectures[] = {
6909 PROCESSOR_ARCHITECTURE_INTEL,
6910 PROCESSOR_ARCHITECTURE_IA64,
6911 PROCESSOR_ARCHITECTURE_AMD64
6913 uint32_t needed[3];
6914 int i;
6915 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6916 struct dcerpc_binding_handle *b = p->binding_handle;
6918 for (i=0; i < ARRAY_SIZE(architectures); i++) {
6920 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6922 u1.size = 0;
6923 u1.client = NULL;
6924 u1.user = NULL;
6925 u1.build = 0;
6926 u1.major = 3;
6927 u1.minor = 0;
6928 u1.processor = architectures[i];
6930 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6931 r.in.datatype = NULL;
6932 r.in.devmode_ctr.devmode= NULL;
6933 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6934 r.in.level = 1;
6935 r.in.userlevel.level1 = &u1;
6936 r.out.handle = &handle;
6938 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6939 torture_assert_werr_ok(tctx, r.out.result, "");
6942 struct spoolss_EnumPrinters e;
6943 uint32_t count;
6944 union spoolss_PrinterInfo *info;
6946 e.in.flags = PRINTER_ENUM_LOCAL;
6947 e.in.server = NULL;
6948 e.in.level = 2;
6949 e.in.buffer = NULL;
6950 e.in.offered = 0;
6951 e.out.count = &count;
6952 e.out.info = &info;
6953 e.out.needed = &needed[i];
6955 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6956 #if 0
6957 torture_comment(tctx, "needed was %d\n", needed[i]);
6958 #endif
6961 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6964 for (i=1; i < ARRAY_SIZE(architectures); i++) {
6965 if (needed[i-1] != needed[i]) {
6966 torture_fail(tctx,
6967 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6968 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6972 return true;
6975 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
6976 void *private_data)
6978 struct test_spoolss_context *ctx =
6979 talloc_get_type_abort(private_data, struct test_spoolss_context);
6980 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6981 struct dcerpc_binding_handle *b = p->binding_handle;
6983 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
6986 static bool test_PrintServer_Forms(struct torture_context *tctx,
6987 void *private_data)
6989 struct test_spoolss_context *ctx =
6990 talloc_get_type_abort(private_data, struct test_spoolss_context);
6991 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6992 struct dcerpc_binding_handle *b = p->binding_handle;
6994 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
6997 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
6998 void *private_data)
7000 struct test_spoolss_context *ctx =
7001 talloc_get_type_abort(private_data, struct test_spoolss_context);
7002 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7003 struct dcerpc_binding_handle *b = p->binding_handle;
7005 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7008 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7010 NTSTATUS status;
7012 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7014 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7016 torture_assert(tctx,
7017 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7018 "failed to open printserver");
7019 torture_assert(tctx,
7020 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7021 "failed to get environment");
7023 return true;
7026 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7028 struct test_spoolss_context *t;
7030 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7032 return torture_rpc_spoolss_setup_common(tctx, t);
7035 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7037 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7039 return true;
7042 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7044 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7045 bool ret;
7047 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7048 talloc_free(t);
7050 return ret;
7053 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7055 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
7056 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
7058 torture_tcase_set_fixture(tcase,
7059 torture_rpc_spoolss_setup,
7060 torture_rpc_spoolss_teardown);
7062 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7063 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7064 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7065 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7066 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7067 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7068 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7069 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7070 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7071 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7072 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7073 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7074 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7075 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7076 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7077 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7078 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7079 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7080 torture_tcase_add_simple_test(tcase, "printprocessors_winreg", test_print_processors_winreg);
7082 return suite;
7085 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7087 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
7089 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
7090 "printer", &ndr_table_spoolss);
7092 struct torture_printer_context *t;
7094 t = talloc_zero(mem_ctx, struct torture_printer_context);
7096 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7097 t->driver.info8.driver_name = TORTURE_DRIVER;
7098 t->driver.info8.driver_path = "pscript5.dll";
7099 t->driver.info8.data_file = "cups6.ppd";
7100 t->driver.info8.config_file = "ps5ui.dll";
7101 t->driver.info8.help_file = "pscript.hlp";
7102 t->driver.info8.default_datatype = "RAW";
7103 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7104 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7105 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7106 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7107 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7108 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7109 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7110 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7111 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7112 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7114 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7116 t->info2.drivername = "Microsoft XPS Document Writer";
7117 t->info2.portname = "LPT1:";
7119 torture_rpc_tcase_add_test_ex(tcase, "add_printer", test_add_printer, t);
7120 torture_rpc_tcase_add_test_ex(tcase, "add_printer_wellknown", test_add_printer_wellknown, t);
7121 torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex", test_add_printer_ex, t);
7122 torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex_wellknown", test_add_printer_ex_wellknown, t);
7124 torture_rpc_tcase_add_test_ex(tcase, "add_printer_with_devmode", test_add_printer_with_devmode, t);
7126 return suite;
7129 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7130 struct dcerpc_binding_handle *b,
7131 const char *server,
7132 const char *environment,
7133 const char **dir_p)
7135 struct spoolss_GetPrinterDriverDirectory r;
7136 uint32_t needed;
7138 r.in.server = server;
7139 r.in.environment = environment;
7140 r.in.level = 1;
7141 r.in.buffer = NULL;
7142 r.in.offered = 0;
7143 r.out.needed = &needed;
7145 torture_assert_ntstatus_ok(tctx,
7146 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7147 "failed to query driver directory");
7149 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7150 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7151 r.in.buffer = &blob;
7152 r.in.offered = needed;
7154 torture_assert_ntstatus_ok(tctx,
7155 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7156 "failed to query driver directory");
7159 torture_assert_werr_ok(tctx, r.out.result,
7160 "failed to query driver directory");
7162 if (dir_p) {
7163 *dir_p = r.out.info->info1.directory_name;
7166 return true;
7169 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7171 if (info_ctr == NULL) {
7172 return NULL;
7175 switch (info_ctr->level) {
7176 case 1:
7177 return info_ctr->info.info1->driver_name;
7178 case 2:
7179 return info_ctr->info.info2->driver_name;
7180 case 3:
7181 return info_ctr->info.info3->driver_name;
7182 case 4:
7183 return info_ctr->info.info4->driver_name;
7184 case 6:
7185 return info_ctr->info.info6->driver_name;
7186 case 8:
7187 return info_ctr->info.info8->driver_name;
7188 default:
7189 return NULL;
7193 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7195 if (info_ctr == NULL) {
7196 return NULL;
7199 switch (info_ctr->level) {
7200 case 2:
7201 return info_ctr->info.info2->architecture;
7202 case 3:
7203 return info_ctr->info.info3->architecture;
7204 case 4:
7205 return info_ctr->info.info4->architecture;
7206 case 6:
7207 return info_ctr->info.info6->architecture;
7208 case 8:
7209 return info_ctr->info.info8->architecture;
7210 default:
7211 return NULL;
7216 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7217 struct dcerpc_binding_handle *b,
7218 const char *servername,
7219 struct spoolss_AddDriverInfoCtr *info_ctr,
7220 WERROR expected_result)
7222 struct spoolss_AddPrinterDriver r;
7223 const char *drivername = get_driver_from_info(info_ctr);
7224 const char *environment = get_environment_from_info(info_ctr);
7226 r.in.servername = servername;
7227 r.in.info_ctr = info_ctr;
7229 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
7230 drivername, info_ctr->level, environment);
7232 torture_assert_ntstatus_ok(tctx,
7233 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
7234 "spoolss_AddPrinterDriver failed");
7235 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7236 "spoolss_AddPrinterDriver failed with unexpected result");
7238 return true;
7242 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
7243 struct dcerpc_binding_handle *b,
7244 const char *servername,
7245 struct spoolss_AddDriverInfoCtr *info_ctr,
7246 uint32_t flags,
7247 WERROR expected_result)
7249 struct spoolss_AddPrinterDriverEx r;
7250 const char *drivername = get_driver_from_info(info_ctr);
7251 const char *environment = get_environment_from_info(info_ctr);
7253 r.in.servername = servername;
7254 r.in.info_ctr = info_ctr;
7255 r.in.flags = flags;
7257 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
7258 drivername, info_ctr->level, environment);
7260 torture_assert_ntstatus_ok(tctx,
7261 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7262 "AddPrinterDriverEx failed");
7263 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7264 "AddPrinterDriverEx failed with unexpected result");
7266 return true;
7269 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7270 struct dcerpc_binding_handle *b,
7271 const char *server_name,
7272 struct spoolss_AddDriverInfo8 *r,
7273 uint32_t flags,
7274 bool ex)
7276 struct spoolss_AddDriverInfoCtr info_ctr;
7277 struct spoolss_AddDriverInfo1 info1;
7279 ZERO_STRUCT(info1);
7281 info_ctr.level = 1;
7282 info_ctr.info.info1 = &info1;
7284 if (ex) {
7285 torture_assert(tctx,
7286 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7287 "failed to test AddPrinterDriverEx level 1");
7288 } else {
7289 torture_assert(tctx,
7290 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7291 "failed to test AddPrinterDriver level 1");
7294 info1.driver_name = r->driver_name;
7296 if (ex) {
7297 torture_assert(tctx,
7298 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7299 "failed to test AddPrinterDriverEx level 1");
7300 } else {
7301 torture_assert(tctx,
7302 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7303 "failed to test AddPrinterDriver level 1");
7306 return true;
7309 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7310 struct dcerpc_binding_handle *b,
7311 const char *server_name,
7312 struct spoolss_AddDriverInfo8 *r,
7313 uint32_t flags,
7314 bool ex)
7316 struct spoolss_AddDriverInfoCtr info_ctr;
7317 struct spoolss_AddDriverInfo2 info2;
7319 ZERO_STRUCT(info2);
7321 info_ctr.level = 2;
7322 info_ctr.info.info2 = &info2;
7324 if (ex) {
7325 torture_assert(tctx,
7326 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7327 "failed to test AddPrinterDriverEx level 2");
7328 } else {
7329 torture_assert(tctx,
7330 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7331 "failed to test AddPrinterDriver level 2");
7334 info2.driver_name = r->driver_name;
7336 if (ex) {
7337 torture_assert(tctx,
7338 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7339 "failed to test AddPrinterDriverEx level 2");
7340 } else {
7341 torture_assert(tctx,
7342 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7343 "failed to test AddPrinterDriver level 2");
7346 info2.version = r->version;
7348 if (ex) {
7349 torture_assert(tctx,
7350 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7351 "failed to test AddPrinterDriverEx level 2");
7352 } else {
7353 torture_assert(tctx,
7354 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7355 "failed to test AddPrinterDriver level 2");
7358 info2.architecture = r->architecture;
7360 if (ex) {
7361 torture_assert(tctx,
7362 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7363 "failed to test AddPrinterDriverEx level 2");
7364 } else {
7365 torture_assert(tctx,
7366 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7367 "failed to test AddPrinterDriver level 2");
7370 info2.driver_path = r->driver_path;
7372 if (ex) {
7373 torture_assert(tctx,
7374 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7375 "failed to test AddPrinterDriverEx level 2");
7376 } else {
7377 torture_assert(tctx,
7378 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7379 "failed to test AddPrinterDriver level 2");
7382 info2.data_file = r->data_file;
7384 if (ex) {
7385 torture_assert(tctx,
7386 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7387 "failed to test AddPrinterDriverEx level 2");
7388 } else {
7389 torture_assert(tctx,
7390 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7391 "failed to test AddPrinterDriver level 2");
7394 info2.config_file = r->config_file;
7396 if (ex) {
7397 torture_assert(tctx,
7398 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7399 "failed to test AddPrinterDriverEx");
7402 if (ex) {
7403 torture_assert(tctx,
7404 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7405 "failed to test AddPrinterDriverEx level 2");
7406 } else {
7407 torture_assert(tctx,
7408 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7409 "failed to test AddPrinterDriver level 2");
7412 torture_assert(tctx,
7413 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7414 "failed to find added printer driver");
7416 return true;
7419 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7420 struct dcerpc_binding_handle *b,
7421 const char *server_name,
7422 struct spoolss_AddDriverInfo8 *r,
7423 uint32_t flags,
7424 bool ex)
7426 struct spoolss_AddDriverInfoCtr info_ctr;
7427 struct spoolss_AddDriverInfo3 info3;
7429 info3.driver_name = r->driver_name;
7430 info3.version = r->version;
7431 info3.architecture = r->architecture;
7432 info3.driver_path = r->driver_path;
7433 info3.data_file = r->data_file;
7434 info3.config_file = r->config_file;
7435 info3.help_file = r->help_file;
7436 info3.monitor_name = r->monitor_name;
7437 info3.default_datatype = r->default_datatype;
7438 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7439 info3.dependent_files = r->dependent_files;
7441 info_ctr.level = 3;
7442 info_ctr.info.info3 = &info3;
7444 if (ex) {
7445 torture_assert(tctx,
7446 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7447 "failed to test AddPrinterDriverEx level 3");
7448 } else {
7449 torture_assert(tctx,
7450 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7451 "failed to test AddPrinterDriver level 3");
7454 torture_assert(tctx,
7455 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7456 "failed to find added printer driver");
7458 return true;
7461 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7462 struct dcerpc_binding_handle *b,
7463 const char *server_name,
7464 struct spoolss_AddDriverInfo8 *r,
7465 uint32_t flags,
7466 bool ex)
7468 struct spoolss_AddDriverInfoCtr info_ctr;
7469 struct spoolss_AddDriverInfo4 info4;
7471 info4.version = r->version;
7472 info4.driver_name = r->driver_name;
7473 info4.architecture = r->architecture;
7474 info4.driver_path = r->driver_path;
7475 info4.data_file = r->data_file;
7476 info4.config_file = r->config_file;
7477 info4.help_file = r->help_file;
7478 info4.monitor_name = r->monitor_name;
7479 info4.default_datatype = r->default_datatype;
7480 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7481 info4.dependent_files = r->dependent_files;
7482 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7483 info4.previous_names = r->previous_names;
7485 info_ctr.level = 4;
7486 info_ctr.info.info4 = &info4;
7488 if (ex) {
7489 torture_assert(tctx,
7490 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7491 "failed to test AddPrinterDriverEx level 4");
7492 } else {
7493 torture_assert(tctx,
7494 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7495 "failed to test AddPrinterDriver level 4");
7498 torture_assert(tctx,
7499 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7500 "failed to find added printer driver");
7502 return true;
7505 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7506 struct dcerpc_binding_handle *b,
7507 const char *server_name,
7508 struct spoolss_AddDriverInfo8 *r,
7509 uint32_t flags,
7510 bool ex)
7512 struct spoolss_AddDriverInfoCtr info_ctr;
7513 struct spoolss_AddDriverInfo6 info6;
7515 info6.version = r->version;
7516 info6.driver_name = r->driver_name;
7517 info6.architecture = r->architecture;
7518 info6.driver_path = r->driver_path;
7519 info6.data_file = r->data_file;
7520 info6.config_file = r->config_file;
7521 info6.help_file = r->help_file;
7522 info6.monitor_name = r->monitor_name;
7523 info6.default_datatype = r->default_datatype;
7524 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7525 info6.dependent_files = r->dependent_files;
7526 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7527 info6.previous_names = r->previous_names;
7528 info6.driver_date = r->driver_date;
7529 info6.driver_version = r->driver_version;
7530 info6.manufacturer_name = r->manufacturer_name;
7531 info6.manufacturer_url = r->manufacturer_url;
7532 info6.hardware_id = r->hardware_id;
7533 info6.provider = r->provider;
7535 info_ctr.level = 6;
7536 info_ctr.info.info6 = &info6;
7538 if (ex) {
7539 torture_assert(tctx,
7540 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7541 "failed to test AddPrinterDriverEx level 6");
7542 } else {
7543 torture_assert(tctx,
7544 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7545 "failed to test AddPrinterDriver level 6");
7548 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7550 if (!ex) {
7551 return true;
7554 torture_assert(tctx,
7555 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7556 "failed to find added printer driver");
7558 return true;
7561 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7562 struct dcerpc_binding_handle *b,
7563 const char *server_name,
7564 struct spoolss_AddDriverInfo8 *r,
7565 uint32_t flags,
7566 bool ex)
7568 struct spoolss_AddDriverInfoCtr info_ctr;
7570 info_ctr.level = 8;
7571 info_ctr.info.info8 = r;
7573 if (ex) {
7574 torture_assert(tctx,
7575 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7576 "failed to test AddPrinterDriverEx level 8");
7577 } else {
7578 torture_assert(tctx,
7579 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7580 "failed to test AddPrinterDriver level 8");
7583 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7585 if (!ex) {
7586 return true;
7589 torture_assert(tctx,
7590 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7591 "failed to find added printer driver");
7593 return true;
7596 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7597 struct dcerpc_binding_handle *b,
7598 const char *server,
7599 const char *driver,
7600 const char *environment,
7601 WERROR expected_result)
7603 struct spoolss_DeletePrinterDriver r;
7605 r.in.server = server;
7606 r.in.architecture = environment;
7607 r.in.driver = driver;
7609 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7611 torture_assert_ntstatus_ok(tctx,
7612 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7613 "DeletePrinterDriver failed");
7614 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7615 "DeletePrinterDriver failed with unexpected result");
7617 return true;
7620 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7621 struct dcerpc_binding_handle *b,
7622 const char *server,
7623 const char *driver,
7624 const char *environment,
7625 uint32_t delete_flags,
7626 uint32_t version,
7627 WERROR expected_result)
7629 struct spoolss_DeletePrinterDriverEx r;
7631 r.in.server = server;
7632 r.in.architecture = environment;
7633 r.in.driver = driver;
7634 r.in.delete_flags = delete_flags;
7635 r.in.version = version;
7637 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7639 torture_assert_ntstatus_ok(tctx,
7640 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7641 "DeletePrinterDriverEx failed");
7642 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7643 "DeletePrinterDriverEx failed with unexpected result");
7645 return true;
7648 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7649 struct dcerpc_binding_handle *b,
7650 const char *server_name,
7651 const char *driver,
7652 const char *environment)
7654 torture_assert(tctx,
7655 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7656 "failed to delete driver");
7658 torture_assert(tctx,
7659 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
7660 "failed to delete driver");
7662 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7663 torture_fail(tctx, "deleted driver still enumerated");
7666 torture_assert(tctx,
7667 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
7668 "2nd delete failed");
7670 return true;
7673 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7674 struct dcerpc_binding_handle *b,
7675 const char *server_name,
7676 const char *driver,
7677 const char *environment,
7678 uint32_t delete_flags,
7679 uint32_t version)
7681 torture_assert(tctx,
7682 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7683 "failed to delete driver");
7685 torture_assert(tctx,
7686 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7687 "failed to delete driver");
7689 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7690 torture_fail(tctx, "deleted driver still enumerated");
7693 torture_assert(tctx,
7694 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7695 "2nd delete failed");
7697 return true;
7700 static bool test_PrinterDriver_args(struct torture_context *tctx,
7701 struct dcerpc_binding_handle *b,
7702 const char *server_name,
7703 uint32_t level,
7704 struct spoolss_AddDriverInfo8 *r,
7705 uint32_t add_flags,
7706 uint32_t delete_flags,
7707 uint32_t delete_version,
7708 bool ex)
7710 bool ret = true;
7712 switch (level) {
7713 case 1:
7714 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7715 break;
7716 case 2:
7717 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7718 break;
7719 case 3:
7720 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7721 break;
7722 case 4:
7723 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7724 break;
7725 case 6:
7726 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7727 break;
7728 case 8:
7729 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7730 break;
7731 default:
7732 return false;
7735 if (ret == false) {
7736 return ret;
7739 if (level == 1) {
7740 return ret;
7743 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7745 if (!ex && (level == 6 || level == 8)) {
7746 return ret;
7749 if (ex) {
7750 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
7751 } else {
7752 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
7756 static bool fillup_printserver_info(struct torture_context *tctx,
7757 struct dcerpc_pipe *p,
7758 struct torture_driver_context *d)
7760 struct policy_handle server_handle;
7761 struct dcerpc_binding_handle *b = p->binding_handle;
7762 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7764 torture_assert(tctx,
7765 test_OpenPrinter_server(tctx, p, &server_handle),
7766 "failed to open printserver");
7767 torture_assert(tctx,
7768 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
7769 "failed to get environment");
7770 torture_assert(tctx,
7771 test_ClosePrinter(tctx, b, &server_handle),
7772 "failed to close printserver");
7774 torture_assert(tctx,
7775 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
7776 d->local.environment ? d->local.environment : d->remote.environment,
7777 &d->remote.driver_directory),
7778 "failed to get driver directory");
7780 return true;
7783 static const char *driver_directory_dir(const char *driver_directory)
7785 char *p;
7787 p = strrchr(driver_directory, '\\');
7788 if (p) {
7789 return p+1;
7792 return NULL;
7795 static const char *driver_directory_share(struct torture_context *tctx,
7796 const char *driver_directory)
7798 const char *p;
7799 char *tok;
7801 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
7802 driver_directory += 2;
7805 p = talloc_strdup(tctx, driver_directory);
7807 torture_assert(tctx,
7808 next_token_talloc(tctx, &p, &tok, "\\"),
7809 "cannot explode uri");
7810 torture_assert(tctx,
7811 next_token_talloc(tctx, &p, &tok, "\\"),
7812 "cannot explode uri");
7814 return tok;
7817 static bool upload_printer_driver_file(struct torture_context *tctx,
7818 struct smbcli_state *cli,
7819 struct torture_driver_context *d,
7820 const char *file_name)
7822 XFILE *f;
7823 int fnum;
7824 uint8_t *buf;
7825 int maxwrite = 64512;
7826 off_t nread = 0;
7827 size_t start = 0;
7828 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7829 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
7830 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7832 if (!file_name) {
7833 return true;
7836 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
7838 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
7839 if (fnum == -1) {
7840 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
7843 f = x_fopen(local_name, O_RDONLY, 0);
7844 if (f == NULL) {
7845 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
7848 buf = talloc_array(tctx, uint8_t, maxwrite);
7849 if (!buf) {
7850 return false;
7853 while (!x_feof(f)) {
7854 int n = maxwrite;
7855 int ret;
7857 if ((n = x_fread(buf, 1, n, f)) < 1) {
7858 if((n == 0) && x_feof(f))
7859 break; /* Empty local file. */
7861 torture_warning(tctx,
7862 "failed to read file: %s\n", strerror(errno));
7863 break;
7866 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
7868 if (n != ret) {
7869 torture_warning(tctx,
7870 "failed to write file: %s\n", smbcli_errstr(cli->tree));
7871 break;
7874 nread += n;
7877 x_fclose(f);
7879 torture_assert_ntstatus_ok(tctx,
7880 smbcli_close(cli->tree, fnum),
7881 "failed to close file");
7883 return true;
7886 static bool connect_printer_driver_share(struct torture_context *tctx,
7887 const char *server_name,
7888 const char *share_name,
7889 struct smbcli_state **cli)
7891 struct smbcli_options smb_options;
7892 struct smbcli_session_options smb_session_options;
7894 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
7895 share_name, server_name);
7897 lp_smbcli_options(tctx->lp_ctx, &smb_options);
7898 lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
7900 torture_assert_ntstatus_ok(tctx,
7901 smbcli_full_connection(tctx, cli, server_name,
7902 lp_smb_ports(tctx->lp_ctx),
7903 share_name, NULL,
7904 lp_socket_options(tctx->lp_ctx),
7905 cmdline_credentials,
7906 lp_resolve_context(tctx->lp_ctx),
7907 tctx->ev,
7908 &smb_options,
7909 &smb_session_options,
7910 lp_gensec_settings(tctx, tctx->lp_ctx)),
7911 "failed to open driver share");
7913 return true;
7916 static bool upload_printer_driver(struct torture_context *tctx,
7917 const char *server_name,
7918 struct torture_driver_context *d)
7920 struct smbcli_state *cli;
7921 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7922 int i;
7924 torture_assert(tctx,
7925 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7926 "failed to connect to driver share");
7928 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
7929 server_name, share_name);
7931 torture_assert(tctx,
7932 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7933 "failed to upload driver_path");
7934 torture_assert(tctx,
7935 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
7936 "failed to upload data_file");
7937 torture_assert(tctx,
7938 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
7939 "failed to upload config_file");
7940 torture_assert(tctx,
7941 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
7942 "failed to upload help_file");
7943 if (d->info8.dependent_files) {
7944 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7945 torture_assert(tctx,
7946 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7947 "failed to upload dependent_files");
7951 talloc_free(cli);
7953 return true;
7956 static bool remove_printer_driver_file(struct torture_context *tctx,
7957 struct smbcli_state *cli,
7958 struct torture_driver_context *d,
7959 const char *file_name)
7961 const char *remote_name;
7962 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7964 if (!file_name) {
7965 return true;
7968 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7970 torture_comment(tctx, "Removing %s\n", remote_name);
7972 torture_assert_ntstatus_ok(tctx,
7973 smbcli_unlink(cli->tree, remote_name),
7974 "failed to unlink");
7976 return true;
7979 static bool remove_printer_driver(struct torture_context *tctx,
7980 const char *server_name,
7981 struct torture_driver_context *d)
7983 struct smbcli_state *cli;
7984 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7985 int i;
7987 torture_assert(tctx,
7988 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7989 "failed to connect to driver share");
7991 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
7992 server_name, share_name);
7994 torture_assert(tctx,
7995 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7996 "failed to remove driver_path");
7997 torture_assert(tctx,
7998 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
7999 "failed to remove data_file");
8000 torture_assert(tctx,
8001 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8002 "failed to remove config_file");
8003 torture_assert(tctx,
8004 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8005 "failed to remove help_file");
8006 if (d->info8.dependent_files) {
8007 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8008 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8009 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8010 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8011 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8012 continue;
8014 torture_assert(tctx,
8015 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8016 "failed to remove dependent_files");
8020 talloc_free(cli);
8022 return true;
8026 static bool test_add_driver_arg(struct torture_context *tctx,
8027 struct dcerpc_pipe *p,
8028 struct torture_driver_context *d)
8030 bool ret = true;
8031 struct dcerpc_binding_handle *b = p->binding_handle;
8032 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8033 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8034 int i;
8035 struct spoolss_AddDriverInfo8 info8;
8036 uint32_t add_flags = APD_COPY_NEW_FILES;
8037 uint32_t delete_flags = 0;
8039 ZERO_STRUCT(info8);
8041 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8042 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8044 torture_assert(tctx,
8045 fillup_printserver_info(tctx, p, d),
8046 "failed to fillup printserver info");
8048 if (!directory_exist(d->local.driver_directory)) {
8049 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8052 torture_assert(tctx,
8053 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8054 "failed to upload printer driver");
8056 info8.version = d->info8.version;
8057 info8.driver_name = d->info8.driver_name;
8058 info8.architecture = d->local.environment;
8059 info8.driver_path = d->info8.driver_path;
8060 info8.data_file = d->info8.data_file;
8061 info8.config_file = d->info8.config_file;
8063 for (i=0; i < ARRAY_SIZE(levels); i++) {
8065 if (torture_setting_bool(tctx, "samba3", false)) {
8066 switch (levels[i]) {
8067 case 2:
8068 case 4:
8069 case 8:
8070 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8071 continue;
8072 default:
8073 break;
8077 torture_comment(tctx,
8078 "Testing PrinterDriver%s '%s' add & delete level %d\n",
8079 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8081 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8084 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8085 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8086 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8088 for (i=0; i < ARRAY_SIZE(levels); i++) {
8090 if (torture_setting_bool(tctx, "samba3", false)) {
8091 switch (levels[i]) {
8092 case 2:
8093 case 4:
8094 case 8:
8095 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8096 continue;
8097 default:
8098 break;
8103 torture_comment(tctx,
8104 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8105 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8107 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8110 torture_assert(tctx,
8111 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8112 "failed to remove printer driver");
8114 torture_comment(tctx, "\n");
8116 return ret;
8119 static bool test_add_driver_ex_64(struct torture_context *tctx,
8120 struct dcerpc_pipe *p,
8121 void *private_data)
8123 struct torture_driver_context *d =
8124 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8126 d->local.environment = talloc_strdup(d, "Windows x64");
8127 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8128 d->info8.driver_name = TORTURE_DRIVER_EX;
8129 d->ex = true;
8131 return test_add_driver_arg(tctx, p, d);
8134 static bool test_add_driver_ex_32(struct torture_context *tctx,
8135 struct dcerpc_pipe *p,
8136 void *private_data)
8138 struct torture_driver_context *d =
8139 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8141 d->local.environment = talloc_strdup(d, "Windows NT x86");
8142 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8143 d->info8.driver_name = TORTURE_DRIVER_EX;
8144 d->ex = true;
8146 return test_add_driver_arg(tctx, p, d);
8149 static bool test_add_driver_64(struct torture_context *tctx,
8150 struct dcerpc_pipe *p,
8151 void *private_data)
8153 struct torture_driver_context *d =
8154 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8156 d->local.environment = talloc_strdup(d, "Windows x64");
8157 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8158 d->info8.driver_name = TORTURE_DRIVER;
8159 d->ex = false;
8161 return test_add_driver_arg(tctx, p, d);
8164 static bool test_add_driver_32(struct torture_context *tctx,
8165 struct dcerpc_pipe *p,
8166 void *private_data)
8168 struct torture_driver_context *d =
8169 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8171 d->local.environment = talloc_strdup(d, "Windows NT x86");
8172 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8173 d->info8.driver_name = TORTURE_DRIVER;
8174 d->ex = false;
8176 return test_add_driver_arg(tctx, p, d);
8179 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
8181 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
8183 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
8184 "driver", &ndr_table_spoolss);
8185 struct torture_driver_context *t;
8187 t = talloc_zero(mem_ctx, struct torture_driver_context);
8189 t->info8.version = SPOOLSS_DRIVER_VERSION_200X;
8190 t->info8.driver_name = NULL;
8191 t->info8.architecture = NULL;
8192 t->info8.driver_path = talloc_strdup(t, "pscript5.dll");
8193 t->info8.data_file = talloc_strdup(t, "cups6.ppd");
8194 t->info8.config_file = talloc_strdup(t, "cupsui6.dll");
8196 torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
8197 torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
8199 torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
8200 torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
8202 return suite;