s4-smbtorture: fix DriverDate and DriverVersion comparison checks against w2k3.
[Samba.git] / source4 / torture / rpc / spoolss.c
blob31b7baf5da5d421f38ae404c9b1c18ee79f94fde
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"
40 #include "torture/ndr/ndr.h"
42 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
43 #define TORTURE_PRINTER "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX "torture_printer_ex"
46 #define TORTURE_DRIVER "torture_driver"
47 #define TORTURE_DRIVER_EX "torture_driver_ex"
48 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
49 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
50 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
51 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
53 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
54 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
55 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
56 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
57 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
58 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
60 struct test_spoolss_context {
61 struct dcerpc_pipe *spoolss_pipe;
63 /* server environment */
64 const char *environment;
66 /* print server handle */
67 struct policy_handle server_handle;
69 /* for EnumPorts */
70 uint32_t port_count[3];
71 union spoolss_PortInfo *ports[3];
73 /* for EnumPrinterDrivers */
74 uint32_t driver_count[8];
75 union spoolss_DriverInfo *drivers[8];
77 /* for EnumMonitors */
78 uint32_t monitor_count[3];
79 union spoolss_MonitorInfo *monitors[3];
81 /* for EnumPrintProcessors */
82 uint32_t print_processor_count[2];
83 union spoolss_PrintProcessorInfo *print_processors[2];
85 /* for EnumPrinters */
86 uint32_t printer_count[6];
87 union spoolss_PrinterInfo *printers[6];
90 struct torture_driver_context {
91 struct {
92 const char *driver_directory;
93 const char *environment;
94 } local;
95 struct {
96 const char *driver_directory;
97 const char *environment;
98 } remote;
99 struct spoolss_AddDriverInfo8 info8;
100 bool ex;
103 struct torture_printer_context {
104 struct dcerpc_pipe *spoolss_pipe;
105 struct spoolss_SetPrinterInfo2 info2;
106 struct torture_driver_context driver;
107 bool ex;
108 bool wellknown;
109 bool added_driver;
110 bool have_driver;
111 struct spoolss_DeviceMode *devmode;
112 struct policy_handle handle;
115 static bool upload_printer_driver(struct torture_context *tctx,
116 const char *server_name,
117 struct torture_driver_context *d);
118 static bool remove_printer_driver(struct torture_context *tctx,
119 const char *server_name,
120 struct torture_driver_context *d);
121 static bool fillup_printserver_info(struct torture_context *tctx,
122 struct dcerpc_pipe *p,
123 struct torture_driver_context *d);
124 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
125 struct dcerpc_binding_handle *b,
126 const char *server_name,
127 struct spoolss_AddDriverInfo8 *r,
128 uint32_t flags,
129 bool ex,
130 const char *remote_driver_dir);
132 #define COMPARE_STRING(tctx, c,r,e) \
133 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
135 /* not every compiler supports __typeof__() */
136 #if (__GNUC__ >= 3)
137 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
138 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
139 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
141 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
142 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
144 } while(0)
145 #else
146 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
147 #endif
149 #define COMPARE_UINT32(tctx, c, r, e) do {\
150 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
151 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
152 } while(0)
154 #define COMPARE_UINT64(tctx, c, r, e) do {\
155 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
156 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
157 } while(0)
160 #define COMPARE_NTTIME(tctx, c, r, e) do {\
161 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
162 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
163 } while(0)
165 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
166 int __i; \
167 if (!c.e && !r.e) { \
168 break; \
170 if (c.e && !r.e) { \
171 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
173 if (!c.e && r.e) { \
174 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
176 for (__i=0;c.e[__i] != NULL; __i++) { \
177 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
179 } while(0)
181 #define CHECK_ALIGN(size, n) do {\
182 if (size % n) {\
183 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
184 size, n, size + n - (size % n));\
186 } while(0)
188 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
190 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
191 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
192 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
193 uint32_t round_size = DO_ROUND(size, align);\
194 if (round_size != needed) {\
195 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
196 CHECK_ALIGN(size, align);\
199 } while(0)
201 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
202 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
203 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
204 uint32_t round_size = DO_ROUND(size, align);\
205 if (round_size != needed) {\
206 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
207 CHECK_ALIGN(size, align);\
210 } while(0)
212 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
213 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
214 uint32_t size = ndr_size_##fn(info, level, 0);\
215 uint32_t round_size = DO_ROUND(size, align);\
216 if (round_size != needed) {\
217 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
218 CHECK_ALIGN(size, align);\
221 } while(0)
223 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
224 const union spoolss_PrinterInfo *i,
225 uint32_t level,
226 union spoolss_SetPrinterInfo *s)
228 switch (level) {
229 case 0:
230 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
231 break;
232 case 2:
233 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
234 s->info2->servername = i->info2.servername;
235 s->info2->printername = i->info2.printername;
236 s->info2->sharename = i->info2.sharename;
237 s->info2->portname = i->info2.portname;
238 s->info2->drivername = i->info2.drivername;
239 s->info2->comment = i->info2.comment;
240 s->info2->location = i->info2.location;
241 s->info2->devmode_ptr = 0;
242 s->info2->sepfile = i->info2.sepfile;
243 s->info2->printprocessor = i->info2.printprocessor;
244 s->info2->datatype = i->info2.datatype;
245 s->info2->parameters = i->info2.parameters;
246 s->info2->secdesc_ptr = 0;
247 s->info2->attributes = i->info2.attributes;
248 s->info2->priority = i->info2.priority;
249 s->info2->defaultpriority = i->info2.defaultpriority;
250 s->info2->starttime = i->info2.starttime;
251 s->info2->untiltime = i->info2.untiltime;
252 s->info2->status = i->info2.status;
253 s->info2->cjobs = i->info2.cjobs;
254 s->info2->averageppm = i->info2.averageppm;
255 break;
256 case 3:
257 case 4:
258 case 5:
259 case 6:
260 case 7:
261 case 8:
262 case 9:
263 default:
264 return false;
267 return true;
270 static bool test_OpenPrinter_server(struct torture_context *tctx,
271 struct dcerpc_pipe *p,
272 struct policy_handle *server_handle)
274 NTSTATUS status;
275 struct spoolss_OpenPrinter op;
276 struct dcerpc_binding_handle *b = p->binding_handle;
278 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
279 op.in.datatype = NULL;
280 op.in.devmode_ctr.devmode= NULL;
281 op.in.access_mask = 0;
282 op.out.handle = server_handle;
284 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
286 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
287 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
288 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
290 return true;
293 static bool test_EnumPorts(struct torture_context *tctx,
294 void *private_data)
296 struct test_spoolss_context *ctx =
297 talloc_get_type_abort(private_data, struct test_spoolss_context);
298 struct dcerpc_pipe *p = ctx->spoolss_pipe;
299 struct dcerpc_binding_handle *b = p->binding_handle;
300 NTSTATUS status;
301 struct spoolss_EnumPorts r;
302 uint16_t levels[] = { 1, 2 };
303 int i, j;
305 for (i=0;i<ARRAY_SIZE(levels);i++) {
306 int level = levels[i];
307 DATA_BLOB blob;
308 uint32_t needed;
309 uint32_t count;
310 union spoolss_PortInfo *info;
312 r.in.servername = "";
313 r.in.level = level;
314 r.in.buffer = NULL;
315 r.in.offered = 0;
316 r.out.needed = &needed;
317 r.out.count = &count;
318 r.out.info = &info;
320 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
322 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
323 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
324 if (W_ERROR_IS_OK(r.out.result)) {
325 /* TODO: do some more checks here */
326 continue;
328 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
329 "EnumPorts unexpected return code");
331 blob = data_blob_talloc_zero(ctx, needed);
332 r.in.buffer = &blob;
333 r.in.offered = needed;
335 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
336 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
338 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
340 torture_assert(tctx, info, "EnumPorts returned no info");
342 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
344 ctx->port_count[level] = count;
345 ctx->ports[level] = info;
348 for (i=1;i<ARRAY_SIZE(levels);i++) {
349 int level = levels[i];
350 int old_level = levels[i-1];
351 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
352 "EnumPorts invalid value");
354 /* if the array sizes are not the same we would maybe segfault in the following code */
356 for (i=0;i<ARRAY_SIZE(levels);i++) {
357 int level = levels[i];
358 for (j=0;j<ctx->port_count[level];j++) {
359 union spoolss_PortInfo *cur = &ctx->ports[level][j];
360 union spoolss_PortInfo *ref = &ctx->ports[2][j];
361 switch (level) {
362 case 1:
363 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
364 break;
365 case 2:
366 /* level 2 is our reference, and it makes no sense to compare it to itself */
367 break;
372 return true;
375 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
376 void *private_data)
378 struct test_spoolss_context *ctx =
379 talloc_get_type_abort(private_data, struct test_spoolss_context);
381 NTSTATUS status;
382 struct dcerpc_pipe *p = ctx->spoolss_pipe;
383 struct dcerpc_binding_handle *b = p->binding_handle;
384 struct spoolss_GetPrintProcessorDirectory r;
385 struct {
386 uint16_t level;
387 const char *server;
388 } levels[] = {{
389 .level = 1,
390 .server = NULL
392 .level = 1,
393 .server = ""
395 .level = 78,
396 .server = ""
398 .level = 1,
399 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
401 .level = 1024,
402 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
405 int i;
406 uint32_t needed;
408 for (i=0;i<ARRAY_SIZE(levels);i++) {
409 int level = levels[i].level;
410 DATA_BLOB blob;
412 r.in.server = levels[i].server;
413 r.in.environment = ctx->environment;
414 r.in.level = level;
415 r.in.buffer = NULL;
416 r.in.offered = 0;
417 r.out.needed = &needed;
419 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
421 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
422 torture_assert_ntstatus_ok(tctx, status,
423 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
424 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
425 "GetPrintProcessorDirectory unexpected return code");
427 blob = data_blob_talloc_zero(tctx, needed);
428 r.in.buffer = &blob;
429 r.in.offered = needed;
431 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
432 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
434 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
436 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
439 return true;
443 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
444 void *private_data)
446 struct test_spoolss_context *ctx =
447 talloc_get_type_abort(private_data, struct test_spoolss_context);
449 NTSTATUS status;
450 struct dcerpc_pipe *p = ctx->spoolss_pipe;
451 struct dcerpc_binding_handle *b = p->binding_handle;
452 struct spoolss_GetPrinterDriverDirectory r;
453 struct {
454 uint16_t level;
455 const char *server;
456 } levels[] = {{
457 .level = 1,
458 .server = NULL
460 .level = 1,
461 .server = ""
463 .level = 78,
464 .server = ""
466 .level = 1,
467 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
469 .level = 1024,
470 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
473 int i;
474 uint32_t needed;
476 for (i=0;i<ARRAY_SIZE(levels);i++) {
477 int level = levels[i].level;
478 DATA_BLOB blob;
480 r.in.server = levels[i].server;
481 r.in.environment = ctx->environment;
482 r.in.level = level;
483 r.in.buffer = NULL;
484 r.in.offered = 0;
485 r.out.needed = &needed;
487 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
489 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
490 torture_assert_ntstatus_ok(tctx, status,
491 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
492 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
493 "GetPrinterDriverDirectory unexpected return code");
495 blob = data_blob_talloc_zero(tctx, needed);
496 r.in.buffer = &blob;
497 r.in.offered = needed;
499 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
500 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
502 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
504 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
507 return true;
510 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
511 struct dcerpc_binding_handle *b,
512 const char *server_name,
513 const char *environment,
514 uint32_t level,
515 uint32_t *count_p,
516 union spoolss_DriverInfo **info_p)
518 struct spoolss_EnumPrinterDrivers r;
519 uint32_t needed;
520 uint32_t count;
521 union spoolss_DriverInfo *info;
523 r.in.server = server_name;
524 r.in.environment = environment;
525 r.in.level = level;
526 r.in.buffer = NULL;
527 r.in.offered = 0;
528 r.out.needed = &needed;
529 r.out.count = &count;
530 r.out.info = &info;
532 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
533 r.in.environment, r.in.level);
535 torture_assert_ntstatus_ok(tctx,
536 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
537 "EnumPrinterDrivers failed");
538 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
539 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
540 r.in.buffer = &blob;
541 r.in.offered = needed;
543 torture_assert_ntstatus_ok(tctx,
544 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
545 "EnumPrinterDrivers failed");
548 torture_assert_werr_ok(tctx, r.out.result,
549 "EnumPrinterDrivers failed");
551 if (count_p) {
552 *count_p = count;
554 if (info_p) {
555 *info_p = info;
558 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
560 return true;
564 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
565 struct dcerpc_binding_handle *b,
566 const char *server_name,
567 const char *environment,
568 uint32_t level,
569 const char *driver_name,
570 union spoolss_DriverInfo *info_p)
572 uint32_t count;
573 union spoolss_DriverInfo *info;
574 int i;
575 const char *environment_ret = NULL;
577 torture_assert(tctx,
578 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
579 "failed to enumerate printer drivers");
581 for (i=0; i < count; i++) {
582 const char *driver_name_ret;
583 switch (level) {
584 case 1:
585 driver_name_ret = info[i].info1.driver_name;
586 break;
587 case 2:
588 driver_name_ret = info[i].info2.driver_name;
589 environment_ret = info[i].info2.architecture;
590 break;
591 case 3:
592 driver_name_ret = info[i].info3.driver_name;
593 environment_ret = info[i].info3.architecture;
594 break;
595 case 4:
596 driver_name_ret = info[i].info4.driver_name;
597 environment_ret = info[i].info4.architecture;
598 break;
599 case 5:
600 driver_name_ret = info[i].info5.driver_name;
601 environment_ret = info[i].info5.architecture;
602 break;
603 case 6:
604 driver_name_ret = info[i].info6.driver_name;
605 environment_ret = info[i].info6.architecture;
606 break;
607 case 7:
608 driver_name_ret = info[i].info7.driver_name;
609 break;
610 case 8:
611 driver_name_ret = info[i].info8.driver_name;
612 environment_ret = info[i].info8.architecture;
613 break;
614 default:
615 break;
617 if (environment_ret) {
618 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
620 if (strequal(driver_name, driver_name_ret)) {
621 if (info_p) {
622 *info_p = info[i];
624 return true;
628 return false;
631 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
632 void *private_data)
634 struct test_spoolss_context *ctx =
635 talloc_get_type_abort(private_data, struct test_spoolss_context);
636 struct dcerpc_pipe *p = ctx->spoolss_pipe;
637 struct dcerpc_binding_handle *b = p->binding_handle;
638 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
639 int i, j, a;
641 /* FIXME: gd, come back and fix "" as server, and handle
642 * priority of returned error codes in torture test and samba 3
643 * server */
644 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
645 const char *environments[2];
647 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
648 environments[1] = ctx->environment;
650 for (a=0;a<ARRAY_SIZE(environments);a++) {
652 for (i=0;i<ARRAY_SIZE(levels);i++) {
653 int level = levels[i];
654 uint32_t count;
655 union spoolss_DriverInfo *info;
657 torture_assert(tctx,
658 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
659 "failed to enumerate drivers");
661 ctx->driver_count[level] = count;
662 ctx->drivers[level] = info;
665 for (i=1;i<ARRAY_SIZE(levels);i++) {
666 int level = levels[i];
667 int old_level = levels[i-1];
669 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
670 "EnumPrinterDrivers invalid value");
673 for (i=0;i<ARRAY_SIZE(levels);i++) {
674 int level = levels[i];
676 for (j=0;j<ctx->driver_count[level];j++) {
677 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
678 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
680 switch (level) {
681 case 1:
682 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
683 break;
684 case 2:
685 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
686 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
687 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
688 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
689 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
690 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
691 break;
692 case 3:
693 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
694 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
695 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
696 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
697 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
698 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
699 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
700 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
703 break;
704 case 4:
705 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
706 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
707 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
708 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
709 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
710 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
711 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
712 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
715 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
716 break;
717 case 5:
718 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
719 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
720 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
721 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
722 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
723 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
724 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
725 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
726 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
727 break;
728 case 6:
729 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
730 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
731 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
732 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
733 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
734 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
735 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
736 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
739 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
740 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
741 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
742 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
745 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
746 break;
747 case 8:
748 /* level 8 is our reference, and it makes no sense to compare it to itself */
749 break;
755 return true;
758 static bool test_EnumMonitors(struct torture_context *tctx,
759 void *private_data)
761 struct test_spoolss_context *ctx =
762 talloc_get_type_abort(private_data, struct test_spoolss_context);
763 struct dcerpc_pipe *p = ctx->spoolss_pipe;
764 struct dcerpc_binding_handle *b = p->binding_handle;
765 NTSTATUS status;
766 struct spoolss_EnumMonitors r;
767 uint16_t levels[] = { 1, 2 };
768 int i, j;
770 for (i=0;i<ARRAY_SIZE(levels);i++) {
771 int level = levels[i];
772 DATA_BLOB blob;
773 uint32_t needed;
774 uint32_t count;
775 union spoolss_MonitorInfo *info;
777 r.in.servername = "";
778 r.in.level = level;
779 r.in.buffer = NULL;
780 r.in.offered = 0;
781 r.out.needed = &needed;
782 r.out.count = &count;
783 r.out.info = &info;
785 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
787 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
788 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
789 if (W_ERROR_IS_OK(r.out.result)) {
790 /* TODO: do some more checks here */
791 continue;
793 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
794 "EnumMonitors failed");
796 blob = data_blob_talloc_zero(ctx, needed);
797 r.in.buffer = &blob;
798 r.in.offered = needed;
800 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
801 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
803 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
805 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
807 ctx->monitor_count[level] = count;
808 ctx->monitors[level] = info;
811 for (i=1;i<ARRAY_SIZE(levels);i++) {
812 int level = levels[i];
813 int old_level = levels[i-1];
814 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
815 "EnumMonitors invalid value");
818 for (i=0;i<ARRAY_SIZE(levels);i++) {
819 int level = levels[i];
820 for (j=0;j<ctx->monitor_count[level];j++) {
821 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
822 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
823 switch (level) {
824 case 1:
825 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
826 break;
827 case 2:
828 /* level 2 is our reference, and it makes no sense to compare it to itself */
829 break;
834 return true;
837 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
838 struct dcerpc_binding_handle *b,
839 const char *environment,
840 uint32_t level,
841 uint32_t *count_p,
842 union spoolss_PrintProcessorInfo **info_p,
843 WERROR expected_result)
845 struct spoolss_EnumPrintProcessors r;
846 DATA_BLOB blob;
847 uint32_t needed;
848 uint32_t count;
849 union spoolss_PrintProcessorInfo *info;
851 r.in.servername = "";
852 r.in.environment = environment;
853 r.in.level = level;
854 r.in.buffer = NULL;
855 r.in.offered = 0;
856 r.out.needed = &needed;
857 r.out.count = &count;
858 r.out.info = &info;
860 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
861 r.in.environment, r.in.level);
863 torture_assert_ntstatus_ok(tctx,
864 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
865 "EnumPrintProcessors failed");
866 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
867 blob = data_blob_talloc_zero(tctx, needed);
868 r.in.buffer = &blob;
869 r.in.offered = needed;
870 torture_assert_ntstatus_ok(tctx,
871 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
872 "EnumPrintProcessors failed");
874 torture_assert_werr_equal(tctx, r.out.result, expected_result,
875 "EnumPrintProcessors failed");
877 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
879 if (count_p) {
880 *count_p = count;
882 if (info_p) {
883 *info_p = info;
886 return true;
889 static bool test_EnumPrintProcessors(struct torture_context *tctx,
890 void *private_data)
892 struct test_spoolss_context *ctx =
893 talloc_get_type_abort(private_data, struct test_spoolss_context);
895 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
896 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
897 int i;
898 struct dcerpc_pipe *p = ctx->spoolss_pipe;
899 struct dcerpc_binding_handle *b = p->binding_handle;
901 torture_assert(tctx,
902 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
903 "test_EnumPrintProcessors_level failed");
905 for (i=0;i<ARRAY_SIZE(levels);i++) {
906 union spoolss_PrintProcessorInfo *info;
907 uint32_t count;
908 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
910 torture_assert(tctx,
911 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
912 "test_EnumPrintProcessors_level failed");
915 return true;
918 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
919 struct dcerpc_binding_handle *b,
920 const char *print_processor_name,
921 uint32_t level,
922 uint32_t *count_p,
923 union spoolss_PrintProcDataTypesInfo **info_p,
924 WERROR expected_result)
926 struct spoolss_EnumPrintProcDataTypes r;
927 DATA_BLOB blob;
928 uint32_t needed;
929 uint32_t count;
930 union spoolss_PrintProcDataTypesInfo *info;
932 r.in.servername = "";
933 r.in.print_processor_name = print_processor_name;
934 r.in.level = level;
935 r.in.buffer = NULL;
936 r.in.offered = 0;
937 r.out.needed = &needed;
938 r.out.count = &count;
939 r.out.info = &info;
941 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
942 r.in.print_processor_name, r.in.level);
944 torture_assert_ntstatus_ok(tctx,
945 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
946 "EnumPrintProcDataTypes failed");
947 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
948 blob = data_blob_talloc_zero(tctx, needed);
949 r.in.buffer = &blob;
950 r.in.offered = needed;
951 torture_assert_ntstatus_ok(tctx,
952 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
953 "EnumPrintProcDataTypes failed");
955 torture_assert_werr_equal(tctx, r.out.result, expected_result,
956 "EnumPrintProcDataTypes failed");
958 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
960 if (count_p) {
961 *count_p = count;
963 if (info_p) {
964 *info_p = info;
967 return true;
970 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
971 void *private_data)
973 struct test_spoolss_context *ctx =
974 talloc_get_type_abort(private_data, struct test_spoolss_context);
976 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
977 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
978 int i;
979 struct dcerpc_pipe *p = ctx->spoolss_pipe;
980 struct dcerpc_binding_handle *b = p->binding_handle;
982 torture_assert(tctx,
983 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
984 "test_EnumPrintProcDataTypes_level failed");
986 torture_assert(tctx,
987 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
988 "test_EnumPrintProcDataTypes_level failed");
990 for (i=0;i<ARRAY_SIZE(levels);i++) {
991 int level = levels[i];
992 uint32_t count;
993 union spoolss_PrintProcDataTypesInfo *info;
994 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
996 torture_assert(tctx,
997 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
998 "test_EnumPrintProcDataTypes_level failed");
1002 union spoolss_PrintProcessorInfo *info;
1003 uint32_t count;
1005 torture_assert(tctx,
1006 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1007 "test_EnumPrintProcessors_level failed");
1009 for (i=0; i < count; i++) {
1010 torture_assert(tctx,
1011 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1012 "test_EnumPrintProcDataTypes_level failed");
1017 return true;
1020 static bool test_EnumPrinters(struct torture_context *tctx,
1021 void *private_data)
1023 struct test_spoolss_context *ctx =
1024 talloc_get_type_abort(private_data, struct test_spoolss_context);
1025 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1026 struct dcerpc_binding_handle *b = p->binding_handle;
1027 struct spoolss_EnumPrinters r;
1028 NTSTATUS status;
1029 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1030 int i, j;
1032 for (i=0;i<ARRAY_SIZE(levels);i++) {
1033 int level = levels[i];
1034 DATA_BLOB blob;
1035 uint32_t needed;
1036 uint32_t count;
1037 union spoolss_PrinterInfo *info;
1039 r.in.flags = PRINTER_ENUM_LOCAL;
1040 r.in.server = "";
1041 r.in.level = level;
1042 r.in.buffer = NULL;
1043 r.in.offered = 0;
1044 r.out.needed = &needed;
1045 r.out.count = &count;
1046 r.out.info = &info;
1048 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1050 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1051 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1052 if (W_ERROR_IS_OK(r.out.result)) {
1053 /* TODO: do some more checks here */
1054 continue;
1056 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1057 "EnumPrinters unexpected return code");
1059 blob = data_blob_talloc_zero(ctx, needed);
1060 r.in.buffer = &blob;
1061 r.in.offered = needed;
1063 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1064 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1066 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1068 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1070 ctx->printer_count[level] = count;
1071 ctx->printers[level] = info;
1074 for (i=1;i<ARRAY_SIZE(levels);i++) {
1075 int level = levels[i];
1076 int old_level = levels[i-1];
1077 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1078 "EnumPrinters invalid value");
1081 for (i=0;i<ARRAY_SIZE(levels);i++) {
1082 int level = levels[i];
1083 for (j=0;j<ctx->printer_count[level];j++) {
1084 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1085 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1086 switch (level) {
1087 case 0:
1088 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1089 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1090 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1091 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1092 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1093 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1094 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1095 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1097 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1099 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1110 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1112 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1113 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1116 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1117 break;
1118 case 1:
1119 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1120 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1121 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1122 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1123 break;
1124 case 2:
1125 /* level 2 is our reference, and it makes no sense to compare it to itself */
1126 break;
1127 case 4:
1128 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1129 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1130 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1131 break;
1132 case 5:
1133 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1134 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1135 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1136 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1137 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1138 break;
1143 /* TODO:
1144 * - verify that the port of a printer was in the list returned by EnumPorts
1147 return true;
1150 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1151 struct dcerpc_binding_handle *b,
1152 struct policy_handle *handle,
1153 const char *driver_name,
1154 const char *environment);
1156 bool test_GetPrinter_level(struct torture_context *tctx,
1157 struct dcerpc_binding_handle *b,
1158 struct policy_handle *handle,
1159 uint32_t level,
1160 union spoolss_PrinterInfo *info)
1162 struct spoolss_GetPrinter r;
1163 uint32_t needed;
1165 r.in.handle = handle;
1166 r.in.level = level;
1167 r.in.buffer = NULL;
1168 r.in.offered = 0;
1169 r.out.needed = &needed;
1171 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1173 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1174 "GetPrinter failed");
1176 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1177 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1178 r.in.buffer = &blob;
1179 r.in.offered = needed;
1181 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1182 "GetPrinter failed");
1185 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1187 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1189 if (info && r.out.info) {
1190 *info = *r.out.info;
1193 return true;
1197 static bool test_GetPrinter(struct torture_context *tctx,
1198 struct dcerpc_binding_handle *b,
1199 struct policy_handle *handle,
1200 const char *environment)
1202 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1203 int i;
1205 for (i=0;i<ARRAY_SIZE(levels);i++) {
1207 union spoolss_PrinterInfo info;
1209 ZERO_STRUCT(info);
1211 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1212 "failed to call GetPrinter");
1214 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1215 torture_assert(tctx,
1216 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1217 "failed to call test_GetPrinterDriver2");
1221 return true;
1224 static bool test_SetPrinter(struct torture_context *tctx,
1225 struct dcerpc_binding_handle *b,
1226 struct policy_handle *handle,
1227 struct spoolss_SetPrinterInfoCtr *info_ctr,
1228 struct spoolss_DevmodeContainer *devmode_ctr,
1229 struct sec_desc_buf *secdesc_ctr,
1230 enum spoolss_PrinterControl command)
1232 struct spoolss_SetPrinter r;
1234 r.in.handle = handle;
1235 r.in.info_ctr = info_ctr;
1236 r.in.devmode_ctr = devmode_ctr;
1237 r.in.secdesc_ctr = secdesc_ctr;
1238 r.in.command = command;
1240 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1242 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1243 "failed to call SetPrinter");
1244 torture_assert_werr_ok(tctx, r.out.result,
1245 "failed to call SetPrinter");
1247 return true;
1250 static bool test_SetPrinter_errors(struct torture_context *tctx,
1251 struct dcerpc_binding_handle *b,
1252 struct policy_handle *handle)
1254 struct spoolss_SetPrinter r;
1255 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1256 int i;
1258 struct spoolss_SetPrinterInfoCtr info_ctr;
1259 struct spoolss_DevmodeContainer devmode_ctr;
1260 struct sec_desc_buf secdesc_ctr;
1262 info_ctr.level = 0;
1263 info_ctr.info.info0 = NULL;
1265 ZERO_STRUCT(devmode_ctr);
1266 ZERO_STRUCT(secdesc_ctr);
1268 r.in.handle = handle;
1269 r.in.info_ctr = &info_ctr;
1270 r.in.devmode_ctr = &devmode_ctr;
1271 r.in.secdesc_ctr = &secdesc_ctr;
1272 r.in.command = 0;
1274 torture_comment(tctx, "Testing SetPrinter all zero\n");
1276 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1277 "failed to call SetPrinter");
1278 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1279 "failed to call SetPrinter");
1281 again:
1282 for (i=0; i < ARRAY_SIZE(levels); i++) {
1284 struct spoolss_SetPrinterInfo0 info0;
1285 struct spoolss_SetPrinterInfo1 info1;
1286 struct spoolss_SetPrinterInfo2 info2;
1287 struct spoolss_SetPrinterInfo3 info3;
1288 struct spoolss_SetPrinterInfo4 info4;
1289 struct spoolss_SetPrinterInfo5 info5;
1290 struct spoolss_SetPrinterInfo6 info6;
1291 struct spoolss_SetPrinterInfo7 info7;
1292 struct spoolss_SetPrinterInfo8 info8;
1293 struct spoolss_SetPrinterInfo9 info9;
1296 info_ctr.level = levels[i];
1297 switch (levels[i]) {
1298 case 0:
1299 ZERO_STRUCT(info0);
1300 info_ctr.info.info0 = &info0;
1301 break;
1302 case 1:
1303 ZERO_STRUCT(info1);
1304 info_ctr.info.info1 = &info1;
1305 break;
1306 case 2:
1307 ZERO_STRUCT(info2);
1308 info_ctr.info.info2 = &info2;
1309 break;
1310 case 3:
1311 ZERO_STRUCT(info3);
1312 info_ctr.info.info3 = &info3;
1313 break;
1314 case 4:
1315 ZERO_STRUCT(info4);
1316 info_ctr.info.info4 = &info4;
1317 break;
1318 case 5:
1319 ZERO_STRUCT(info5);
1320 info_ctr.info.info5 = &info5;
1321 break;
1322 case 6:
1323 ZERO_STRUCT(info6);
1324 info_ctr.info.info6 = &info6;
1325 break;
1326 case 7:
1327 ZERO_STRUCT(info7);
1328 info_ctr.info.info7 = &info7;
1329 break;
1330 case 8:
1331 ZERO_STRUCT(info8);
1332 info_ctr.info.info8 = &info8;
1333 break;
1334 case 9:
1335 ZERO_STRUCT(info9);
1336 info_ctr.info.info9 = &info9;
1337 break;
1340 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1341 info_ctr.level, r.in.command);
1343 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1344 "failed to call SetPrinter");
1346 switch (r.in.command) {
1347 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1348 /* is ignored for all levels other then 0 */
1349 if (info_ctr.level > 0) {
1350 /* ignored then */
1351 break;
1353 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1354 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1355 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1356 if (info_ctr.level > 0) {
1357 /* is invalid for all levels other then 0 */
1358 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1359 "unexpected error code returned");
1360 continue;
1361 } else {
1362 torture_assert_werr_ok(tctx, r.out.result,
1363 "failed to call SetPrinter with non 0 command");
1364 continue;
1366 break;
1368 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1369 /* FIXME: gd needs further investigation */
1370 default:
1371 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1372 "unexpected error code returned");
1373 continue;
1376 switch (info_ctr.level) {
1377 case 1:
1378 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1379 "unexpected error code returned");
1380 break;
1381 case 2:
1382 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1383 "unexpected error code returned");
1384 break;
1385 case 3:
1386 case 4:
1387 case 5:
1388 case 7:
1389 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1390 "unexpected error code returned");
1391 break;
1392 case 9:
1393 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1394 "unexpected error code returned");
1395 break;
1396 default:
1397 torture_assert_werr_ok(tctx, r.out.result,
1398 "failed to call SetPrinter");
1399 break;
1403 if (r.in.command < 5) {
1404 r.in.command++;
1405 goto again;
1408 return true;
1411 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1413 if ((r->level == 2) && (r->info.info2)) {
1414 r->info.info2->secdesc_ptr = 0;
1415 r->info.info2->devmode_ptr = 0;
1419 static bool test_PrinterInfo(struct torture_context *tctx,
1420 struct dcerpc_binding_handle *b,
1421 struct policy_handle *handle)
1423 NTSTATUS status;
1424 struct spoolss_SetPrinter s;
1425 struct spoolss_GetPrinter q;
1426 struct spoolss_GetPrinter q0;
1427 struct spoolss_SetPrinterInfoCtr info_ctr;
1428 union spoolss_PrinterInfo info;
1429 struct spoolss_DevmodeContainer devmode_ctr;
1430 struct sec_desc_buf secdesc_ctr;
1431 uint32_t needed;
1432 bool ret = true;
1433 int i;
1435 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1437 uint32_t status_list[] = {
1438 /* these do not stick
1439 PRINTER_STATUS_PAUSED,
1440 PRINTER_STATUS_ERROR,
1441 PRINTER_STATUS_PENDING_DELETION, */
1442 PRINTER_STATUS_PAPER_JAM,
1443 PRINTER_STATUS_PAPER_OUT,
1444 PRINTER_STATUS_MANUAL_FEED,
1445 PRINTER_STATUS_PAPER_PROBLEM,
1446 PRINTER_STATUS_OFFLINE,
1447 PRINTER_STATUS_IO_ACTIVE,
1448 PRINTER_STATUS_BUSY,
1449 PRINTER_STATUS_PRINTING,
1450 PRINTER_STATUS_OUTPUT_BIN_FULL,
1451 PRINTER_STATUS_NOT_AVAILABLE,
1452 PRINTER_STATUS_WAITING,
1453 PRINTER_STATUS_PROCESSING,
1454 PRINTER_STATUS_INITIALIZING,
1455 PRINTER_STATUS_WARMING_UP,
1456 PRINTER_STATUS_TONER_LOW,
1457 PRINTER_STATUS_NO_TONER,
1458 PRINTER_STATUS_PAGE_PUNT,
1459 PRINTER_STATUS_USER_INTERVENTION,
1460 PRINTER_STATUS_OUT_OF_MEMORY,
1461 PRINTER_STATUS_DOOR_OPEN,
1462 PRINTER_STATUS_SERVER_UNKNOWN,
1463 PRINTER_STATUS_POWER_SAVE,
1464 /* these do not stick
1465 0x02000000,
1466 0x04000000,
1467 0x08000000,
1468 0x10000000,
1469 0x20000000,
1470 0x40000000,
1471 0x80000000 */
1473 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1474 uint32_t attribute_list[] = {
1475 PRINTER_ATTRIBUTE_QUEUED,
1476 /* fails with WERR_INVALID_DATATYPE:
1477 PRINTER_ATTRIBUTE_DIRECT, */
1478 /* does not stick
1479 PRINTER_ATTRIBUTE_DEFAULT, */
1480 PRINTER_ATTRIBUTE_SHARED,
1481 /* does not stick
1482 PRINTER_ATTRIBUTE_NETWORK, */
1483 PRINTER_ATTRIBUTE_HIDDEN,
1484 PRINTER_ATTRIBUTE_LOCAL,
1485 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1486 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1487 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1488 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1489 /* does not stick
1490 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1491 /* fails with WERR_INVALID_DATATYPE:
1492 PRINTER_ATTRIBUTE_RAW_ONLY, */
1493 /* these do not stick
1494 PRINTER_ATTRIBUTE_PUBLISHED,
1495 PRINTER_ATTRIBUTE_FAX,
1496 PRINTER_ATTRIBUTE_TS,
1497 0x00010000,
1498 0x00020000,
1499 0x00040000,
1500 0x00080000,
1501 0x00100000,
1502 0x00200000,
1503 0x00400000,
1504 0x00800000,
1505 0x01000000,
1506 0x02000000,
1507 0x04000000,
1508 0x08000000,
1509 0x10000000,
1510 0x20000000,
1511 0x40000000,
1512 0x80000000 */
1515 ZERO_STRUCT(devmode_ctr);
1516 ZERO_STRUCT(secdesc_ctr);
1518 s.in.handle = handle;
1519 s.in.command = 0;
1520 s.in.info_ctr = &info_ctr;
1521 s.in.devmode_ctr = &devmode_ctr;
1522 s.in.secdesc_ctr = &secdesc_ctr;
1524 q.in.handle = handle;
1525 q.out.info = &info;
1526 q0 = q;
1528 #define TESTGETCALL(call, r) \
1529 r.in.buffer = NULL; \
1530 r.in.offered = 0;\
1531 r.out.needed = &needed; \
1532 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1533 if (!NT_STATUS_IS_OK(status)) { \
1534 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1535 r.in.level, nt_errstr(status), __location__); \
1536 ret = false; \
1537 break; \
1539 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1540 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1541 r.in.buffer = &blob; \
1542 r.in.offered = needed; \
1544 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1545 if (!NT_STATUS_IS_OK(status)) { \
1546 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1547 r.in.level, nt_errstr(status), __location__); \
1548 ret = false; \
1549 break; \
1551 if (!W_ERROR_IS_OK(r.out.result)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, win_errstr(r.out.result), __location__); \
1554 ret = false; \
1555 break; \
1559 #define TESTSETCALL_EXP(call, r, err) \
1560 clear_info2(&info_ctr);\
1561 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1562 if (!NT_STATUS_IS_OK(status)) { \
1563 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1564 r.in.info_ctr->level, nt_errstr(status), __location__); \
1565 ret = false; \
1566 break; \
1568 if (!W_ERROR_IS_OK(err)) { \
1569 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1570 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1571 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1572 ret = false; \
1574 break; \
1576 if (!W_ERROR_IS_OK(r.out.result)) { \
1577 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1578 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1579 ret = false; \
1580 break; \
1583 #define TESTSETCALL(call, r) \
1584 TESTSETCALL_EXP(call, r, WERR_OK)
1586 #define STRING_EQUAL(s1, s2, field) \
1587 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1588 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1589 #field, s2, __location__); \
1590 ret = false; \
1591 break; \
1594 #define MEM_EQUAL(s1, s2, length, field) \
1595 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1596 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1597 #field, (const char *)s2, __location__); \
1598 ret = false; \
1599 break; \
1602 #define INT_EQUAL(i1, i2, field) \
1603 if (i1 != i2) { \
1604 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1605 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1606 ret = false; \
1607 break; \
1610 #define SD_EQUAL(sd1, sd2, field) \
1611 if (!security_descriptor_equal(sd1, sd2)) { \
1612 torture_comment(tctx, "Failed to set %s (%s)\n", \
1613 #field, __location__); \
1614 ret = false; \
1615 break; \
1618 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1619 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1620 q.in.level = lvl1; \
1621 TESTGETCALL(GetPrinter, q) \
1622 info_ctr.level = lvl1; \
1623 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1624 info_ctr.info.info ## lvl1->field1 = value;\
1625 TESTSETCALL_EXP(SetPrinter, s, err) \
1626 info_ctr.info.info ## lvl1->field1 = ""; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.info.info ## lvl1->field1 = value; \
1629 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1630 q.in.level = lvl2; \
1631 TESTGETCALL(GetPrinter, q) \
1632 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1633 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1634 } while (0)
1636 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1637 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1638 } while (0);
1640 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1641 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1642 q.in.level = lvl1; \
1643 TESTGETCALL(GetPrinter, q) \
1644 info_ctr.level = lvl1; \
1645 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1646 info_ctr.info.info ## lvl1->field1 = value; \
1647 TESTSETCALL(SetPrinter, s) \
1648 info_ctr.info.info ## lvl1->field1 = 0; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1651 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1652 q.in.level = lvl2; \
1653 TESTGETCALL(GetPrinter, q) \
1654 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1655 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1656 } while (0)
1658 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1659 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1660 } while (0)
1662 q0.in.level = 0;
1663 do { TESTGETCALL(GetPrinter, q0) } while (0);
1665 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1666 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1668 /* level 0 printername does not stick */
1669 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1670 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1671 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1672 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1673 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1674 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1675 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1676 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1677 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1678 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1679 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1680 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1681 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1682 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1683 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1685 /* servername can be set but does not stick
1686 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1687 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1688 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1691 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1692 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1693 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1694 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1695 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1697 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1698 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1700 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1701 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1702 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1703 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1704 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1705 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1706 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1708 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1709 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1710 attribute_list[i],
1711 (attribute_list[i] | default_attribute)
1712 ); */
1713 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1714 attribute_list[i],
1715 (attribute_list[i] | default_attribute)
1717 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1718 attribute_list[i],
1719 (attribute_list[i] | default_attribute)
1721 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1722 attribute_list[i],
1723 (attribute_list[i] | default_attribute)
1725 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1726 attribute_list[i],
1727 (attribute_list[i] | default_attribute)
1728 ); */
1729 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1730 attribute_list[i],
1731 (attribute_list[i] | default_attribute)
1733 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1734 attribute_list[i],
1735 (attribute_list[i] | default_attribute)
1737 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1738 attribute_list[i],
1739 (attribute_list[i] | default_attribute)
1741 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1742 attribute_list[i],
1743 (attribute_list[i] | default_attribute)
1744 ); */
1745 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1746 attribute_list[i],
1747 (attribute_list[i] | default_attribute)
1749 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1750 attribute_list[i],
1751 (attribute_list[i] | default_attribute)
1753 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1754 attribute_list[i],
1755 (attribute_list[i] | default_attribute)
1759 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1760 /* level 2 sets do not stick
1761 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1762 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1763 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1764 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1765 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1766 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1769 /* priorities need to be between 0 and 99
1770 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1771 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1772 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1773 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1774 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1775 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1776 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1777 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1778 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1780 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1781 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1783 /* does not stick
1784 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1785 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1787 /* does not stick
1788 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1789 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1791 /* FIXME: gd also test devmode and secdesc behavior */
1794 /* verify composition of level 1 description field */
1795 const char *description;
1796 const char *tmp;
1798 q0.in.level = 1;
1799 do { TESTGETCALL(GetPrinter, q0) } while (0);
1801 description = talloc_strdup(tctx, q0.out.info->info1.description);
1803 q0.in.level = 2;
1804 do { TESTGETCALL(GetPrinter, q0) } while (0);
1806 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1807 q0.out.info->info2.printername,
1808 q0.out.info->info2.drivername,
1809 q0.out.info->info2.location);
1811 do { STRING_EQUAL(description, tmp, "description")} while (0);
1814 return ret;
1817 static bool test_security_descriptor_equal(struct torture_context *tctx,
1818 const struct security_descriptor *sd1,
1819 const struct security_descriptor *sd2)
1821 if (sd1 == sd2) {
1822 return true;
1825 if (!sd1 || !sd2) {
1826 torture_comment(tctx, "%s\n", __location__);
1827 return false;
1830 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1831 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1833 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1834 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1836 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1837 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1838 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1839 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1840 return false;
1842 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1843 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1846 return false;
1849 return true;
1852 static bool test_sd_set_level(struct torture_context *tctx,
1853 struct dcerpc_binding_handle *b,
1854 struct policy_handle *handle,
1855 uint32_t level,
1856 struct security_descriptor *sd)
1858 struct spoolss_SetPrinterInfoCtr info_ctr;
1859 struct spoolss_DevmodeContainer devmode_ctr;
1860 struct sec_desc_buf secdesc_ctr;
1861 union spoolss_SetPrinterInfo sinfo;
1863 ZERO_STRUCT(devmode_ctr);
1864 ZERO_STRUCT(secdesc_ctr);
1866 switch (level) {
1867 case 2: {
1868 union spoolss_PrinterInfo info;
1869 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1870 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1872 info_ctr.level = 2;
1873 info_ctr.info = sinfo;
1875 break;
1877 case 3: {
1878 struct spoolss_SetPrinterInfo3 info3;
1880 info3.sec_desc_ptr = 0;
1882 info_ctr.level = 3;
1883 info_ctr.info.info3 = &info3;
1885 break;
1887 default:
1888 return false;
1891 secdesc_ctr.sd = sd;
1893 torture_assert(tctx,
1894 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1896 return true;
1899 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1900 struct dcerpc_binding_handle *b,
1901 struct policy_handle *handle)
1903 union spoolss_PrinterInfo info;
1904 struct security_descriptor *sd1, *sd2;
1905 int i;
1907 /* just compare level 2 and level 3 */
1909 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1911 sd1 = info.info2.secdesc;
1913 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1915 sd2 = info.info3.secdesc;
1917 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1918 "SD level 2 != SD level 3");
1921 /* query level 2, set level 2, query level 2 */
1923 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1925 sd1 = info.info2.secdesc;
1927 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd2 = info.info2.secdesc;
1932 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1933 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1934 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1937 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1938 "SD level 2 != SD level 2 after SD has been set via level 2");
1941 /* query level 2, set level 3, query level 2 */
1943 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1945 sd1 = info.info2.secdesc;
1947 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd2 = info.info2.secdesc;
1953 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1954 "SD level 2 != SD level 2 after SD has been set via level 3");
1956 /* set modified sd level 3, query level 2 */
1958 for (i=0; i < 93; i++) {
1959 struct security_ace a;
1960 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1961 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1962 a.flags = 0;
1963 a.size = 0; /* autogenerated */
1964 a.access_mask = 0;
1965 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1966 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1969 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1971 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1972 sd2 = info.info2.secdesc;
1974 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1975 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1976 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1979 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1980 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1983 return true;
1987 * wrapper call that saves original sd, runs tests, and restores sd
1990 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1991 struct dcerpc_binding_handle *b,
1992 struct policy_handle *handle)
1994 union spoolss_PrinterInfo info;
1995 struct security_descriptor *sd;
1996 bool ret = true;
1998 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2000 /* save original sd */
2002 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2003 "failed to get initial security descriptor");
2005 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2007 /* run tests */
2009 ret = test_PrinterInfo_SDs(tctx, b, handle);
2011 /* restore original sd */
2013 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2014 "failed to restore initial security descriptor");
2016 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2017 ret ? "succeeded" : "failed");
2020 return ret;
2023 static bool test_devmode_set_level(struct torture_context *tctx,
2024 struct dcerpc_binding_handle *b,
2025 struct policy_handle *handle,
2026 uint32_t level,
2027 struct spoolss_DeviceMode *devmode)
2029 struct spoolss_SetPrinterInfoCtr info_ctr;
2030 struct spoolss_DevmodeContainer devmode_ctr;
2031 struct sec_desc_buf secdesc_ctr;
2032 union spoolss_SetPrinterInfo sinfo;
2034 ZERO_STRUCT(devmode_ctr);
2035 ZERO_STRUCT(secdesc_ctr);
2037 switch (level) {
2038 case 2: {
2039 union spoolss_PrinterInfo info;
2040 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2041 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2043 info_ctr.level = 2;
2044 info_ctr.info = sinfo;
2046 break;
2048 case 8: {
2049 struct spoolss_SetPrinterInfo8 info8;
2051 info8.devmode_ptr = 0;
2053 info_ctr.level = 8;
2054 info_ctr.info.info8 = &info8;
2056 break;
2058 default:
2059 return false;
2062 devmode_ctr.devmode = devmode;
2064 torture_assert(tctx,
2065 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2067 return true;
2071 static bool test_devicemode_equal(struct torture_context *tctx,
2072 const struct spoolss_DeviceMode *d1,
2073 const struct spoolss_DeviceMode *d2)
2075 if (d1 == d2) {
2076 return true;
2079 if (!d1 || !d2) {
2080 torture_comment(tctx, "%s\n", __location__);
2081 return false;
2083 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2084 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2085 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2086 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2087 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2088 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2089 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2090 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2091 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2092 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2093 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2094 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2095 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2096 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2097 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2098 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2099 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2100 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2101 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2102 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2103 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2104 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2105 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2106 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2107 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2108 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2109 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2110 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2111 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2112 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2113 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2114 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2115 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2116 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2117 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2119 return true;
2122 static bool test_devicemode_full(struct torture_context *tctx,
2123 struct dcerpc_binding_handle *b,
2124 struct policy_handle *handle)
2126 struct spoolss_SetPrinter s;
2127 struct spoolss_GetPrinter q;
2128 struct spoolss_GetPrinter q0;
2129 struct spoolss_SetPrinterInfoCtr info_ctr;
2130 struct spoolss_SetPrinterInfo8 info8;
2131 union spoolss_PrinterInfo info;
2132 struct spoolss_DevmodeContainer devmode_ctr;
2133 struct sec_desc_buf secdesc_ctr;
2134 uint32_t needed;
2135 bool ret = true;
2136 NTSTATUS status;
2138 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2139 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2140 q.in.level = lvl1; \
2141 TESTGETCALL(GetPrinter, q) \
2142 info_ctr.level = lvl1; \
2143 if (lvl1 == 2) {\
2144 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2145 } else if (lvl1 == 8) {\
2146 info_ctr.info.info ## lvl1 = &info8; \
2148 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2149 devmode_ctr.devmode->field1 = value; \
2150 TESTSETCALL(SetPrinter, s) \
2151 TESTGETCALL(GetPrinter, q) \
2152 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2153 q.in.level = lvl2; \
2154 TESTGETCALL(GetPrinter, q) \
2155 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2156 } while (0)
2158 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2159 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2160 } while (0)
2162 ZERO_STRUCT(devmode_ctr);
2163 ZERO_STRUCT(secdesc_ctr);
2164 ZERO_STRUCT(info8);
2166 s.in.handle = handle;
2167 s.in.command = 0;
2168 s.in.info_ctr = &info_ctr;
2169 s.in.devmode_ctr = &devmode_ctr;
2170 s.in.secdesc_ctr = &secdesc_ctr;
2172 q.in.handle = handle;
2173 q.out.info = &info;
2174 q0 = q;
2176 #if 0
2177 const char *devicename;/* [charset(UTF16)] */
2178 enum spoolss_DeviceModeSpecVersion specversion;
2179 uint16_t driverversion;
2180 uint16_t size;
2181 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2182 uint32_t fields;
2183 #endif
2185 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2186 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2187 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2188 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2189 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2190 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2191 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2192 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2193 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2194 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2195 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2196 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2197 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2198 #if 0
2199 const char *formname;/* [charset(UTF16)] */
2200 #endif
2201 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2202 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2203 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2204 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2205 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2206 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2207 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2208 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2209 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2210 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2211 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2212 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2213 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2214 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2216 return ret;
2219 static bool call_OpenPrinterEx(struct torture_context *tctx,
2220 struct dcerpc_pipe *p,
2221 const char *name,
2222 struct spoolss_DeviceMode *devmode,
2223 struct policy_handle *handle);
2225 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2226 struct dcerpc_pipe *p,
2227 struct policy_handle *handle,
2228 const char *name)
2230 union spoolss_PrinterInfo info;
2231 struct spoolss_DeviceMode *devmode;
2232 struct spoolss_DeviceMode *devmode2;
2233 struct policy_handle handle_devmode;
2234 struct dcerpc_binding_handle *b = p->binding_handle;
2236 /* simply compare level8 and level2 devmode */
2238 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2240 devmode = info.info8.devmode;
2242 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2244 devmode2 = info.info2.devmode;
2246 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2247 "DM level 8 != DM level 2");
2250 /* set devicemode level 8 and see if it persists */
2252 devmode->copies = 93;
2253 devmode->formname = talloc_strdup(tctx, "Legal");
2255 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2257 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2259 devmode2 = info.info8.devmode;
2261 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2262 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2264 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2266 devmode2 = info.info2.devmode;
2268 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2269 "modified DM level 8 != DM level 2");
2272 /* set devicemode level 2 and see if it persists */
2274 devmode->copies = 39;
2275 devmode->formname = talloc_strdup(tctx, "Executive");
2277 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2279 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2281 devmode2 = info.info8.devmode;
2283 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2284 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2286 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2288 devmode2 = info.info2.devmode;
2290 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2291 "modified DM level 8 != DM level 2");
2294 /* check every single bit in public part of devicemode */
2296 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2297 "failed to set every single devicemode component");
2300 /* change formname upon open and see if it persists in getprinter calls */
2302 devmode->formname = talloc_strdup(tctx, "A4");
2303 devmode->copies = 42;
2305 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2306 "failed to open printer handle");
2308 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2310 devmode2 = info.info8.devmode;
2312 if (strequal(devmode->devicename, devmode2->devicename)) {
2313 torture_warning(tctx, "devicenames are the same\n");
2314 } else {
2315 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2316 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2319 if (strequal(devmode->formname, devmode2->formname)) {
2320 torture_warning(tctx, "formname are the same\n");
2321 } else {
2322 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2323 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2326 if (devmode->copies == devmode2->copies) {
2327 torture_warning(tctx, "copies are the same\n");
2328 } else {
2329 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2330 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2333 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2335 devmode2 = info.info2.devmode;
2337 if (strequal(devmode->devicename, devmode2->devicename)) {
2338 torture_warning(tctx, "devicenames are the same\n");
2339 } else {
2340 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2341 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2344 if (strequal(devmode->formname, devmode2->formname)) {
2345 torture_warning(tctx, "formname is the same\n");
2346 } else {
2347 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2348 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2351 if (devmode->copies == devmode2->copies) {
2352 torture_warning(tctx, "copies are the same\n");
2353 } else {
2354 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2355 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2358 test_ClosePrinter(tctx, b, &handle_devmode);
2360 return true;
2364 * wrapper call that saves original devmode, runs tests, and restores devmode
2367 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2368 struct dcerpc_pipe *p,
2369 struct policy_handle *handle,
2370 const char *name,
2371 struct spoolss_DeviceMode *addprinter_devmode)
2373 union spoolss_PrinterInfo info;
2374 struct spoolss_DeviceMode *devmode;
2375 bool ret = true;
2376 struct dcerpc_binding_handle *b = p->binding_handle;
2378 torture_comment(tctx, "Testing Printer Devicemodes\n");
2380 /* save original devmode */
2382 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2383 "failed to get initial global devicemode");
2385 devmode = info.info8.devmode;
2387 if (addprinter_devmode) {
2388 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2389 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2393 /* run tests */
2395 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2397 /* restore original devmode */
2399 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2400 "failed to restore initial global device mode");
2402 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2403 ret ? "succeeded" : "failed");
2406 return ret;
2409 bool test_ClosePrinter(struct torture_context *tctx,
2410 struct dcerpc_binding_handle *b,
2411 struct policy_handle *handle)
2413 NTSTATUS status;
2414 struct spoolss_ClosePrinter r;
2416 r.in.handle = handle;
2417 r.out.handle = handle;
2419 torture_comment(tctx, "Testing ClosePrinter\n");
2421 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2422 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2423 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2425 return true;
2428 static bool test_GetForm_args(struct torture_context *tctx,
2429 struct dcerpc_binding_handle *b,
2430 struct policy_handle *handle,
2431 const char *form_name,
2432 uint32_t level,
2433 union spoolss_FormInfo *info_p)
2435 NTSTATUS status;
2436 struct spoolss_GetForm r;
2437 uint32_t needed;
2439 r.in.handle = handle;
2440 r.in.form_name = form_name;
2441 r.in.level = level;
2442 r.in.buffer = NULL;
2443 r.in.offered = 0;
2444 r.out.needed = &needed;
2446 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2448 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2449 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2451 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2452 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2453 r.in.buffer = &blob;
2454 r.in.offered = needed;
2455 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2456 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2458 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2460 torture_assert(tctx, r.out.info, "No form info returned");
2463 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2465 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2467 if (info_p) {
2468 *info_p = *r.out.info;
2471 return true;
2474 static bool test_GetForm(struct torture_context *tctx,
2475 struct dcerpc_binding_handle *b,
2476 struct policy_handle *handle,
2477 const char *form_name,
2478 uint32_t level)
2480 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2483 static bool test_EnumForms(struct torture_context *tctx,
2484 struct dcerpc_binding_handle *b,
2485 struct policy_handle *handle,
2486 bool print_server,
2487 uint32_t level,
2488 uint32_t *count_p,
2489 union spoolss_FormInfo **info_p)
2491 struct spoolss_EnumForms r;
2492 uint32_t needed;
2493 uint32_t count;
2494 union spoolss_FormInfo *info;
2496 r.in.handle = handle;
2497 r.in.level = level;
2498 r.in.buffer = NULL;
2499 r.in.offered = 0;
2500 r.out.needed = &needed;
2501 r.out.count = &count;
2502 r.out.info = &info;
2504 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2506 torture_assert_ntstatus_ok(tctx,
2507 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2508 "EnumForms failed");
2510 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2511 torture_skip(tctx, "EnumForms level 2 not supported");
2514 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2515 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2518 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2519 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2520 r.in.buffer = &blob;
2521 r.in.offered = needed;
2523 torture_assert_ntstatus_ok(tctx,
2524 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2525 "EnumForms failed");
2527 torture_assert(tctx, info, "No forms returned");
2530 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2532 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2534 if (info_p) {
2535 *info_p = info;
2537 if (count_p) {
2538 *count_p = count;
2541 return true;
2544 static bool test_EnumForms_all(struct torture_context *tctx,
2545 struct dcerpc_binding_handle *b,
2546 struct policy_handle *handle,
2547 bool print_server)
2549 uint32_t levels[] = { 1, 2 };
2550 int i, j;
2552 for (i=0; i<ARRAY_SIZE(levels); i++) {
2554 uint32_t count = 0;
2555 union spoolss_FormInfo *info = NULL;
2557 torture_assert(tctx,
2558 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2559 "failed to enum forms");
2561 for (j = 0; j < count; j++) {
2562 if (!print_server) {
2563 torture_assert(tctx,
2564 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2565 "failed to get form");
2570 return true;
2573 static bool test_EnumForms_find_one(struct torture_context *tctx,
2574 struct dcerpc_binding_handle *b,
2575 struct policy_handle *handle,
2576 bool print_server,
2577 const char *form_name)
2579 union spoolss_FormInfo *info;
2580 uint32_t count;
2581 bool found = false;
2582 int i;
2584 torture_assert(tctx,
2585 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2586 "failed to enumerate forms");
2588 for (i=0; i<count; i++) {
2589 if (strequal(form_name, info[i].info1.form_name)) {
2590 found = true;
2591 break;
2595 return found;
2598 static bool test_DeleteForm(struct torture_context *tctx,
2599 struct dcerpc_binding_handle *b,
2600 struct policy_handle *handle,
2601 const char *form_name,
2602 WERROR expected_result)
2604 struct spoolss_DeleteForm r;
2606 r.in.handle = handle;
2607 r.in.form_name = form_name;
2609 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2611 torture_assert_ntstatus_ok(tctx,
2612 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2613 "DeleteForm failed");
2614 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2615 "DeleteForm gave unexpected result");
2616 if (W_ERROR_IS_OK(r.out.result)) {
2617 torture_assert_ntstatus_ok(tctx,
2618 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2619 "2nd DeleteForm failed");
2620 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2621 "2nd DeleteForm failed");
2624 return true;
2627 static bool test_AddForm(struct torture_context *tctx,
2628 struct dcerpc_binding_handle *b,
2629 struct policy_handle *handle,
2630 uint32_t level,
2631 union spoolss_AddFormInfo *info,
2632 WERROR expected_result)
2634 struct spoolss_AddForm r;
2636 if (level != 1) {
2637 torture_skip(tctx, "only level 1 supported");
2640 r.in.handle = handle;
2641 r.in.level = level;
2642 r.in.info = *info;
2644 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2645 r.in.info.info1->form_name, r.in.level,
2646 r.in.info.info1->flags);
2648 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2649 "AddForm failed");
2650 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2651 "AddForm gave unexpected result");
2653 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2654 "2nd AddForm failed");
2655 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2656 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2657 "2nd AddForm gave unexpected result");
2658 } else {
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2660 "2nd AddForm gave unexpected result");
2663 return true;
2666 static bool test_SetForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 const char *form_name,
2670 uint32_t level,
2671 union spoolss_AddFormInfo *info)
2673 struct spoolss_SetForm r;
2675 r.in.handle = handle;
2676 r.in.form_name = form_name;
2677 r.in.level = level;
2678 r.in.info = *info;
2680 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2681 form_name, r.in.level);
2683 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2684 "SetForm failed");
2686 torture_assert_werr_ok(tctx, r.out.result,
2687 "SetForm failed");
2689 return true;
2692 static bool test_GetForm_winreg(struct torture_context *tctx,
2693 struct dcerpc_binding_handle *b,
2694 struct policy_handle *handle,
2695 const char *key_name,
2696 const char *form_name,
2697 enum winreg_Type *w_type,
2698 uint32_t *w_size,
2699 uint32_t *w_length,
2700 uint8_t **w_data);
2702 static bool test_Forms_args(struct torture_context *tctx,
2703 struct dcerpc_binding_handle *b,
2704 struct policy_handle *handle,
2705 bool print_server,
2706 const char *printer_name,
2707 struct dcerpc_binding_handle *winreg_handle,
2708 struct policy_handle *hive_handle,
2709 const char *form_name,
2710 struct spoolss_AddFormInfo1 *info1,
2711 WERROR expected_add_result,
2712 WERROR expected_delete_result)
2714 union spoolss_FormInfo info;
2715 union spoolss_AddFormInfo add_info;
2717 enum winreg_Type w_type;
2718 uint32_t w_size;
2719 uint32_t w_length;
2720 uint8_t *w_data;
2722 add_info.info1 = info1;
2724 torture_assert(tctx,
2725 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2726 "failed to add form");
2728 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2730 struct spoolss_FormInfo1 i1;
2732 torture_assert(tctx,
2733 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2734 "failed to get form via winreg");
2736 i1.size.width = IVAL(w_data, 0);
2737 i1.size.height = IVAL(w_data, 4);
2738 i1.area.left = IVAL(w_data, 8);
2739 i1.area.top = IVAL(w_data, 12);
2740 i1.area.right = IVAL(w_data, 16);
2741 i1.area.bottom = IVAL(w_data, 20);
2742 /* skip index here */
2743 i1.flags = IVAL(w_data, 28);
2745 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2746 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2747 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2748 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2749 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2750 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2751 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2752 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2753 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2754 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2757 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2758 torture_assert(tctx,
2759 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2760 "failed to get added form");
2762 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2763 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2764 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2765 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2766 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2767 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2768 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2770 if (winreg_handle && hive_handle) {
2772 struct spoolss_FormInfo1 i1;
2774 i1.size.width = IVAL(w_data, 0);
2775 i1.size.height = IVAL(w_data, 4);
2776 i1.area.left = IVAL(w_data, 8);
2777 i1.area.top = IVAL(w_data, 12);
2778 i1.area.right = IVAL(w_data, 16);
2779 i1.area.bottom = IVAL(w_data, 20);
2780 /* skip index here */
2781 i1.flags = IVAL(w_data, 28);
2783 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2784 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2785 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2786 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2787 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2788 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2789 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2792 add_info.info1->size.width = 1234;
2794 torture_assert(tctx,
2795 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2796 "failed to set form");
2797 torture_assert(tctx,
2798 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2799 "failed to get setted form");
2801 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2804 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2805 torture_assert(tctx,
2806 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2807 "Newly added form not found in enum call");
2810 torture_assert(tctx,
2811 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2812 "failed to delete form");
2814 return true;
2817 static bool test_Forms(struct torture_context *tctx,
2818 struct dcerpc_binding_handle *b,
2819 struct policy_handle *handle,
2820 bool print_server,
2821 const char *printer_name,
2822 struct dcerpc_binding_handle *winreg_handle,
2823 struct policy_handle *hive_handle)
2825 const struct spoolss_FormSize size = {
2826 .width = 50,
2827 .height = 25
2829 const struct spoolss_FormArea area = {
2830 .left = 5,
2831 .top = 10,
2832 .right = 45,
2833 .bottom = 15
2835 int i;
2837 struct {
2838 struct spoolss_AddFormInfo1 info1;
2839 WERROR expected_add_result;
2840 WERROR expected_delete_result;
2841 } forms[] = {
2843 .info1 = {
2844 .flags = SPOOLSS_FORM_USER,
2845 .form_name = "testform_user",
2846 .size = size,
2847 .area = area,
2849 .expected_add_result = WERR_OK,
2850 .expected_delete_result = WERR_OK
2853 weird, we can add a builtin form but we can never remove it
2854 again - gd
2857 .info1 = {
2858 .flags = SPOOLSS_FORM_BUILTIN,
2859 .form_name = "testform_builtin",
2860 .size = size,
2861 .area = area,
2863 .expected_add_result = WERR_OK,
2864 .expected_delete_result = WERR_INVALID_PARAM,
2868 .info1 = {
2869 .flags = SPOOLSS_FORM_PRINTER,
2870 .form_name = "testform_printer",
2871 .size = size,
2872 .area = area,
2874 .expected_add_result = WERR_OK,
2875 .expected_delete_result = WERR_OK
2878 .info1 = {
2879 .flags = SPOOLSS_FORM_USER,
2880 .form_name = "Letter",
2881 .size = size,
2882 .area = area,
2884 .expected_add_result = WERR_FILE_EXISTS,
2885 .expected_delete_result = WERR_INVALID_PARAM
2888 .info1 = {
2889 .flags = SPOOLSS_FORM_BUILTIN,
2890 .form_name = "Letter",
2891 .size = size,
2892 .area = area,
2894 .expected_add_result = WERR_FILE_EXISTS,
2895 .expected_delete_result = WERR_INVALID_PARAM
2898 .info1 = {
2899 .flags = SPOOLSS_FORM_PRINTER,
2900 .form_name = "Letter",
2901 .size = size,
2902 .area = area,
2904 .expected_add_result = WERR_FILE_EXISTS,
2905 .expected_delete_result = WERR_INVALID_PARAM
2908 .info1 = {
2909 .flags = 12345,
2910 .form_name = "invalid_flags",
2911 .size = size,
2912 .area = area,
2914 .expected_add_result = WERR_INVALID_PARAM,
2915 .expected_delete_result = WERR_INVALID_FORM_NAME
2920 for (i=0; i < ARRAY_SIZE(forms); i++) {
2921 torture_assert(tctx,
2922 test_Forms_args(tctx, b, handle, print_server, printer_name,
2923 winreg_handle, hive_handle,
2924 forms[i].info1.form_name,
2925 &forms[i].info1,
2926 forms[i].expected_add_result,
2927 forms[i].expected_delete_result),
2928 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2931 return true;
2934 static bool test_EnumPorts_old(struct torture_context *tctx,
2935 void *private_data)
2937 struct test_spoolss_context *ctx =
2938 talloc_get_type_abort(private_data, struct test_spoolss_context);
2940 NTSTATUS status;
2941 struct spoolss_EnumPorts r;
2942 uint32_t needed;
2943 uint32_t count;
2944 union spoolss_PortInfo *info;
2945 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2946 struct dcerpc_binding_handle *b = p->binding_handle;
2948 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2949 dcerpc_server_name(p));
2950 r.in.level = 2;
2951 r.in.buffer = NULL;
2952 r.in.offered = 0;
2953 r.out.needed = &needed;
2954 r.out.count = &count;
2955 r.out.info = &info;
2957 torture_comment(tctx, "Testing EnumPorts\n");
2959 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2961 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2963 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2964 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2965 r.in.buffer = &blob;
2966 r.in.offered = needed;
2968 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2969 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2970 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2972 torture_assert(tctx, info, "No ports returned");
2975 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2977 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
2979 return true;
2982 static bool test_AddPort(struct torture_context *tctx,
2983 void *private_data)
2985 struct test_spoolss_context *ctx =
2986 talloc_get_type_abort(private_data, struct test_spoolss_context);
2988 NTSTATUS status;
2989 struct spoolss_AddPort r;
2990 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2991 struct dcerpc_binding_handle *b = p->binding_handle;
2993 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2994 dcerpc_server_name(p));
2995 r.in.unknown = 0;
2996 r.in.monitor_name = "foo";
2998 torture_comment(tctx, "Testing AddPort\n");
3000 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3002 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3004 /* win2k3 returns WERR_NOT_SUPPORTED */
3006 #if 0
3008 if (!W_ERROR_IS_OK(r.out.result)) {
3009 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3010 return false;
3013 #endif
3015 return true;
3018 static bool test_GetJob_args(struct torture_context *tctx,
3019 struct dcerpc_binding_handle *b,
3020 struct policy_handle *handle,
3021 uint32_t job_id,
3022 uint32_t level,
3023 union spoolss_JobInfo *info_p)
3025 NTSTATUS status;
3026 struct spoolss_GetJob r;
3027 union spoolss_JobInfo info;
3028 uint32_t needed;
3030 r.in.handle = handle;
3031 r.in.job_id = job_id;
3032 r.in.level = level;
3033 r.in.buffer = NULL;
3034 r.in.offered = 0;
3035 r.out.needed = &needed;
3036 r.out.info = &info;
3038 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3040 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3041 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3042 if (level == 0) {
3043 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3046 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3047 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3048 r.in.buffer = &blob;
3049 r.in.offered = needed;
3051 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3052 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3055 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3056 torture_assert(tctx, r.out.info, "No job info returned");
3058 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3060 if (info_p) {
3061 *info_p = *r.out.info;
3064 return true;
3067 static bool test_GetJob(struct torture_context *tctx,
3068 struct dcerpc_binding_handle *b,
3069 struct policy_handle *handle,
3070 uint32_t job_id)
3072 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3073 uint32_t i;
3075 for (i=0; i < ARRAY_SIZE(levels); i++) {
3076 torture_assert(tctx,
3077 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3078 "GetJob failed");
3081 return true;
3084 static bool test_SetJob(struct torture_context *tctx,
3085 struct dcerpc_binding_handle *b,
3086 struct policy_handle *handle,
3087 uint32_t job_id,
3088 struct spoolss_JobInfoContainer *ctr,
3089 enum spoolss_JobControl command)
3091 NTSTATUS status;
3092 struct spoolss_SetJob r;
3094 r.in.handle = handle;
3095 r.in.job_id = job_id;
3096 r.in.ctr = ctr;
3097 r.in.command = command;
3099 switch (command) {
3100 case SPOOLSS_JOB_CONTROL_PAUSE:
3101 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3102 break;
3103 case SPOOLSS_JOB_CONTROL_RESUME:
3104 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3105 break;
3106 case SPOOLSS_JOB_CONTROL_CANCEL:
3107 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3108 break;
3109 case SPOOLSS_JOB_CONTROL_RESTART:
3110 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3111 break;
3112 case SPOOLSS_JOB_CONTROL_DELETE:
3113 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3114 break;
3115 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3116 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3117 break;
3118 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3119 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3120 break;
3121 case SPOOLSS_JOB_CONTROL_RETAIN:
3122 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3123 break;
3124 case SPOOLSS_JOB_CONTROL_RELEASE:
3125 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3126 break;
3127 default:
3128 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3129 break;
3132 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3133 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3134 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3136 return true;
3139 static bool test_AddJob(struct torture_context *tctx,
3140 struct dcerpc_binding_handle *b,
3141 struct policy_handle *handle)
3143 NTSTATUS status;
3144 struct spoolss_AddJob r;
3145 uint32_t needed;
3147 r.in.level = 0;
3148 r.in.handle = handle;
3149 r.in.offered = 0;
3150 r.out.needed = &needed;
3151 r.in.buffer = r.out.buffer = NULL;
3153 torture_comment(tctx, "Testing AddJob\n");
3155 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3156 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3158 r.in.level = 1;
3160 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3161 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3163 return true;
3167 static bool test_EnumJobs_args(struct torture_context *tctx,
3168 struct dcerpc_binding_handle *b,
3169 struct policy_handle *handle,
3170 uint32_t level,
3171 uint32_t *count_p,
3172 union spoolss_JobInfo **info_p)
3174 NTSTATUS status;
3175 struct spoolss_EnumJobs r;
3176 uint32_t needed;
3177 uint32_t count;
3178 union spoolss_JobInfo *info;
3180 r.in.handle = handle;
3181 r.in.firstjob = 0;
3182 r.in.numjobs = 0xffffffff;
3183 r.in.level = level;
3184 r.in.buffer = NULL;
3185 r.in.offered = 0;
3186 r.out.needed = &needed;
3187 r.out.count = &count;
3188 r.out.info = &info;
3190 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3192 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3194 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3196 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3197 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3198 r.in.buffer = &blob;
3199 r.in.offered = needed;
3201 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3203 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3204 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3205 torture_assert(tctx, info, "No jobs returned");
3207 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3209 } else {
3210 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3213 if (count_p) {
3214 *count_p = count;
3216 if (info_p) {
3217 *info_p = info;
3220 return true;
3223 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3224 struct dcerpc_binding_handle *b,
3225 struct policy_handle *handle,
3226 uint32_t *job_id)
3228 NTSTATUS status;
3229 struct spoolss_StartDocPrinter s;
3230 struct spoolss_DocumentInfo1 info1;
3231 struct spoolss_StartPagePrinter sp;
3232 struct spoolss_WritePrinter w;
3233 struct spoolss_EndPagePrinter ep;
3234 struct spoolss_EndDocPrinter e;
3235 int i;
3236 uint32_t num_written;
3238 torture_comment(tctx, "Testing StartDocPrinter\n");
3240 s.in.handle = handle;
3241 s.in.level = 1;
3242 s.in.info.info1 = &info1;
3243 s.out.job_id = job_id;
3244 info1.document_name = "TorturePrintJob";
3245 info1.output_file = NULL;
3246 info1.datatype = "RAW";
3248 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3249 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3250 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3252 for (i=1; i < 4; i++) {
3253 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3255 sp.in.handle = handle;
3257 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3258 torture_assert_ntstatus_ok(tctx, status,
3259 "dcerpc_spoolss_StartPagePrinter failed");
3260 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3262 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3264 w.in.handle = handle;
3265 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3266 w.out.num_written = &num_written;
3268 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3269 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3270 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3272 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3274 ep.in.handle = handle;
3276 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3277 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3278 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3281 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3283 e.in.handle = handle;
3285 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3286 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3287 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3289 return true;
3292 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3293 struct dcerpc_binding_handle *b,
3294 struct policy_handle *handle,
3295 uint32_t num_jobs,
3296 uint32_t *job_ids)
3298 uint32_t count;
3299 union spoolss_JobInfo *info = NULL;
3300 int i;
3302 torture_assert(tctx,
3303 test_AddJob(tctx, b, handle),
3304 "AddJob failed");
3306 torture_assert(tctx,
3307 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3308 "EnumJobs level 1 failed");
3310 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3312 for (i=0; i < num_jobs; i++) {
3313 union spoolss_JobInfo ginfo;
3314 const char *document_name;
3315 const char *new_document_name = "any_other_docname";
3316 struct spoolss_JobInfoContainer ctr;
3317 struct spoolss_SetJobInfo1 info1;
3319 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3321 torture_assert(tctx,
3322 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3323 "failed to call test_GetJob");
3325 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3327 document_name = ginfo.info1.document_name;
3329 info1.job_id = ginfo.info1.job_id;
3330 info1.printer_name = ginfo.info1.printer_name;
3331 info1.server_name = ginfo.info1.server_name;
3332 info1.user_name = ginfo.info1.user_name;
3333 info1.document_name = new_document_name;
3334 info1.data_type = ginfo.info1.data_type;
3335 info1.text_status = ginfo.info1.text_status;
3336 info1.status = ginfo.info1.status;
3337 info1.priority = ginfo.info1.priority;
3338 info1.position = ginfo.info1.position;
3339 info1.total_pages = ginfo.info1.total_pages;
3340 info1.pages_printed = ginfo.info1.pages_printed;
3341 info1.submitted = ginfo.info1.submitted;
3343 ctr.level = 1;
3344 ctr.info.info1 = &info1;
3346 torture_assert(tctx,
3347 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3348 "failed to call test_SetJob level 1");
3350 torture_assert(tctx,
3351 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3352 "failed to call test_GetJob");
3354 if (strequal(ginfo.info1.document_name, document_name)) {
3355 torture_warning(tctx,
3356 "document_name did *NOT* change from '%s' to '%s'\n",
3357 document_name, new_document_name);
3361 for (i=0; i < num_jobs; i++) {
3362 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3363 torture_warning(tctx, "failed to pause printjob\n");
3365 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3366 torture_warning(tctx, "failed to resume printjob\n");
3370 return true;
3373 static bool test_DoPrintTest(struct torture_context *tctx,
3374 struct dcerpc_binding_handle *b,
3375 struct policy_handle *handle)
3377 bool ret = true;
3378 uint32_t num_jobs = 8;
3379 uint32_t *job_ids;
3380 int i;
3382 torture_comment(tctx, "Testing real print operations\n");
3384 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3386 for (i=0; i < num_jobs; i++) {
3387 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3390 for (i=0; i < num_jobs; i++) {
3391 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3394 if (ret == true) {
3395 torture_comment(tctx, "real print operations test succeeded\n\n");
3398 return ret;
3401 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3402 struct dcerpc_binding_handle *b,
3403 struct policy_handle *handle)
3405 bool ret = true;
3406 uint32_t num_jobs = 8;
3407 uint32_t *job_ids;
3408 int i;
3409 torture_comment(tctx, "Testing real print operations (extended)\n");
3411 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3413 for (i=0; i < num_jobs; i++) {
3414 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3417 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3419 for (i=0; i < num_jobs; i++) {
3420 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3423 if (ret == true) {
3424 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3427 return ret;
3430 static bool test_PausePrinter(struct torture_context *tctx,
3431 struct dcerpc_binding_handle *b,
3432 struct policy_handle *handle)
3434 NTSTATUS status;
3435 struct spoolss_SetPrinter r;
3436 struct spoolss_SetPrinterInfoCtr info_ctr;
3437 struct spoolss_DevmodeContainer devmode_ctr;
3438 struct sec_desc_buf secdesc_ctr;
3440 info_ctr.level = 0;
3441 info_ctr.info.info0 = NULL;
3443 ZERO_STRUCT(devmode_ctr);
3444 ZERO_STRUCT(secdesc_ctr);
3446 r.in.handle = handle;
3447 r.in.info_ctr = &info_ctr;
3448 r.in.devmode_ctr = &devmode_ctr;
3449 r.in.secdesc_ctr = &secdesc_ctr;
3450 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3452 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3454 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3456 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3458 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3460 return true;
3463 static bool test_ResumePrinter(struct torture_context *tctx,
3464 struct dcerpc_binding_handle *b,
3465 struct policy_handle *handle)
3467 NTSTATUS status;
3468 struct spoolss_SetPrinter r;
3469 struct spoolss_SetPrinterInfoCtr info_ctr;
3470 struct spoolss_DevmodeContainer devmode_ctr;
3471 struct sec_desc_buf secdesc_ctr;
3473 info_ctr.level = 0;
3474 info_ctr.info.info0 = NULL;
3476 ZERO_STRUCT(devmode_ctr);
3477 ZERO_STRUCT(secdesc_ctr);
3479 r.in.handle = handle;
3480 r.in.info_ctr = &info_ctr;
3481 r.in.devmode_ctr = &devmode_ctr;
3482 r.in.secdesc_ctr = &secdesc_ctr;
3483 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3485 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3487 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3489 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3491 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3493 return true;
3496 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3497 struct dcerpc_binding_handle *b,
3498 struct policy_handle *handle,
3499 const char *value_name,
3500 enum winreg_Type *expected_type,
3501 enum winreg_Type *type_p,
3502 uint8_t **data_p,
3503 uint32_t *needed_p)
3505 NTSTATUS status;
3506 struct spoolss_GetPrinterData r;
3507 uint32_t needed;
3508 enum winreg_Type type;
3509 union spoolss_PrinterData data;
3511 r.in.handle = handle;
3512 r.in.value_name = value_name;
3513 r.in.offered = 0;
3514 r.out.needed = &needed;
3515 r.out.type = &type;
3516 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3518 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3520 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3521 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3523 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3524 if (expected_type) {
3525 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3527 r.in.offered = needed;
3528 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3529 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3530 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3533 torture_assert_werr_ok(tctx, r.out.result,
3534 talloc_asprintf(tctx, "GetPrinterData(%s) failed", 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_GetPrinterData(struct torture_context *tctx,
3554 struct dcerpc_binding_handle *b,
3555 struct policy_handle *handle,
3556 const char *value_name,
3557 enum winreg_Type *type_p,
3558 uint8_t **data_p,
3559 uint32_t *needed_p)
3561 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3562 NULL, type_p, data_p, needed_p);
3565 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3566 struct dcerpc_pipe *p,
3567 struct policy_handle *handle,
3568 const char *key_name,
3569 const char *value_name,
3570 enum winreg_Type *expected_type,
3571 enum winreg_Type *type_p,
3572 uint8_t **data_p,
3573 uint32_t *needed_p)
3575 NTSTATUS status;
3576 struct spoolss_GetPrinterDataEx r;
3577 enum winreg_Type type;
3578 uint32_t needed;
3579 union spoolss_PrinterData data;
3580 struct dcerpc_binding_handle *b = p->binding_handle;
3582 r.in.handle = handle;
3583 r.in.key_name = key_name;
3584 r.in.value_name = value_name;
3585 r.in.offered = 0;
3586 r.out.type = &type;
3587 r.out.needed = &needed;
3588 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3590 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3591 r.in.key_name, r.in.value_name);
3593 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3594 if (!NT_STATUS_IS_OK(status)) {
3595 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3596 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3598 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3601 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3602 if (expected_type) {
3603 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3605 r.in.offered = needed;
3606 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3607 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3608 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3611 torture_assert_werr_ok(tctx, r.out.result,
3612 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3614 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3616 if (type_p) {
3617 *type_p = type;
3620 if (data_p) {
3621 *data_p = r.out.data;
3624 if (needed_p) {
3625 *needed_p = needed;
3628 return true;
3631 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3632 struct dcerpc_pipe *p,
3633 struct policy_handle *handle,
3634 const char *key_name,
3635 const char *value_name,
3636 enum winreg_Type *type_p,
3637 uint8_t **data_p,
3638 uint32_t *needed_p)
3640 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3641 NULL, type_p, data_p, needed_p);
3644 static bool test_get_environment(struct torture_context *tctx,
3645 struct dcerpc_binding_handle *b,
3646 struct policy_handle *handle,
3647 const char **architecture)
3649 DATA_BLOB blob;
3650 enum winreg_Type type;
3651 uint8_t *data;
3652 uint32_t needed;
3654 torture_assert(tctx,
3655 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3656 "failed to get Architecture");
3658 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3660 blob = data_blob_const(data, needed);
3661 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3663 return true;
3666 static bool test_GetPrinterData_list(struct torture_context *tctx,
3667 void *private_data)
3669 struct test_spoolss_context *ctx =
3670 talloc_get_type_abort(private_data, struct test_spoolss_context);
3671 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3672 struct dcerpc_binding_handle *b = p->binding_handle;
3673 const char *list[] = {
3674 "W3SvcInstalled",
3675 "BeepEnabled",
3676 "EventLog",
3677 /* "NetPopup", not on w2k8 */
3678 /* "NetPopupToComputer", not on w2k8 */
3679 "MajorVersion",
3680 "MinorVersion",
3681 "DefaultSpoolDirectory",
3682 "Architecture",
3683 "DsPresent",
3684 "OSVersion",
3685 /* "OSVersionEx", not on s3 */
3686 "DNSMachineName"
3688 int i;
3690 for (i=0; i < ARRAY_SIZE(list); i++) {
3691 enum winreg_Type type, type_ex;
3692 uint8_t *data, *data_ex;
3693 uint32_t needed, needed_ex;
3695 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3696 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3697 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3698 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3699 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3700 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3701 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3704 return true;
3707 static bool test_EnumPrinterData(struct torture_context *tctx,
3708 struct dcerpc_pipe *p,
3709 struct policy_handle *handle,
3710 uint32_t enum_index,
3711 uint32_t value_offered,
3712 uint32_t data_offered,
3713 enum winreg_Type *type_p,
3714 uint32_t *value_needed_p,
3715 uint32_t *data_needed_p,
3716 const char **value_name_p,
3717 uint8_t **data_p,
3718 WERROR *result_p)
3720 struct spoolss_EnumPrinterData r;
3721 uint32_t data_needed;
3722 uint32_t value_needed;
3723 enum winreg_Type type;
3724 struct dcerpc_binding_handle *b = p->binding_handle;
3726 r.in.handle = handle;
3727 r.in.enum_index = enum_index;
3728 r.in.value_offered = value_offered;
3729 r.in.data_offered = data_offered;
3730 r.out.data_needed = &data_needed;
3731 r.out.value_needed = &value_needed;
3732 r.out.type = &type;
3733 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3734 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3736 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3738 torture_assert_ntstatus_ok(tctx,
3739 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3740 "EnumPrinterData failed");
3742 if (type_p) {
3743 *type_p = type;
3745 if (value_needed_p) {
3746 *value_needed_p = value_needed;
3748 if (data_needed_p) {
3749 *data_needed_p = data_needed;
3751 if (value_name_p) {
3752 *value_name_p = r.out.value_name;
3754 if (data_p) {
3755 *data_p = r.out.data;
3757 if (result_p) {
3758 *result_p = r.out.result;
3761 return true;
3765 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3766 struct dcerpc_pipe *p,
3767 struct policy_handle *handle)
3769 uint32_t enum_index = 0;
3770 enum winreg_Type type;
3771 uint32_t value_needed;
3772 uint32_t data_needed;
3773 uint8_t *data;
3774 const char *value_name;
3775 WERROR result;
3777 torture_comment(tctx, "Testing EnumPrinterData\n");
3779 do {
3780 torture_assert(tctx,
3781 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3782 &type, &value_needed, &data_needed,
3783 &value_name, &data, &result),
3784 "EnumPrinterData failed");
3786 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3787 break;
3790 torture_assert(tctx,
3791 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3792 &type, &value_needed, &data_needed,
3793 &value_name, &data, &result),
3794 "EnumPrinterData failed");
3796 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3797 break;
3800 enum_index++;
3802 } while (W_ERROR_IS_OK(result));
3804 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3806 return true;
3809 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3810 struct dcerpc_binding_handle *b,
3811 struct policy_handle *handle,
3812 const char *key_name,
3813 uint32_t *count_p,
3814 struct spoolss_PrinterEnumValues **info_p)
3816 struct spoolss_EnumPrinterDataEx r;
3817 struct spoolss_PrinterEnumValues *info;
3818 uint32_t needed;
3819 uint32_t count;
3821 r.in.handle = handle;
3822 r.in.key_name = key_name;
3823 r.in.offered = 0;
3824 r.out.needed = &needed;
3825 r.out.count = &count;
3826 r.out.info = &info;
3828 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3830 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3831 "EnumPrinterDataEx failed");
3832 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3833 r.in.offered = needed;
3834 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3835 "EnumPrinterDataEx failed");
3838 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3840 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3842 if (count_p) {
3843 *count_p = count;
3845 if (info_p) {
3846 *info_p = info;
3849 return true;
3852 static bool test_SetPrinterData(struct torture_context *tctx,
3853 struct dcerpc_binding_handle *b,
3854 struct policy_handle *handle,
3855 const char *value_name,
3856 enum winreg_Type type,
3857 uint8_t *data,
3858 uint32_t offered);
3859 static bool test_DeletePrinterData(struct torture_context *tctx,
3860 struct dcerpc_binding_handle *b,
3861 struct policy_handle *handle,
3862 const char *value_name);
3864 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3865 struct dcerpc_pipe *p,
3866 struct policy_handle *handle)
3868 uint32_t count;
3869 struct spoolss_PrinterEnumValues *info;
3870 int i;
3871 uint32_t value_needed, data_needed;
3872 uint32_t value_offered, data_offered;
3873 WERROR result;
3874 struct dcerpc_binding_handle *b = p->binding_handle;
3876 enum winreg_Type type;
3877 DATA_BLOB blob;
3879 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3881 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3882 type = REG_SZ;
3884 torture_assert(tctx,
3885 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3886 "SetPrinterData failed");
3888 blob = data_blob_string_const("torture_data2");
3890 torture_assert(tctx,
3891 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3892 "SetPrinterData failed");
3894 blob = data_blob_talloc(tctx, NULL, 4);
3895 SIVAL(blob.data, 0, 0x11223344);
3897 torture_assert(tctx,
3898 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3899 "SetPrinterData failed");
3901 torture_assert(tctx,
3902 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3903 "failed to call EnumPrinterDataEx");
3905 /* get the max sizes for value and data */
3907 torture_assert(tctx,
3908 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3909 NULL, &value_needed, &data_needed,
3910 NULL, NULL, &result),
3911 "EnumPrinterData failed");
3912 torture_assert_werr_ok(tctx, result, "unexpected result");
3914 /* check if the reply from the EnumPrinterData really matches max values */
3916 for (i=0; i < count; i++) {
3917 if (info[i].value_name_len > value_needed) {
3918 torture_fail(tctx,
3919 talloc_asprintf(tctx,
3920 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3921 info[i].value_name_len, value_needed));
3923 if (info[i].data_length > data_needed) {
3924 torture_fail(tctx,
3925 talloc_asprintf(tctx,
3926 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3927 info[i].data_length, data_needed));
3931 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3932 * sort or not sort the replies by value name, we should be able to do
3933 * the following entry comparison */
3935 data_offered = data_needed;
3936 value_offered = value_needed;
3938 for (i=0; i < count; i++) {
3940 const char *value_name;
3941 uint8_t *data;
3943 torture_assert(tctx,
3944 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3945 &type, &value_needed, &data_needed,
3946 &value_name, &data, &result),
3947 "EnumPrinterData failed");
3949 if (i -1 == count) {
3950 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3951 "unexpected result");
3952 break;
3953 } else {
3954 torture_assert_werr_ok(tctx, result, "unexpected result");
3957 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3958 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3959 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3960 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3961 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3964 torture_assert(tctx,
3965 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3966 "DeletePrinterData failed");
3967 torture_assert(tctx,
3968 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3969 "DeletePrinterData failed");
3970 torture_assert(tctx,
3971 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3972 "DeletePrinterData failed");
3974 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3976 return true;
3979 static bool test_DeletePrinterData(struct torture_context *tctx,
3980 struct dcerpc_binding_handle *b,
3981 struct policy_handle *handle,
3982 const char *value_name)
3984 NTSTATUS status;
3985 struct spoolss_DeletePrinterData r;
3987 r.in.handle = handle;
3988 r.in.value_name = value_name;
3990 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3991 r.in.value_name);
3993 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3995 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3996 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3998 return true;
4001 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4002 struct dcerpc_binding_handle *b,
4003 struct policy_handle *handle,
4004 const char *key_name,
4005 const char *value_name)
4007 struct spoolss_DeletePrinterDataEx r;
4009 r.in.handle = handle;
4010 r.in.key_name = key_name;
4011 r.in.value_name = value_name;
4013 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4014 r.in.key_name, r.in.value_name);
4016 torture_assert_ntstatus_ok(tctx,
4017 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4018 "DeletePrinterDataEx failed");
4019 torture_assert_werr_ok(tctx, r.out.result,
4020 "DeletePrinterDataEx failed");
4022 return true;
4025 static bool test_DeletePrinterKey(struct torture_context *tctx,
4026 struct dcerpc_binding_handle *b,
4027 struct policy_handle *handle,
4028 const char *key_name)
4030 struct spoolss_DeletePrinterKey r;
4032 r.in.handle = handle;
4033 r.in.key_name = key_name;
4035 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4037 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4038 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4039 return true;
4042 torture_assert_ntstatus_ok(tctx,
4043 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4044 "DeletePrinterKey failed");
4045 torture_assert_werr_ok(tctx, r.out.result,
4046 "DeletePrinterKey failed");
4048 return true;
4051 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4052 struct dcerpc_binding_handle *b,
4053 struct policy_handle *handle)
4055 struct winreg_OpenHKLM r;
4057 r.in.system_name = NULL;
4058 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4059 r.out.handle = handle;
4061 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4063 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4064 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4066 return true;
4069 static void init_winreg_String(struct winreg_String *name, const char *s)
4071 name->name = s;
4072 if (s) {
4073 name->name_len = 2 * (strlen_m(s) + 1);
4074 name->name_size = name->name_len;
4075 } else {
4076 name->name_len = 0;
4077 name->name_size = 0;
4081 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4082 struct dcerpc_binding_handle *b,
4083 struct policy_handle *hive_handle,
4084 const char *keyname,
4085 uint32_t options,
4086 struct policy_handle *key_handle)
4088 struct winreg_OpenKey r;
4090 r.in.parent_handle = hive_handle;
4091 init_winreg_String(&r.in.keyname, keyname);
4092 r.in.options = options;
4093 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4094 r.out.handle = key_handle;
4096 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4098 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4099 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4101 return true;
4104 static bool test_winreg_OpenKey(struct torture_context *tctx,
4105 struct dcerpc_binding_handle *b,
4106 struct policy_handle *hive_handle,
4107 const char *keyname,
4108 struct policy_handle *key_handle)
4110 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4111 REG_OPTION_NON_VOLATILE, key_handle);
4114 static bool test_winreg_CloseKey(struct torture_context *tctx,
4115 struct dcerpc_binding_handle *b,
4116 struct policy_handle *handle)
4118 struct winreg_CloseKey r;
4120 r.in.handle = handle;
4121 r.out.handle = handle;
4123 torture_comment(tctx, "Testing winreg_CloseKey\n");
4125 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4126 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4128 return true;
4131 bool test_winreg_QueryValue(struct torture_context *tctx,
4132 struct dcerpc_binding_handle *b,
4133 struct policy_handle *handle,
4134 const char *value_name,
4135 enum winreg_Type *type_p,
4136 uint32_t *data_size_p,
4137 uint32_t *data_length_p,
4138 uint8_t **data_p)
4140 struct winreg_QueryValue r;
4141 enum winreg_Type type = REG_NONE;
4142 uint32_t data_size = 0;
4143 uint32_t data_length = 0;
4144 struct winreg_String valuename;
4145 uint8_t *data = NULL;
4147 init_winreg_String(&valuename, value_name);
4149 data = talloc_zero_array(tctx, uint8_t, 0);
4151 r.in.handle = handle;
4152 r.in.value_name = &valuename;
4153 r.in.type = &type;
4154 r.in.data_size = &data_size;
4155 r.in.data_length = &data_length;
4156 r.in.data = data;
4157 r.out.type = &type;
4158 r.out.data = data;
4159 r.out.data_size = &data_size;
4160 r.out.data_length = &data_length;
4162 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4164 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4165 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4166 *r.in.data_size = *r.out.data_size;
4167 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4168 r.in.data = data;
4169 r.out.data = data;
4170 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4172 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4174 if (type_p) {
4175 *type_p = *r.out.type;
4177 if (data_size_p) {
4178 *data_size_p = *r.out.data_size;
4180 if (data_length_p) {
4181 *data_length_p = *r.out.data_length;
4183 if (data_p) {
4184 *data_p = r.out.data;
4187 return true;
4190 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4191 struct dcerpc_binding_handle *b,
4192 struct policy_handle *handle,
4193 const char *printer_name,
4194 const char *key_name,
4195 const char *value_name,
4196 enum winreg_Type *w_type,
4197 uint32_t *w_size,
4198 uint32_t *w_length,
4199 uint8_t **w_data)
4201 const char *printer_key;
4202 struct policy_handle key_handle;
4204 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4205 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4207 torture_assert(tctx,
4208 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4210 torture_assert(tctx,
4211 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4213 torture_assert(tctx,
4214 test_winreg_CloseKey(tctx, b, &key_handle), "");
4216 return true;
4219 static bool test_GetForm_winreg(struct torture_context *tctx,
4220 struct dcerpc_binding_handle *b,
4221 struct policy_handle *handle,
4222 const char *key_name,
4223 const char *form_name,
4224 enum winreg_Type *w_type,
4225 uint32_t *w_size,
4226 uint32_t *w_length,
4227 uint8_t **w_data)
4229 struct policy_handle key_handle;
4231 torture_assert(tctx,
4232 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4234 torture_assert(tctx,
4235 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4237 torture_assert(tctx,
4238 test_winreg_CloseKey(tctx, b, &key_handle), "");
4240 return true;
4243 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4244 struct dcerpc_binding_handle *b,
4245 struct policy_handle *handle,
4246 const char *symlink_keyname,
4247 const char *symlink_destination)
4249 /* check if the first key is a symlink to the second key */
4251 enum winreg_Type w_type;
4252 uint32_t w_size;
4253 uint32_t w_length;
4254 uint8_t *w_data;
4255 struct policy_handle key_handle;
4256 DATA_BLOB blob;
4257 const char *str;
4259 if (torture_setting_bool(tctx, "samba3", false)) {
4260 torture_skip(tctx, "skip winreg symlink test against samba");
4263 torture_assert(tctx,
4264 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4265 "failed to open key link");
4267 torture_assert(tctx,
4268 test_winreg_QueryValue(tctx, b, &key_handle,
4269 "SymbolicLinkValue",
4270 &w_type, &w_size, &w_length, &w_data),
4271 "failed to query for 'SymbolicLinkValue' attribute");
4273 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4275 blob = data_blob(w_data, w_size);
4276 str = reg_val_data_string(tctx, REG_SZ, blob);
4278 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4280 torture_assert(tctx,
4281 test_winreg_CloseKey(tctx, b, &key_handle),
4282 "failed to close key link");
4284 return true;
4287 static const char *strip_unc(const char *unc)
4289 char *name;
4291 if (!unc) {
4292 return NULL;
4295 if (unc[0] == '\\' && unc[1] == '\\') {
4296 unc +=2;
4299 name = strchr(unc, '\\');
4300 if (name) {
4301 return name+1;
4304 return unc;
4307 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4308 struct dcerpc_binding_handle *b,
4309 struct policy_handle *handle,
4310 const char *printer_name,
4311 struct dcerpc_binding_handle *winreg_handle,
4312 struct policy_handle *hive_handle)
4314 union spoolss_PrinterInfo info;
4315 const char *keys[] = {
4316 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4317 TOP_LEVEL_PRINT_PRINTERS_KEY
4319 int i;
4320 const char *printername, *sharename;
4322 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4324 torture_assert(tctx,
4325 test_GetPrinter_level(tctx, b, handle, 2, &info),
4326 "failed to get printer info level 2");
4328 printername = strip_unc(info.info2.printername);
4329 sharename = strip_unc(info.info2.sharename);
4331 #define test_sz(wname, iname) \
4332 do {\
4333 DATA_BLOB blob;\
4334 const char *str;\
4335 enum winreg_Type w_type;\
4336 uint32_t w_size;\
4337 uint32_t w_length;\
4338 uint8_t *w_data;\
4339 torture_assert(tctx,\
4340 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4341 &w_type, &w_size, &w_length, &w_data),\
4342 "failed to query winreg");\
4343 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4344 blob = data_blob(w_data, w_size);\
4345 str = reg_val_data_string(tctx, REG_SZ, blob);\
4346 if (w_size == 2 && iname == NULL) {\
4347 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4348 } else {\
4349 torture_assert_str_equal(tctx, str, iname,\
4350 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4352 } while(0);
4354 #define test_dword(wname, iname) \
4355 do {\
4356 uint32_t value;\
4357 enum winreg_Type w_type;\
4358 uint32_t w_size;\
4359 uint32_t w_length;\
4360 uint8_t *w_data;\
4361 torture_assert(tctx,\
4362 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4363 &w_type, &w_size, &w_length, &w_data),\
4364 "failed to query winreg");\
4365 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4366 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4367 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4368 value = IVAL(w_data, 0);\
4369 torture_assert_int_equal(tctx, value, iname,\
4370 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4371 } while(0);
4373 #define test_binary(wname, iname) \
4374 do {\
4375 enum winreg_Type w_type;\
4376 uint32_t w_size;\
4377 uint32_t w_length;\
4378 uint8_t *w_data;\
4379 torture_assert(tctx,\
4380 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4381 &w_type, &w_size, &w_length, &w_data),\
4382 "failed to query winreg");\
4383 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4384 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4385 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4386 "binary unequal");\
4387 } while(0);
4390 #define test_dm(wname, iname) \
4391 do {\
4392 DATA_BLOB blob;\
4393 struct spoolss_DeviceMode dm;\
4394 enum ndr_err_code ndr_err;\
4395 enum winreg_Type w_type;\
4396 uint32_t w_size;\
4397 uint32_t w_length;\
4398 uint8_t *w_data;\
4399 torture_assert(tctx,\
4400 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4401 &w_type, &w_size, &w_length, &w_data),\
4402 "failed to query winreg");\
4403 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4404 blob = data_blob(w_data, w_size);\
4405 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4406 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4407 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4408 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4409 "dm unequal");\
4410 } while(0);
4412 #define test_sd(wname, iname) \
4413 do {\
4414 DATA_BLOB blob;\
4415 struct security_descriptor sd;\
4416 enum ndr_err_code ndr_err;\
4417 enum winreg_Type w_type;\
4418 uint32_t w_size;\
4419 uint32_t w_length;\
4420 uint8_t *w_data;\
4421 torture_assert(tctx,\
4422 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4423 &w_type, &w_size, &w_length, &w_data),\
4424 "failed to query winreg");\
4425 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4426 blob = data_blob(w_data, w_size);\
4427 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4428 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4429 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4430 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4431 "sd unequal");\
4432 } while(0);
4434 #define test_multi_sz(wname, iname) \
4435 do {\
4436 DATA_BLOB blob;\
4437 const char **array;\
4438 enum winreg_Type w_type;\
4439 uint32_t w_size;\
4440 uint32_t w_length;\
4441 uint8_t *w_data;\
4442 int i;\
4443 torture_assert(tctx,\
4444 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4445 &w_type, &w_size, &w_length, &w_data),\
4446 "failed to query winreg");\
4447 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4448 blob = data_blob(w_data, w_size);\
4449 torture_assert(tctx, \
4450 pull_reg_multi_sz(tctx, &blob, &array),\
4451 "failed to pull multi sz");\
4452 for (i=0; array[i] != NULL; i++) {\
4453 torture_assert_str_equal(tctx, array[i], iname[i],\
4454 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4456 } while(0);
4458 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4459 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4460 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4462 torture_warning(tctx, "failed to check for winreg symlink");
4465 for (i=0; i < ARRAY_SIZE(keys); i++) {
4467 const char *printer_key;
4468 struct policy_handle key_handle;
4470 printer_key = talloc_asprintf(tctx, "%s\\%s",
4471 keys[i], printer_name);
4473 torture_assert(tctx,
4474 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4476 test_sz("Name", printername);
4477 test_sz("Share Name", sharename);
4478 test_sz("Port", info.info2.portname);
4479 test_sz("Printer Driver", info.info2.drivername);
4480 test_sz("Description", info.info2.comment);
4481 test_sz("Location", info.info2.location);
4482 test_sz("Separator File", info.info2.sepfile);
4483 test_sz("Print Processor", info.info2.printprocessor);
4484 test_sz("Datatype", info.info2.datatype);
4485 test_sz("Parameters", info.info2.parameters);
4486 /* winreg: 0, spoolss not */
4487 /* test_dword("Attributes", info.info2.attributes); */
4488 test_dword("Priority", info.info2.priority);
4489 test_dword("Default Priority", info.info2.defaultpriority);
4490 /* winreg: 60, spoolss: 0 */
4491 /* test_dword("StartTime", info.info2.starttime); */
4492 /* test_dword("UntilTime", info.info2.untiltime); */
4493 /* winreg != spoolss */
4494 /* test_dword("Status", info.info2.status); */
4495 test_dm("Default DevMode", info.info2.devmode);
4496 test_sd("Security", info.info2.secdesc);
4498 torture_assert(tctx,
4499 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4502 #undef test_dm
4503 #undef test_sd
4505 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4507 return true;
4510 static bool test_PrintProcessors(struct torture_context *tctx,
4511 struct dcerpc_binding_handle *b,
4512 const char *environment,
4513 struct dcerpc_binding_handle *winreg_handle,
4514 struct policy_handle *hive_handle)
4516 union spoolss_PrintProcessorInfo *info;
4517 uint32_t count;
4518 int i;
4520 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4522 torture_assert(tctx,
4523 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4524 "failed to enum print processors level 1");
4526 for (i=0; i < count; i++) {
4528 const char *processor_key;
4529 struct policy_handle key_handle;
4531 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4532 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4533 environment,
4534 info[i].info1.print_processor_name);
4536 torture_assert(tctx,
4537 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4539 /* nothing to check in there so far */
4541 torture_assert(tctx,
4542 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4545 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4547 return true;
4550 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4551 struct dcerpc_binding_handle *b,
4552 struct policy_handle *handle,
4553 const char *driver_name,
4554 const char *architecture,
4555 uint32_t level,
4556 uint32_t client_major_version,
4557 uint32_t client_minor_version,
4558 union spoolss_DriverInfo *info_p,
4559 WERROR *result);
4561 static const char *strip_path(const char *path)
4563 char *p;
4565 if (path == NULL) {
4566 return NULL;
4569 p = strrchr(path, '\\');
4570 if (p) {
4571 return p+1;
4574 return path;
4577 static const char **strip_paths(const char **path_array)
4579 int i;
4581 if (path_array == NULL) {
4582 return NULL;
4585 for (i=0; path_array[i] != NULL; i++) {
4586 path_array[i] = strip_path(path_array[i]);
4589 return path_array;
4592 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4594 time_t t;
4595 struct tm *tm;
4597 if (nt == 0) {
4598 return talloc_strdup(mem_ctx, "01/01/1601");
4601 t = nt_time_to_unix(nt);
4602 tm = localtime(&t);
4604 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4605 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4608 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4610 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4611 (unsigned)((v >> 48) & 0xFFFF),
4612 (unsigned)((v >> 32) & 0xFFFF),
4613 (unsigned)((v >> 16) & 0xFFFF),
4614 (unsigned)(v & 0xFFFF));
4617 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4618 struct dcerpc_binding_handle *b,
4619 struct policy_handle *handle,
4620 const char *printer_name,
4621 const char *driver_name,
4622 const char *environment,
4623 enum spoolss_DriverOSVersion version,
4624 struct dcerpc_binding_handle *winreg_handle,
4625 struct policy_handle *hive_handle,
4626 const char *server_name_slash)
4628 WERROR result;
4629 union spoolss_DriverInfo info;
4630 const char *driver_key;
4631 struct policy_handle key_handle;
4633 const char *driver_path;
4634 const char *data_file;
4635 const char *config_file;
4636 const char *help_file;
4637 const char **dependent_files;
4639 const char *driver_date;
4640 const char *inbox_driver_date;
4642 const char *driver_version;
4643 const char *inbox_driver_version;
4645 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4647 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4648 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4649 environment,
4650 version,
4651 driver_name);
4653 torture_assert(tctx,
4654 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4655 "failed to open driver key");
4657 if (torture_setting_bool(tctx, "samba3", false)) {
4658 goto try_level3;
4661 if (torture_setting_bool(tctx, "w2k3", false)) {
4662 goto try_level6;
4665 if (handle) {
4666 torture_assert(tctx,
4667 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4668 "failed to get driver info level 8");
4669 } else {
4670 torture_assert(tctx,
4671 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4672 "failed to get driver info level 8");
4675 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4676 goto try_level6;
4679 driver_path = strip_path(info.info8.driver_path);
4680 data_file = strip_path(info.info8.data_file);
4681 config_file = strip_path(info.info8.config_file);
4682 help_file = strip_path(info.info8.help_file);
4683 dependent_files = strip_paths(info.info8.dependent_files);
4685 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4686 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4688 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4689 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4691 test_sz("Configuration File", config_file);
4692 test_sz("Data File", data_file);
4693 test_sz("Datatype", info.info8.default_datatype);
4694 test_sz("Driver", driver_path);
4695 test_sz("DriverDate", driver_date);
4696 test_sz("DriverVersion", driver_version);
4697 test_sz("HardwareID", info.info8.hardware_id);
4698 test_sz("Help File", help_file);
4699 test_sz("InfPath", info.info8.inf_path);
4700 test_sz("Manufacturer", info.info8.manufacturer_name);
4701 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4702 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4703 test_sz("Monitor", info.info8.monitor_name);
4704 test_sz("OEM URL", info.info8.manufacturer_url);
4705 test_sz("Print Processor", info.info8.print_processor);
4706 test_sz("Provider", info.info8.provider);
4707 test_sz("VendorSetup", info.info8.vendor_setup);
4708 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4709 test_multi_sz("Dependent Files", dependent_files);
4710 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4711 test_multi_sz("Previous Names", info.info8.previous_names);
4712 /* test_dword("Attributes", ?); */
4713 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4714 test_dword("Version", info.info8.version);
4715 /* test_dword("TempDir", ?); */
4717 try_level6:
4719 if (handle) {
4720 torture_assert(tctx,
4721 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4722 "failed to get driver info level 6");
4723 } else {
4724 torture_assert(tctx,
4725 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4726 "failed to get driver info level 6");
4729 driver_path = strip_path(info.info6.driver_path);
4730 data_file = strip_path(info.info6.data_file);
4731 config_file = strip_path(info.info6.config_file);
4732 help_file = strip_path(info.info6.help_file);
4733 dependent_files = strip_paths(info.info6.dependent_files);
4735 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4737 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4739 test_sz("Configuration File", config_file);
4740 test_sz("Data File", data_file);
4741 test_sz("Datatype", info.info6.default_datatype);
4742 test_sz("Driver", driver_path);
4743 if (torture_setting_bool(tctx, "w2k3", false)) {
4744 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4745 push_nttime(blob.data, 0, info.info6.driver_date);
4746 test_binary("DriverDate", blob);
4747 SBVAL(blob.data, 0, info.info6.driver_version);
4748 test_binary("DriverVersion", blob);
4749 } else {
4750 test_sz("DriverDate", driver_date);
4751 test_sz("DriverVersion", driver_version);
4753 test_sz("HardwareID", info.info6.hardware_id);
4754 test_sz("Help File", help_file);
4755 test_sz("Manufacturer", info.info6.manufacturer_name);
4756 test_sz("Monitor", info.info6.monitor_name);
4757 test_sz("OEM URL", info.info6.manufacturer_url);
4758 test_sz("Provider", info.info6.provider);
4759 test_multi_sz("Dependent Files", dependent_files);
4760 test_multi_sz("Previous Names", info.info6.previous_names);
4761 /* test_dword("Attributes", ?); */
4762 test_dword("Version", info.info6.version);
4763 /* test_dword("TempDir", ?); */
4765 try_level3:
4767 if (handle) {
4768 torture_assert(tctx,
4769 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4770 "failed to get driver info level 3");
4771 } else {
4772 torture_assert(tctx,
4773 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4774 "failed to get driver info level 3");
4777 driver_path = strip_path(info.info3.driver_path);
4778 data_file = strip_path(info.info3.data_file);
4779 config_file = strip_path(info.info3.config_file);
4780 help_file = strip_path(info.info3.help_file);
4781 dependent_files = strip_paths(info.info3.dependent_files);
4783 test_sz("Configuration File", config_file);
4784 test_sz("Data File", data_file);
4785 test_sz("Datatype", info.info3.default_datatype);
4786 test_sz("Driver", driver_path);
4787 test_sz("Help File", help_file);
4788 test_sz("Monitor", info.info3.monitor_name);
4789 test_multi_sz("Dependent Files", dependent_files);
4790 /* test_dword("Attributes", ?); */
4791 test_dword("Version", info.info3.version);
4792 /* test_dword("TempDir", ?); */
4795 torture_assert(tctx,
4796 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4798 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4800 return true;
4803 #undef test_sz
4804 #undef test_dword
4806 static bool test_SetPrinterData(struct torture_context *tctx,
4807 struct dcerpc_binding_handle *b,
4808 struct policy_handle *handle,
4809 const char *value_name,
4810 enum winreg_Type type,
4811 uint8_t *data,
4812 uint32_t offered)
4814 struct spoolss_SetPrinterData r;
4816 r.in.handle = handle;
4817 r.in.value_name = value_name;
4818 r.in.type = type;
4819 r.in.data = data;
4820 r.in.offered = offered;
4822 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4823 r.in.value_name);
4825 torture_assert_ntstatus_ok(tctx,
4826 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4827 "SetPrinterData failed");
4828 torture_assert_werr_ok(tctx, r.out.result,
4829 "SetPrinterData failed");
4831 return true;
4834 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4835 struct dcerpc_binding_handle *b,
4836 struct policy_handle *handle,
4837 const char *printer_name,
4838 struct dcerpc_binding_handle *winreg_handle,
4839 struct policy_handle *hive_handle)
4841 const char *values[] = {
4842 "spootyfoot",
4843 "spooty\\foot",
4844 #if 0
4845 /* FIXME: not working with s3 atm. */
4846 "spooty,foot",
4847 "spooty,fo,ot",
4848 #endif
4849 "spooty foot",
4850 #if 0
4851 /* FIXME: not working with s3 atm. */
4852 "spooty\\fo,ot",
4853 "spooty,fo\\ot"
4854 #endif
4856 int i;
4858 for (i=0; i < ARRAY_SIZE(values); i++) {
4860 enum winreg_Type type, expected_type = REG_SZ;
4861 DATA_BLOB blob;
4862 uint8_t *data;
4863 uint32_t needed;
4865 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4866 type = REG_SZ;
4868 torture_assert(tctx,
4869 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4870 "SetPrinterData failed");
4872 torture_assert(tctx,
4873 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4874 "GetPrinterData failed");
4876 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4877 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4878 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4880 if (winreg_handle && hive_handle) {
4882 enum winreg_Type w_type;
4883 uint32_t w_size;
4884 uint32_t w_length;
4885 uint8_t *w_data;
4887 torture_assert(tctx,
4888 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4889 printer_name, "PrinterDriverData", values[i],
4890 &w_type, &w_size, &w_length, &w_data), "");
4892 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4893 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4894 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4895 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4898 torture_assert(tctx,
4899 test_DeletePrinterData(tctx, b, handle, values[i]),
4900 "DeletePrinterData failed");
4903 return true;
4907 static bool test_EnumPrinterKey(struct torture_context *tctx,
4908 struct dcerpc_binding_handle *b,
4909 struct policy_handle *handle,
4910 const char *key_name,
4911 const char ***array);
4913 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4914 struct dcerpc_binding_handle *b,
4915 struct policy_handle *handle,
4916 const char *key_name,
4917 const char *value_name,
4918 enum winreg_Type type,
4919 uint8_t *data,
4920 uint32_t offered)
4922 NTSTATUS status;
4923 struct spoolss_SetPrinterDataEx r;
4925 r.in.handle = handle;
4926 r.in.key_name = key_name;
4927 r.in.value_name = value_name;
4928 r.in.type = type;
4929 r.in.data = data;
4930 r.in.offered = offered;
4932 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4933 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4935 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4937 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4938 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4940 return true;
4943 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4944 struct dcerpc_pipe *p,
4945 struct policy_handle *handle)
4947 struct dcerpc_binding_handle *b = p->binding_handle;
4948 const char *value_name = "dog";
4949 const char *keys[] = {
4950 "torturedataex",
4951 "torture data ex",
4952 "torturedataex_with_subkey\\subkey",
4953 "torturedataex_with_subkey\\subkey:0",
4954 "torturedataex_with_subkey\\subkey:1",
4955 "torturedataex_with_subkey\\subkey\\subsubkey",
4956 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4957 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4958 "torture,data",
4959 "torture,data,ex",
4960 "torture,data\\ex",
4961 "torture\\data,ex",
4962 "torture/data",
4963 "torture/data ex",
4964 "torture/data ex/sub",
4965 "torture//data",
4966 "torture//data ex",
4967 "torture//data ex/sub",
4968 "torture//data ex//sub",
4970 int i;
4972 for (i=0; i < ARRAY_SIZE(keys); i++) {
4974 char *c;
4975 const char *key;
4976 enum winreg_Type type;
4977 DATA_BLOB blob_in, blob_out;
4978 const char **subkeys;
4979 uint32_t ecount;
4980 struct spoolss_PrinterEnumValues *einfo;
4981 uint32_t needed;
4983 blob_in = data_blob_talloc(tctx, NULL, 42);
4985 generate_random_buffer(blob_in.data, blob_in.length);
4987 torture_assert(tctx,
4988 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
4989 "failed to call SetPrinterDataEx");
4991 torture_assert(tctx,
4992 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
4993 "failed to call GetPrinterDataEx");
4995 blob_out.length = needed;
4996 torture_assert(tctx,
4997 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4998 "failed to call EnumPrinterDataEx");
5000 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5001 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5002 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5004 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5005 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5006 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5007 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5008 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5009 if (einfo[0].data_length > 0) {
5010 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5013 key = talloc_strdup(tctx, keys[i]);
5015 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5016 return false;
5019 c = strchr(key, '\\');
5020 if (c) {
5021 int k;
5023 /* we have subkeys */
5025 *c = 0;
5027 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5028 return false;
5031 for (k=0; subkeys && subkeys[k]; k++) {
5033 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5035 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5036 return false;
5040 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5041 return false;
5044 } else {
5045 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5046 return false;
5051 return true;
5054 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5055 struct dcerpc_pipe *p,
5056 struct policy_handle *handle)
5058 struct dcerpc_binding_handle *b = p->binding_handle;
5059 const char *key = "torturedataex";
5060 const char *values[] = {
5061 "torture_value",
5062 "torture value",
5063 "torture,value",
5064 "torture/value",
5065 "torture\\value",
5066 "torture\\\\value"
5068 int i;
5070 for (i=0; i < ARRAY_SIZE(values); i++) {
5072 enum winreg_Type type;
5073 DATA_BLOB blob_in, blob_out;
5074 uint32_t ecount;
5075 struct spoolss_PrinterEnumValues *einfo;
5076 uint32_t needed;
5078 if (torture_setting_bool(tctx, "samba3", false)) {
5079 char *q;
5080 q = strrchr(values[i], ',');
5081 if (q) {
5082 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5083 values[i]);
5084 continue;
5088 blob_in = data_blob_talloc(tctx, NULL, 42);
5090 generate_random_buffer(blob_in.data, blob_in.length);
5092 torture_assert(tctx,
5093 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5094 "failed to call SetPrinterDataEx");
5096 torture_assert(tctx,
5097 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5098 "failed to call GetPrinterDataEx");
5100 blob_out.length = needed;
5101 torture_assert(tctx,
5102 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5103 "failed to call EnumPrinterDataEx");
5105 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5106 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5107 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5109 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5110 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5111 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5112 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5113 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5114 if (einfo[0].data_length > 0) {
5115 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5118 torture_assert(tctx,
5119 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5120 "failed to call DeletePrinterDataEx");
5123 return true;
5127 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5128 struct dcerpc_pipe *p,
5129 struct policy_handle *handle,
5130 const char *printername,
5131 struct dcerpc_binding_handle *winreg_handle,
5132 struct policy_handle *hive_handle)
5134 struct dcerpc_binding_handle *b = p->binding_handle;
5135 const char *value_name = "dog";
5136 const char *key_name = "torturedataex";
5137 enum winreg_Type types[] = {
5138 REG_SZ,
5139 REG_MULTI_SZ,
5140 REG_DWORD,
5141 REG_BINARY
5143 const char *str = "abcdefghi";
5144 int t, s;
5146 for (t=0; t < ARRAY_SIZE(types); t++) {
5147 for (s=0; s < strlen(str); s++) {
5149 enum winreg_Type type;
5150 const char *string = talloc_strndup(tctx, str, s);
5151 const char *array[2];
5152 DATA_BLOB blob = data_blob_string_const(string);
5153 DATA_BLOB data;
5154 uint8_t *data_out;
5155 uint32_t needed, offered = 0;
5156 uint32_t ecount;
5157 struct spoolss_PrinterEnumValues *einfo;
5159 array[0] = talloc_strdup(tctx, string);
5160 array[1] = NULL;
5162 if (types[t] == REG_DWORD) {
5163 s = 0xffff;
5166 switch (types[t]) {
5167 case REG_BINARY:
5168 data = blob;
5169 offered = blob.length;
5170 break;
5171 case REG_DWORD:
5172 data = data_blob_talloc(tctx, NULL, 4);
5173 SIVAL(data.data, 0, 0x12345678);
5174 offered = 4;
5175 break;
5176 case REG_SZ:
5177 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5178 type = REG_SZ;
5179 offered = data.length;
5180 /*strlen_m_term(data.string)*2;*/
5181 break;
5182 case REG_MULTI_SZ:
5183 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5184 type = REG_MULTI_SZ;
5185 offered = data.length;
5186 break;
5187 default:
5188 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5191 torture_assert(tctx,
5192 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5193 "failed to call SetPrinterDataEx");
5195 torture_assert(tctx,
5196 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5197 "failed to call GetPrinterDataEx");
5199 torture_assert(tctx,
5200 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5201 "failed to call EnumPrinterDataEx");
5203 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5204 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5205 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5207 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5208 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5209 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5210 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5211 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5212 if (einfo[0].data_length > 0) {
5213 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5216 if (winreg_handle && hive_handle) {
5217 enum winreg_Type w_type;
5218 uint32_t w_size;
5219 uint32_t w_length;
5220 uint8_t *w_data;
5222 torture_assert(tctx,
5223 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5224 printername, key_name, value_name,
5225 &w_type, &w_size, &w_length, &w_data), "");
5227 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5228 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5229 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5230 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5233 torture_assert(tctx,
5234 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5235 "failed to call DeletePrinterDataEx");
5239 return true;
5242 static bool test_PrinterData_winreg(struct torture_context *tctx,
5243 struct dcerpc_pipe *p,
5244 struct policy_handle *handle,
5245 const char *printer_name)
5247 struct dcerpc_binding_handle *b = p->binding_handle;
5248 struct dcerpc_pipe *p2;
5249 bool ret = true;
5250 struct policy_handle hive_handle;
5251 struct dcerpc_binding_handle *b2;
5253 torture_assert_ntstatus_ok(tctx,
5254 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5255 "could not open winreg pipe");
5256 b2 = p2->binding_handle;
5258 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5260 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5261 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5263 test_winreg_CloseKey(tctx, b2, &hive_handle);
5265 talloc_free(p2);
5267 return ret;
5270 static bool test_Forms_winreg(struct torture_context *tctx,
5271 struct dcerpc_binding_handle *b,
5272 struct policy_handle *handle,
5273 bool print_server,
5274 const char *printer_name)
5276 struct dcerpc_pipe *p2;
5277 bool ret = true;
5278 struct policy_handle hive_handle;
5279 struct dcerpc_binding_handle *b2;
5281 torture_assert_ntstatus_ok(tctx,
5282 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5283 "could not open winreg pipe");
5284 b2 = p2->binding_handle;
5286 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5288 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5290 test_winreg_CloseKey(tctx, b2, &hive_handle);
5292 talloc_free(p2);
5294 return ret;
5297 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5298 struct dcerpc_pipe *p,
5299 struct policy_handle *handle,
5300 const char *printer_name)
5302 struct dcerpc_binding_handle *b = p->binding_handle;
5303 struct dcerpc_pipe *p2;
5304 bool ret = true;
5305 struct policy_handle hive_handle;
5306 struct dcerpc_binding_handle *b2;
5308 torture_assert_ntstatus_ok(tctx,
5309 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5310 "could not open winreg pipe");
5311 b2 = p2->binding_handle;
5313 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5315 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5317 test_winreg_CloseKey(tctx, b2, &hive_handle);
5319 talloc_free(p2);
5321 return ret;
5324 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5325 struct dcerpc_pipe *p,
5326 struct policy_handle *handle,
5327 const char *printer_name,
5328 const char *driver_name,
5329 const char *environment,
5330 enum spoolss_DriverOSVersion version)
5332 struct dcerpc_binding_handle *b = p->binding_handle;
5333 struct dcerpc_pipe *p2;
5334 bool ret = true;
5335 struct policy_handle hive_handle;
5336 struct dcerpc_binding_handle *b2;
5338 torture_assert_ntstatus_ok(tctx,
5339 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5340 "could not open winreg pipe");
5341 b2 = p2->binding_handle;
5343 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5345 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5347 test_winreg_CloseKey(tctx, b2, &hive_handle);
5349 talloc_free(p2);
5351 return ret;
5354 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5355 struct dcerpc_binding_handle *b,
5356 const char *environment)
5358 struct dcerpc_pipe *p2;
5359 bool ret = true;
5360 struct policy_handle hive_handle;
5361 struct dcerpc_binding_handle *b2;
5363 torture_assert_ntstatus_ok(tctx,
5364 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5365 "could not open winreg pipe");
5366 b2 = p2->binding_handle;
5368 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5370 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5372 test_winreg_CloseKey(tctx, b2, &hive_handle);
5374 talloc_free(p2);
5376 return ret;
5379 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5380 struct dcerpc_pipe *p,
5381 struct policy_handle *handle,
5382 const char *printer_name)
5384 struct spoolss_SetPrinterInfoCtr info_ctr;
5385 struct spoolss_DevmodeContainer devmode_ctr;
5386 struct sec_desc_buf secdesc_ctr;
5387 union spoolss_SetPrinterInfo sinfo;
5388 union spoolss_PrinterInfo info;
5389 struct dcerpc_binding_handle *b = p->binding_handle;
5390 const char *pname;
5392 ZERO_STRUCT(info_ctr);
5393 ZERO_STRUCT(devmode_ctr);
5394 ZERO_STRUCT(secdesc_ctr);
5396 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5398 torture_assert(tctx,
5399 test_GetPrinter_level(tctx, b, handle, 2, &info),
5400 "failed to query Printer level 2");
5402 torture_assert(tctx,
5403 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5404 "failed to convert");
5406 info_ctr.level = 2;
5407 info_ctr.info = sinfo;
5409 #define TEST_SZ(wname, iname) \
5410 do {\
5411 enum winreg_Type type;\
5412 uint8_t *data;\
5413 uint32_t needed;\
5414 DATA_BLOB blob;\
5415 const char *str;\
5416 torture_assert(tctx,\
5417 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5418 "failed to query");\
5419 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5420 blob = data_blob_const(data, needed);\
5421 torture_assert(tctx,\
5422 pull_reg_sz(tctx, &blob, &str),\
5423 "failed to pull REG_SZ");\
5424 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5425 } while(0);
5428 #define TEST_SET_SZ(wname, iname, val) \
5429 do {\
5430 enum winreg_Type type;\
5431 uint8_t *data;\
5432 uint32_t needed;\
5433 DATA_BLOB blob;\
5434 const char *str;\
5435 sinfo.info2->iname = val;\
5436 torture_assert(tctx,\
5437 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5438 "failed to call SetPrinter");\
5439 torture_assert(tctx,\
5440 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5441 "failed to query");\
5442 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5443 blob = data_blob_const(data, needed);\
5444 torture_assert(tctx,\
5445 pull_reg_sz(tctx, &blob, &str),\
5446 "failed to pull REG_SZ");\
5447 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5448 } while(0);
5450 #define TEST_SET_DWORD(wname, iname, val) \
5451 do {\
5452 enum winreg_Type type;\
5453 uint8_t *data;\
5454 uint32_t needed;\
5455 uint32_t value;\
5456 sinfo.info2->iname = val;\
5457 torture_assert(tctx,\
5458 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5459 "failed to call SetPrinter");\
5460 torture_assert(tctx,\
5461 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5462 "failed to query");\
5463 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5464 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5465 value = IVAL(data, 0); \
5466 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5467 } while(0);
5469 TEST_SET_SZ("description", comment, "newval");
5470 TEST_SET_SZ("location", location, "newval");
5471 /* TEST_SET_DWORD("priority", priority, 25); */
5473 torture_assert(tctx,
5474 test_GetPrinter_level(tctx, b, handle, 2, &info),
5475 "failed to query Printer level 2");
5477 TEST_SZ("description", info.info2.comment);
5478 TEST_SZ("driverName", info.info2.drivername);
5479 TEST_SZ("location", info.info2.location);
5481 pname = strrchr(info.info2.printername, '\\');
5482 if (pname == NULL) {
5483 pname = info.info2.printername;
5484 } else {
5485 pname++;
5487 TEST_SZ("printerName", pname);
5488 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5489 /* TEST_SZ("printShareName", info.info2.sharename); */
5491 /* FIXME gd: complete the list */
5493 #undef TEST_SZ
5494 #undef TEST_SET_SZ
5495 #undef TEST_DWORD
5497 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5499 return true;
5502 static bool test_print_processors_winreg(struct torture_context *tctx,
5503 void *private_data)
5505 struct test_spoolss_context *ctx =
5506 talloc_get_type_abort(private_data, struct test_spoolss_context);
5507 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5508 struct dcerpc_binding_handle *b = p->binding_handle;
5510 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5513 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5514 struct dcerpc_binding_handle *b,
5515 struct policy_handle *handle,
5516 uint32_t *change_id)
5518 enum winreg_Type type;
5519 uint8_t *data;
5520 uint32_t needed;
5522 torture_assert(tctx,
5523 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5524 "failed to call GetPrinterData");
5526 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5527 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5529 *change_id = IVAL(data, 0);
5531 return true;
5534 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5535 struct dcerpc_pipe *p,
5536 struct policy_handle *handle,
5537 uint32_t *change_id)
5539 enum winreg_Type type;
5540 uint8_t *data;
5541 uint32_t needed;
5543 torture_assert(tctx,
5544 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5545 "failed to call GetPrinterData");
5547 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5548 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5550 *change_id = IVAL(data, 0);
5552 return true;
5555 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5556 struct dcerpc_binding_handle *b,
5557 struct policy_handle *handle,
5558 uint32_t *change_id)
5560 union spoolss_PrinterInfo info;
5562 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5563 "failed to query Printer level 0");
5565 *change_id = info.info0.change_id;
5567 return true;
5570 static bool test_ChangeID(struct torture_context *tctx,
5571 struct dcerpc_pipe *p,
5572 struct policy_handle *handle)
5574 uint32_t change_id, change_id_ex, change_id_info;
5575 uint32_t change_id2, change_id_ex2, change_id_info2;
5576 union spoolss_PrinterInfo info;
5577 const char *comment;
5578 struct dcerpc_binding_handle *b = p->binding_handle;
5580 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5582 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5583 "failed to query for ChangeID");
5584 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5585 "failed to query for ChangeID");
5586 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5587 "failed to query for ChangeID");
5589 torture_assert_int_equal(tctx, change_id, change_id_ex,
5590 "change_ids should all be equal");
5591 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5592 "change_ids should all be equal");
5595 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5597 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5598 "failed to query for ChangeID");
5599 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5600 "failed to query Printer level 2");
5601 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5602 "failed to query for ChangeID");
5603 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5604 "failed to query for ChangeID");
5605 torture_assert_int_equal(tctx, change_id, change_id_ex,
5606 "change_id should not have changed");
5607 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5608 "change_id should not have changed");
5611 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5613 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5614 "failed to query for ChangeID");
5615 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5616 "failed to query for ChangeID");
5617 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5618 "failed to query for ChangeID");
5619 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5620 "failed to query Printer level 2");
5621 comment = talloc_strdup(tctx, info.info2.comment);
5624 struct spoolss_SetPrinterInfoCtr info_ctr;
5625 struct spoolss_DevmodeContainer devmode_ctr;
5626 struct sec_desc_buf secdesc_ctr;
5627 union spoolss_SetPrinterInfo sinfo;
5629 ZERO_STRUCT(info_ctr);
5630 ZERO_STRUCT(devmode_ctr);
5631 ZERO_STRUCT(secdesc_ctr);
5634 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5635 sinfo.info2->comment = "torture_comment";
5637 info_ctr.level = 2;
5638 info_ctr.info = sinfo;
5640 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5641 "failed to call SetPrinter");
5643 sinfo.info2->comment = comment;
5645 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5646 "failed to call SetPrinter");
5650 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5651 "failed to query for ChangeID");
5652 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5653 "failed to query for ChangeID");
5654 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5655 "failed to query for ChangeID");
5657 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5658 "change_ids should all be equal");
5659 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5660 "change_ids should all be equal");
5662 torture_assert(tctx, (change_id < change_id2),
5663 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5664 change_id2, change_id));
5665 torture_assert(tctx, (change_id_ex < change_id_ex2),
5666 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5667 change_id_ex2, change_id_ex));
5668 torture_assert(tctx, (change_id_info < change_id_info2),
5669 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5670 change_id_info2, change_id_info));
5672 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5674 return true;
5677 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5678 struct dcerpc_pipe *p,
5679 struct policy_handle *handle)
5681 NTSTATUS status;
5682 struct dcerpc_binding *b;
5683 struct dcerpc_pipe *p2;
5684 struct spoolss_ClosePrinter cp;
5686 /* only makes sense on SMB */
5687 if (p->conn->transport.transport != NCACN_NP) {
5688 return true;
5691 torture_comment(tctx, "Testing close on secondary pipe\n");
5693 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5694 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5696 status = dcerpc_secondary_connection(p, &p2, b);
5697 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5699 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5700 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5702 cp.in.handle = handle;
5703 cp.out.handle = handle;
5705 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5706 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5707 "ERROR: Allowed close on secondary connection");
5709 talloc_free(p2);
5711 return true;
5714 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5715 struct dcerpc_binding_handle *b, const char *name)
5717 NTSTATUS status;
5718 struct spoolss_OpenPrinter op;
5719 struct spoolss_OpenPrinterEx opEx;
5720 struct policy_handle handle;
5721 bool ret = true;
5723 op.in.printername = name;
5724 op.in.datatype = NULL;
5725 op.in.devmode_ctr.devmode= NULL;
5726 op.in.access_mask = 0;
5727 op.out.handle = &handle;
5729 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5731 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5732 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5733 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5734 "unexpected result");
5736 if (W_ERROR_IS_OK(op.out.result)) {
5737 ret &=test_ClosePrinter(tctx, b, &handle);
5740 opEx.in.printername = name;
5741 opEx.in.datatype = NULL;
5742 opEx.in.devmode_ctr.devmode = NULL;
5743 opEx.in.access_mask = 0;
5744 opEx.in.level = 1;
5745 opEx.in.userlevel.level1 = NULL;
5746 opEx.out.handle = &handle;
5748 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5750 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5751 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5752 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5753 "unexpected result");
5755 if (W_ERROR_IS_OK(opEx.out.result)) {
5756 ret &=test_ClosePrinter(tctx, b, &handle);
5759 return ret;
5762 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5763 void *private_data)
5765 struct test_spoolss_context *ctx =
5766 talloc_get_type_abort(private_data, struct test_spoolss_context);
5768 const char *badnames[] = {
5769 "__INVALID_PRINTER__",
5770 "\\\\__INVALID_HOST__",
5772 "\\\\\\",
5773 "\\\\\\__INVALID_PRINTER__"
5775 const char *badname;
5776 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5777 const char *server_name = dcerpc_server_name(p);
5778 struct dcerpc_binding_handle *b = p->binding_handle;
5779 int i;
5781 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5782 torture_assert(tctx,
5783 test_OpenPrinter_badname(tctx, b, badnames[i]),
5784 "");
5787 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5788 torture_assert(tctx,
5789 test_OpenPrinter_badname(tctx, b, badname),
5790 "");
5792 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5793 torture_assert(tctx,
5794 test_OpenPrinter_badname(tctx, b, badname),
5795 "");
5797 return true;
5800 static bool test_OpenPrinter(struct torture_context *tctx,
5801 struct dcerpc_pipe *p,
5802 const char *name,
5803 const char *environment,
5804 bool open_only)
5806 NTSTATUS status;
5807 struct spoolss_OpenPrinter r;
5808 struct policy_handle handle;
5809 bool ret = true;
5810 struct dcerpc_binding_handle *b = p->binding_handle;
5812 r.in.printername = name;
5813 r.in.datatype = NULL;
5814 r.in.devmode_ctr.devmode= NULL;
5815 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5816 r.out.handle = &handle;
5818 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5820 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5822 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5824 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5826 if (open_only) {
5827 goto close_printer;
5830 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5831 ret = false;
5834 if (!torture_setting_bool(tctx, "samba3", false)) {
5835 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5836 ret = false;
5840 close_printer:
5841 if (!test_ClosePrinter(tctx, b, &handle)) {
5842 ret = false;
5845 return ret;
5848 static bool test_OpenPrinterEx(struct torture_context *tctx,
5849 struct dcerpc_binding_handle *b,
5850 const char *printername,
5851 const char *datatype,
5852 struct spoolss_DeviceMode *devmode,
5853 uint32_t access_mask,
5854 uint32_t level,
5855 union spoolss_UserLevel *userlevel,
5856 struct policy_handle *handle,
5857 WERROR expected_result)
5859 struct spoolss_OpenPrinterEx r;
5861 r.in.printername = printername;
5862 r.in.datatype = datatype;
5863 r.in.devmode_ctr.devmode= devmode;
5864 r.in.access_mask = access_mask;
5865 r.in.level = level;
5866 r.in.userlevel = *userlevel;
5867 r.out.handle = handle;
5869 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5871 torture_assert_ntstatus_ok(tctx,
5872 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5873 "OpenPrinterEx failed");
5875 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5876 "OpenPrinterEx failed");
5878 return true;
5881 static bool call_OpenPrinterEx(struct torture_context *tctx,
5882 struct dcerpc_pipe *p,
5883 const char *name,
5884 struct spoolss_DeviceMode *devmode,
5885 struct policy_handle *handle)
5887 union spoolss_UserLevel userlevel;
5888 struct spoolss_UserLevel1 userlevel1;
5889 struct dcerpc_binding_handle *b = p->binding_handle;
5891 userlevel1.size = 1234;
5892 userlevel1.client = "hello";
5893 userlevel1.user = "spottyfoot!";
5894 userlevel1.build = 1;
5895 userlevel1.major = 2;
5896 userlevel1.minor = 3;
5897 userlevel1.processor = 4;
5899 userlevel.level1 = &userlevel1;
5901 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5902 SEC_FLAG_MAXIMUM_ALLOWED,
5904 &userlevel,
5905 handle,
5906 WERR_OK);
5909 static bool test_printer_rename(struct torture_context *tctx,
5910 void *private_data)
5912 struct torture_printer_context *t =
5913 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5914 struct dcerpc_pipe *p = t->spoolss_pipe;
5916 bool ret = true;
5917 union spoolss_PrinterInfo info;
5918 union spoolss_SetPrinterInfo sinfo;
5919 struct spoolss_SetPrinterInfoCtr info_ctr;
5920 struct spoolss_DevmodeContainer devmode_ctr;
5921 struct sec_desc_buf secdesc_ctr;
5922 const char *printer_name;
5923 const char *printer_name_orig;
5924 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5925 struct policy_handle new_handle;
5926 const char *q;
5927 struct dcerpc_binding_handle *b = p->binding_handle;
5929 ZERO_STRUCT(devmode_ctr);
5930 ZERO_STRUCT(secdesc_ctr);
5932 torture_comment(tctx, "Testing Printer rename operations\n");
5934 torture_assert(tctx,
5935 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5936 "failed to call GetPrinter level 2");
5938 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5940 q = strrchr(info.info2.printername, '\\');
5941 if (q) {
5942 torture_warning(tctx,
5943 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5946 torture_assert(tctx,
5947 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5949 sinfo.info2->printername = printer_name_new;
5951 info_ctr.level = 2;
5952 info_ctr.info = sinfo;
5954 torture_assert(tctx,
5955 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5956 "failed to call SetPrinter level 2");
5958 torture_assert(tctx,
5959 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5960 "failed to call GetPrinter level 2");
5962 printer_name = talloc_strdup(tctx, info.info2.printername);
5964 q = strrchr(info.info2.printername, '\\');
5965 if (q) {
5966 torture_warning(tctx,
5967 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5968 q++;
5969 printer_name = q;
5972 torture_assert_str_equal(tctx, printer_name, printer_name_new,
5973 "new printer name was not set");
5975 /* samba currently cannot fully rename printers */
5976 if (!torture_setting_bool(tctx, "samba3", false)) {
5977 torture_assert(tctx,
5978 test_OpenPrinter_badname(tctx, b, printer_name_orig),
5979 "still can open printer with oldname after rename");
5980 } else {
5981 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5984 torture_assert(tctx,
5985 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5986 "failed to open printer with new name");
5988 torture_assert(tctx,
5989 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5990 "failed to call GetPrinter level 2");
5992 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
5993 "new printer name was not set");
5995 torture_assert(tctx,
5996 test_ClosePrinter(tctx, b, &new_handle),
5997 "failed to close printer");
5999 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6001 return ret;
6004 static bool test_openprinter(struct torture_context *tctx,
6005 struct dcerpc_binding_handle *b,
6006 const char *real_printername)
6008 union spoolss_UserLevel userlevel;
6009 struct policy_handle handle;
6010 struct spoolss_UserLevel1 userlevel1;
6011 const char *printername = NULL;
6012 int i;
6014 struct {
6015 const char *suffix;
6016 WERROR expected_result;
6017 } tests[] = {
6019 .suffix = "rubbish",
6020 .expected_result = WERR_INVALID_PRINTER_NAME
6022 .suffix = ", LocalOnl",
6023 .expected_result = WERR_INVALID_PRINTER_NAME
6025 .suffix = ", localOnly",
6026 .expected_result = WERR_INVALID_PRINTER_NAME
6028 .suffix = ", localonl",
6029 .expected_result = WERR_INVALID_PRINTER_NAME
6031 .suffix = ",LocalOnl",
6032 .expected_result = WERR_INVALID_PRINTER_NAME
6034 .suffix = ",localOnl2",
6035 .expected_result = WERR_INVALID_PRINTER_NAME
6037 .suffix = ", DrvConver2t",
6038 .expected_result = WERR_INVALID_PRINTER_NAME
6040 .suffix = ", drvconvert",
6041 .expected_result = WERR_INVALID_PRINTER_NAME
6043 .suffix = ",drvconvert",
6044 .expected_result = WERR_INVALID_PRINTER_NAME
6046 .suffix = ", DrvConvert",
6047 .expected_result = WERR_OK
6049 .suffix = " , DrvConvert",
6050 .expected_result = WERR_INVALID_PRINTER_NAME
6052 .suffix = ",DrvConvert",
6053 .expected_result = WERR_OK
6055 .suffix = ", DrvConvertsadfasdf",
6056 .expected_result = WERR_OK
6058 .suffix = ",DrvConvertasdfasd",
6059 .expected_result = WERR_OK
6061 .suffix = ", LocalOnly",
6062 .expected_result = WERR_OK
6064 .suffix = " , LocalOnly",
6065 .expected_result = WERR_INVALID_PRINTER_NAME
6067 .suffix = ",LocalOnly",
6068 .expected_result = WERR_OK
6070 .suffix = ", LocalOnlysagi4gjfkd",
6071 .expected_result = WERR_OK
6073 .suffix = ",LocalOnlysagi4gjfkd",
6074 .expected_result = WERR_OK
6078 userlevel1.size = 1234;
6079 userlevel1.client = "hello";
6080 userlevel1.user = "spottyfoot!";
6081 userlevel1.build = 1;
6082 userlevel1.major = 2;
6083 userlevel1.minor = 3;
6084 userlevel1.processor = 4;
6086 userlevel.level1 = &userlevel1;
6088 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6090 torture_assert(tctx,
6091 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6092 &userlevel, &handle,
6093 WERR_OK),
6094 "OpenPrinterEx failed");
6095 test_ClosePrinter(tctx, b, &handle);
6097 for (i=0; i < ARRAY_SIZE(tests); i++) {
6099 printername = talloc_asprintf(tctx, "%s%s",
6100 real_printername,
6101 tests[i].suffix);
6103 torture_assert(tctx,
6104 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6105 &userlevel, &handle,
6106 tests[i].expected_result),
6107 "OpenPrinterEx failed");
6108 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6109 test_ClosePrinter(tctx, b, &handle);
6113 return true;
6117 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6118 struct dcerpc_pipe *p,
6119 const char *name,
6120 const char *environment)
6122 struct policy_handle handle;
6123 bool ret = true;
6124 struct dcerpc_binding_handle *b = p->binding_handle;
6126 if (!test_openprinter(tctx, b, name)) {
6127 return false;
6130 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6131 return false;
6134 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6135 ret = false;
6138 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6139 ret = false;
6142 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6143 ret = false;
6146 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6147 ret = false;
6150 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6151 ret = false;
6154 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6155 ret = false;
6158 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6159 ret = false;
6162 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6163 ret = false;
6166 if (!test_printer_all_keys(tctx, b, &handle)) {
6167 ret = false;
6170 if (!test_PausePrinter(tctx, b, &handle)) {
6171 ret = false;
6174 if (!test_DoPrintTest(tctx, b, &handle)) {
6175 ret = false;
6178 if (!test_ResumePrinter(tctx, b, &handle)) {
6179 ret = false;
6182 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6183 ret = false;
6186 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6187 ret = false;
6190 if (!torture_setting_bool(tctx, "samba3", false)) {
6191 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6192 ret = false;
6196 if (!test_ClosePrinter(tctx, b, &handle)) {
6197 ret = false;
6200 return ret;
6203 static bool test_EnumPrinters_old(struct torture_context *tctx,
6204 void *private_data)
6206 struct test_spoolss_context *ctx =
6207 talloc_get_type_abort(private_data, struct test_spoolss_context);
6208 struct spoolss_EnumPrinters r;
6209 NTSTATUS status;
6210 uint16_t levels[] = {1, 2, 4, 5};
6211 int i;
6212 bool ret = true;
6213 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6214 struct dcerpc_binding_handle *b = p->binding_handle;
6216 for (i=0;i<ARRAY_SIZE(levels);i++) {
6217 union spoolss_PrinterInfo *info;
6218 int j;
6219 uint32_t needed;
6220 uint32_t count;
6222 r.in.flags = PRINTER_ENUM_LOCAL;
6223 r.in.server = "";
6224 r.in.level = levels[i];
6225 r.in.buffer = NULL;
6226 r.in.offered = 0;
6227 r.out.needed = &needed;
6228 r.out.count = &count;
6229 r.out.info = &info;
6231 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6233 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6234 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6236 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6237 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6238 r.in.buffer = &blob;
6239 r.in.offered = needed;
6240 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6243 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6245 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6247 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6249 if (!info) {
6250 torture_comment(tctx, "No printers returned\n");
6251 return true;
6254 for (j=0;j<count;j++) {
6255 if (r.in.level == 1) {
6256 char *unc = talloc_strdup(tctx, info[j].info1.name);
6257 char *slash, *name, *full_name;
6258 name = unc;
6259 if (unc[0] == '\\' && unc[1] == '\\') {
6260 unc +=2;
6262 slash = strchr(unc, '\\');
6263 if (slash) {
6264 slash++;
6265 name = slash;
6267 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6268 dcerpc_server_name(p), name);
6269 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6270 ret = false;
6272 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6273 ret = false;
6275 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6276 ret = false;
6278 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6279 ret = false;
6285 return ret;
6288 static bool test_EnumPrinters_level(struct torture_context *tctx,
6289 struct dcerpc_binding_handle *b,
6290 uint32_t flags,
6291 const char *servername,
6292 uint32_t level,
6293 uint32_t *count_p,
6294 union spoolss_PrinterInfo **info_p)
6296 struct spoolss_EnumPrinters r;
6297 union spoolss_PrinterInfo *info;
6298 uint32_t needed;
6299 uint32_t count;
6301 r.in.flags = flags;
6302 r.in.server = servername;
6303 r.in.level = level;
6304 r.in.buffer = NULL;
6305 r.in.offered = 0;
6306 r.out.needed = &needed;
6307 r.out.count = &count;
6308 r.out.info = &info;
6310 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6311 r.in.server, r.in.level);
6313 torture_assert_ntstatus_ok(tctx,
6314 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6315 "EnumPrinters failed");
6316 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6317 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6318 r.in.buffer = &blob;
6319 r.in.offered = needed;
6320 torture_assert_ntstatus_ok(tctx,
6321 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6322 "EnumPrinters failed");
6325 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6327 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6329 if (count_p) {
6330 *count_p = count;
6332 if (info_p) {
6333 *info_p = info;
6336 return true;
6339 static const char *get_short_printername(struct torture_context *tctx,
6340 const char *name)
6342 const char *short_name;
6344 if (name[0] == '\\' && name[1] == '\\') {
6345 name += 2;
6346 short_name = strchr(name, '\\');
6347 if (short_name) {
6348 return talloc_strdup(tctx, short_name+1);
6352 return name;
6355 static const char *get_full_printername(struct torture_context *tctx,
6356 const char *name)
6358 const char *full_name = talloc_strdup(tctx, name);
6359 char *p;
6361 if (name && name[0] == '\\' && name[1] == '\\') {
6362 name += 2;
6363 p = strchr(name, '\\');
6364 if (p) {
6365 return full_name;
6369 return NULL;
6372 static bool test_OnePrinter_servername(struct torture_context *tctx,
6373 struct dcerpc_pipe *p,
6374 struct dcerpc_binding_handle *b,
6375 const char *servername,
6376 const char *printername)
6378 union spoolss_PrinterInfo info;
6379 const char *short_name = get_short_printername(tctx, printername);
6380 const char *full_name = get_full_printername(tctx, printername);
6382 if (short_name) {
6383 struct policy_handle handle;
6384 torture_assert(tctx,
6385 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6386 "failed to open printer");
6388 torture_assert(tctx,
6389 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6390 "failed to get printer info");
6392 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6393 "unexpected servername");
6394 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6395 "unexpected printername");
6397 if (info.info2.devmode) {
6398 const char *expected_devicename;
6399 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6400 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6401 "unexpected devicemode devicename");
6404 torture_assert(tctx,
6405 test_ClosePrinter(tctx, b, &handle),
6406 "failed to close printer");
6409 if (full_name) {
6410 struct policy_handle handle;
6412 torture_assert(tctx,
6413 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6414 "failed to open printer");
6416 torture_assert(tctx,
6417 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6418 "failed to get printer info");
6420 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6421 "unexpected servername");
6422 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6423 "unexpected printername");
6425 if (info.info2.devmode) {
6426 const char *expected_devicename;
6427 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6428 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6429 "unexpected devicemode devicename");
6432 torture_assert(tctx,
6433 test_ClosePrinter(tctx, b, &handle),
6434 "failed to close printer");
6437 return true;
6440 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6441 void *private_data)
6443 struct test_spoolss_context *ctx =
6444 talloc_get_type_abort(private_data, struct test_spoolss_context);
6445 int i;
6446 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6447 struct dcerpc_binding_handle *b = p->binding_handle;
6448 uint32_t count;
6449 union spoolss_PrinterInfo *info;
6450 const char *servername;
6451 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6453 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6455 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6457 torture_assert(tctx,
6458 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6459 "failed to enumerate printers");
6461 for (i=0; i < count; i++) {
6463 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6464 "unexpected servername");
6466 torture_assert(tctx,
6467 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6468 "failed to check printer");
6471 servername = "";
6473 torture_assert(tctx,
6474 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6475 "failed to enumerate printers");
6477 for (i=0; i < count; i++) {
6479 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6480 "unexpected servername");
6482 torture_assert(tctx,
6483 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6484 "failed to check printer");
6488 return true;
6492 static bool test_GetPrinterDriver(struct torture_context *tctx,
6493 struct dcerpc_binding_handle *b,
6494 struct policy_handle *handle,
6495 const char *driver_name)
6497 struct spoolss_GetPrinterDriver r;
6498 uint32_t needed;
6500 r.in.handle = handle;
6501 r.in.architecture = "W32X86";
6502 r.in.level = 1;
6503 r.in.buffer = NULL;
6504 r.in.offered = 0;
6505 r.out.needed = &needed;
6507 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6509 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6510 "failed to call GetPrinterDriver");
6511 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6512 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6513 r.in.buffer = &blob;
6514 r.in.offered = needed;
6515 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6516 "failed to call GetPrinterDriver");
6519 torture_assert_werr_ok(tctx, r.out.result,
6520 "failed to call GetPrinterDriver");
6522 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6524 return true;
6527 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6528 struct dcerpc_binding_handle *b,
6529 struct policy_handle *handle,
6530 const char *driver_name,
6531 const char *architecture,
6532 uint32_t level,
6533 uint32_t client_major_version,
6534 uint32_t client_minor_version,
6535 union spoolss_DriverInfo *info_p,
6536 WERROR *result_p)
6539 struct spoolss_GetPrinterDriver2 r;
6540 uint32_t needed;
6541 uint32_t server_major_version;
6542 uint32_t server_minor_version;
6544 r.in.handle = handle;
6545 r.in.architecture = architecture;
6546 r.in.client_major_version = client_major_version;
6547 r.in.client_minor_version = client_minor_version;
6548 r.in.buffer = NULL;
6549 r.in.offered = 0;
6550 r.in.level = level;
6551 r.out.needed = &needed;
6552 r.out.server_major_version = &server_major_version;
6553 r.out.server_minor_version = &server_minor_version;
6555 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6556 driver_name, r.in.level);
6558 torture_assert_ntstatus_ok(tctx,
6559 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6560 "failed to call GetPrinterDriver2");
6561 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6562 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6563 r.in.buffer = &blob;
6564 r.in.offered = needed;
6565 torture_assert_ntstatus_ok(tctx,
6566 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6567 "failed to call GetPrinterDriver2");
6570 if (result_p) {
6571 *result_p = r.out.result;
6574 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6575 switch (r.in.level) {
6576 case 101:
6577 case 8:
6578 torture_comment(tctx,
6579 "level %d not implemented, not considering as an error\n",
6580 r.in.level);
6581 return true;
6582 default:
6583 break;
6587 torture_assert_werr_ok(tctx, r.out.result,
6588 "failed to call GetPrinterDriver2");
6590 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6592 if (info_p) {
6593 *info_p = *r.out.info;
6596 return true;
6599 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6600 struct dcerpc_binding_handle *b,
6601 struct policy_handle *handle,
6602 const char *driver_name,
6603 const char *architecture)
6605 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6606 int i;
6609 for (i=0;i<ARRAY_SIZE(levels);i++) {
6611 torture_assert(tctx,
6612 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6613 "");
6616 return true;
6619 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6620 void *private_data)
6622 struct test_spoolss_context *ctx =
6623 talloc_get_type_abort(private_data, struct test_spoolss_context);
6624 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6625 int i;
6626 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6627 struct dcerpc_binding_handle *b = p->binding_handle;
6628 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6630 for (i=0;i<ARRAY_SIZE(levels);i++) {
6632 uint32_t count;
6633 union spoolss_DriverInfo *info;
6635 torture_assert(tctx,
6636 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6637 "failed to enumerate drivers");
6639 if (!info) {
6640 torture_comment(tctx, "No printer drivers returned\n");
6641 break;
6645 return true;
6648 static bool test_DeletePrinter(struct torture_context *tctx,
6649 struct dcerpc_binding_handle *b,
6650 struct policy_handle *handle)
6652 struct spoolss_DeletePrinter r;
6654 torture_comment(tctx, "Testing DeletePrinter\n");
6656 r.in.handle = handle;
6658 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6659 "failed to delete printer");
6660 torture_assert_werr_ok(tctx, r.out.result,
6661 "failed to delete printer");
6663 return true;
6666 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6667 struct dcerpc_binding_handle *b,
6668 uint32_t flags,
6669 uint32_t level,
6670 const char *name,
6671 bool *found)
6673 struct spoolss_EnumPrinters e;
6674 uint32_t count;
6675 union spoolss_PrinterInfo *info;
6676 uint32_t needed;
6677 int i;
6679 *found = false;
6681 e.in.flags = flags;
6682 e.in.server = NULL;
6683 e.in.level = level;
6684 e.in.buffer = NULL;
6685 e.in.offered = 0;
6686 e.out.count = &count;
6687 e.out.info = &info;
6688 e.out.needed = &needed;
6690 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6691 "failed to enum printers");
6693 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6694 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6695 e.in.buffer = &blob;
6696 e.in.offered = needed;
6698 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6699 "failed to enum printers");
6702 torture_assert_werr_ok(tctx, e.out.result,
6703 "failed to enum printers");
6705 for (i=0; i < count; i++) {
6707 const char *current = NULL;
6708 const char *q;
6710 switch (level) {
6711 case 1:
6712 current = info[i].info1.name;
6713 break;
6716 if (strequal(current, name)) {
6717 *found = true;
6718 break;
6721 q = strrchr(current, '\\');
6722 if (q) {
6723 if (!e.in.server) {
6724 torture_warning(tctx,
6725 "server returns printername %s incl. servername although we did not set servername", current);
6727 q++;
6728 if (strequal(q, name)) {
6729 *found = true;
6730 break;
6735 return true;
6738 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6739 struct dcerpc_pipe *p,
6740 const char *printername,
6741 bool ex)
6743 WERROR result;
6744 struct spoolss_AddPrinter r;
6745 struct spoolss_AddPrinterEx rex;
6746 struct spoolss_SetPrinterInfoCtr info_ctr;
6747 struct spoolss_SetPrinterInfo1 info1;
6748 struct spoolss_DevmodeContainer devmode_ctr;
6749 struct sec_desc_buf secdesc_ctr;
6750 struct spoolss_UserLevelCtr userlevel_ctr;
6751 struct policy_handle handle;
6752 bool found = false;
6753 struct dcerpc_binding_handle *b = p->binding_handle;
6755 ZERO_STRUCT(devmode_ctr);
6756 ZERO_STRUCT(secdesc_ctr);
6757 ZERO_STRUCT(userlevel_ctr);
6758 ZERO_STRUCT(info1);
6760 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6761 ex ? "Ex":"", printername);
6763 /* try to add printer to wellknown printer list (level 1) */
6765 userlevel_ctr.level = 1;
6767 info_ctr.info.info1 = &info1;
6768 info_ctr.level = 1;
6770 rex.in.server = NULL;
6771 rex.in.info_ctr = &info_ctr;
6772 rex.in.devmode_ctr = &devmode_ctr;
6773 rex.in.secdesc_ctr = &secdesc_ctr;
6774 rex.in.userlevel_ctr = &userlevel_ctr;
6775 rex.out.handle = &handle;
6777 r.in.server = NULL;
6778 r.in.info_ctr = &info_ctr;
6779 r.in.devmode_ctr = &devmode_ctr;
6780 r.in.secdesc_ctr = &secdesc_ctr;
6781 r.out.handle = &handle;
6783 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6784 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6785 "failed to add printer");
6786 result = ex ? rex.out.result : r.out.result;
6787 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6788 "unexpected result code");
6790 info1.name = printername;
6791 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6793 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6794 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6795 "failed to add printer");
6796 result = ex ? rex.out.result : r.out.result;
6797 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6798 "unexpected result code");
6800 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6801 better do a real check to see the printer is really there */
6803 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6804 PRINTER_ENUM_NETWORK, 1,
6805 printername,
6806 &found),
6807 "failed to enum printers");
6809 torture_assert(tctx, found, "failed to find newly added printer");
6811 info1.flags = 0;
6813 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6814 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6815 "failed to add printer");
6816 result = ex ? rex.out.result : r.out.result;
6817 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6818 "unexpected result code");
6820 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6821 better do a real check to see the printer has really been removed
6822 from the well known printer list */
6824 found = false;
6826 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6827 PRINTER_ENUM_NETWORK, 1,
6828 printername,
6829 &found),
6830 "failed to enum printers");
6831 #if 0
6832 torture_assert(tctx, !found, "printer still in well known printer list");
6833 #endif
6834 return true;
6837 static bool test_AddPrinter_normal(struct torture_context *tctx,
6838 struct dcerpc_pipe *p,
6839 struct policy_handle *handle_p,
6840 const char *printername,
6841 const char *drivername,
6842 const char *portname,
6843 struct spoolss_DeviceMode *devmode,
6844 bool ex)
6846 WERROR result;
6847 struct spoolss_AddPrinter r;
6848 struct spoolss_AddPrinterEx rex;
6849 struct spoolss_SetPrinterInfoCtr info_ctr;
6850 struct spoolss_SetPrinterInfo2 info2;
6851 struct spoolss_DevmodeContainer devmode_ctr;
6852 struct sec_desc_buf secdesc_ctr;
6853 struct spoolss_UserLevelCtr userlevel_ctr;
6854 struct policy_handle handle;
6855 bool found = false;
6856 bool existing_printer_deleted = false;
6857 struct dcerpc_binding_handle *b = p->binding_handle;
6859 ZERO_STRUCT(devmode_ctr);
6860 ZERO_STRUCT(secdesc_ctr);
6861 ZERO_STRUCT(userlevel_ctr);
6863 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6864 ex ? "Ex":"", printername);
6866 devmode_ctr.devmode = devmode;
6868 userlevel_ctr.level = 1;
6870 rex.in.server = NULL;
6871 rex.in.info_ctr = &info_ctr;
6872 rex.in.devmode_ctr = &devmode_ctr;
6873 rex.in.secdesc_ctr = &secdesc_ctr;
6874 rex.in.userlevel_ctr = &userlevel_ctr;
6875 rex.out.handle = &handle;
6877 r.in.server = NULL;
6878 r.in.info_ctr = &info_ctr;
6879 r.in.devmode_ctr = &devmode_ctr;
6880 r.in.secdesc_ctr = &secdesc_ctr;
6881 r.out.handle = &handle;
6883 again:
6885 /* try to add printer to printer list (level 2) */
6887 ZERO_STRUCT(info2);
6889 info_ctr.info.info2 = &info2;
6890 info_ctr.level = 2;
6892 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6893 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6894 "failed to add printer");
6895 result = ex ? rex.out.result : r.out.result;
6896 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6897 "unexpected result code");
6899 info2.printername = printername;
6901 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6902 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6903 "failed to add printer");
6904 result = ex ? rex.out.result : r.out.result;
6906 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6907 struct policy_handle printer_handle;
6909 if (existing_printer_deleted) {
6910 torture_fail(tctx, "already deleted printer still existing?");
6913 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6914 "failed to open printer handle");
6916 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6917 "failed to delete printer");
6919 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6920 "failed to close server handle");
6922 existing_printer_deleted = true;
6924 goto again;
6927 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6928 "unexpected result code");
6930 info2.portname = portname;
6932 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6933 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6934 "failed to add printer");
6935 result = ex ? rex.out.result : r.out.result;
6936 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6937 "unexpected result code");
6939 info2.drivername = drivername;
6941 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6942 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6943 "failed to add printer");
6944 result = ex ? rex.out.result : r.out.result;
6946 /* w2k8r2 allows to add printer w/o defining printprocessor */
6948 if (!W_ERROR_IS_OK(result)) {
6949 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6950 "unexpected result code");
6952 info2.printprocessor = "winprint";
6954 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6955 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6956 "failed to add printer");
6957 result = ex ? rex.out.result : r.out.result;
6958 torture_assert_werr_ok(tctx, result,
6959 "failed to add printer");
6962 *handle_p = handle;
6964 /* we are paranoid, really check if the printer is there now */
6966 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6967 PRINTER_ENUM_LOCAL, 1,
6968 printername,
6969 &found),
6970 "failed to enum printers");
6971 torture_assert(tctx, found, "failed to find newly added printer");
6973 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6974 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6975 "failed to add printer");
6976 result = ex ? rex.out.result : r.out.result;
6977 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6978 "unexpected result code");
6980 return true;
6983 static bool test_printer_info(struct torture_context *tctx,
6984 void *private_data)
6986 struct torture_printer_context *t =
6987 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6988 struct dcerpc_pipe *p = t->spoolss_pipe;
6989 struct dcerpc_binding_handle *b = p->binding_handle;
6991 bool ret = true;
6993 if (torture_setting_bool(tctx, "samba3", false)) {
6994 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6997 if (!test_PrinterInfo(tctx, b, &t->handle)) {
6998 ret = false;
7001 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7002 ret = false;
7005 return ret;
7008 static bool test_EnumPrinterKey(struct torture_context *tctx,
7009 struct dcerpc_binding_handle *b,
7010 struct policy_handle *handle,
7011 const char *key_name,
7012 const char ***array)
7014 struct spoolss_EnumPrinterKey r;
7015 uint32_t needed = 0;
7016 union spoolss_KeyNames key_buffer;
7017 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7018 uint32_t _ndr_size;
7019 int i;
7021 r.in.handle = handle;
7022 r.in.key_name = key_name;
7023 r.out.key_buffer = &key_buffer;
7024 r.out.needed = &needed;
7025 r.out._ndr_size = &_ndr_size;
7027 for (i=0; i < ARRAY_SIZE(offered); i++) {
7029 if (offered[i] < 0 && needed) {
7030 if (needed <= 4) {
7031 continue;
7033 r.in.offered = needed + offered[i];
7034 } else {
7035 r.in.offered = offered[i];
7038 ZERO_STRUCT(key_buffer);
7040 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7042 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7043 "failed to call EnumPrinterKey");
7044 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7046 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7047 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7048 _ndr_size, r.in.offered/2));
7050 r.in.offered = needed;
7051 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7052 "failed to call EnumPrinterKey");
7055 if (offered[i] > 0) {
7056 torture_assert_werr_ok(tctx, r.out.result,
7057 "failed to call EnumPrinterKey");
7060 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7061 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7062 _ndr_size, r.in.offered/2));
7064 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7065 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7067 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7068 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7070 if (key_buffer.string_array) {
7071 uint32_t calc_needed = 0;
7072 int s;
7073 for (s=0; key_buffer.string_array[s]; s++) {
7074 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7076 if (!key_buffer.string_array[0]) {
7077 calc_needed += 2;
7079 calc_needed += 2;
7081 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7082 "EnumPrinterKey unexpected size");
7086 if (array) {
7087 *array = key_buffer.string_array;
7090 return true;
7093 bool test_printer_all_keys(struct torture_context *tctx,
7094 struct dcerpc_binding_handle *b,
7095 struct policy_handle *handle)
7097 const char **key_array = NULL;
7098 int i;
7100 torture_comment(tctx, "Testing Printer Keys\n");
7102 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7103 "failed to call test_EnumPrinterKey");
7105 for (i=0; key_array && key_array[i]; i++) {
7106 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7107 "failed to call test_EnumPrinterKey");
7109 for (i=0; key_array && key_array[i]; i++) {
7110 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7111 "failed to call test_EnumPrinterDataEx");
7114 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7116 return true;
7119 static bool test_openprinter_wrap(struct torture_context *tctx,
7120 void *private_data)
7122 struct torture_printer_context *t =
7123 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7124 struct dcerpc_pipe *p = t->spoolss_pipe;
7125 struct dcerpc_binding_handle *b = p->binding_handle;
7126 const char *printername = t->info2.printername;
7128 return test_openprinter(tctx, b, printername);
7131 static bool test_csetprinter(struct torture_context *tctx,
7132 void *private_data)
7134 struct torture_printer_context *t =
7135 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7136 struct dcerpc_pipe *p = t->spoolss_pipe;
7138 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7139 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7140 const char *portname = t->info2.portname;
7142 union spoolss_PrinterInfo info;
7143 struct policy_handle new_handle, new_handle2;
7144 struct dcerpc_binding_handle *b = p->binding_handle;
7146 torture_comment(tctx, "Testing c_setprinter\n");
7148 torture_assert(tctx,
7149 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7150 "failed to get level 0 printer info");
7151 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7152 info.info0.c_setprinter);
7154 /* check if c_setprinter on 1st handle increases after a printer has
7155 * been added */
7157 torture_assert(tctx,
7158 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7159 "failed to add new printer");
7160 torture_assert(tctx,
7161 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7162 "failed to get level 0 printer info");
7163 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7164 info.info0.c_setprinter);
7166 /* check if c_setprinter on new handle increases after a printer has
7167 * been added */
7169 torture_assert(tctx,
7170 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7171 "failed to get level 0 printer info");
7172 torture_comment(tctx, "csetprinter on created handle: %d\n",
7173 info.info0.c_setprinter);
7175 /* open the new printer and check if c_setprinter increases */
7177 torture_assert(tctx,
7178 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7179 "failed to open created printer");
7180 torture_assert(tctx,
7181 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7182 "failed to get level 0 printer info");
7183 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7184 info.info0.c_setprinter);
7186 /* cleanup */
7188 torture_assert(tctx,
7189 test_ClosePrinter(tctx, b, &new_handle2),
7190 "failed to close printer");
7191 torture_assert(tctx,
7192 test_DeletePrinter(tctx, b, &new_handle),
7193 "failed to delete new printer");
7195 return true;
7198 static bool compose_local_driver_directory(struct torture_context *tctx,
7199 const char *environment,
7200 const char *local_dir,
7201 const char **path)
7203 char *p;
7205 p = strrchr(local_dir, '/');
7206 if (!p) {
7207 return NULL;
7209 p++;
7211 if (strequal(environment, "Windows x64")) {
7212 if (!strequal(p, "x64")) {
7213 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7215 } else if (strequal(environment, "Windows NT x86")) {
7216 if (!strequal(p, "i386")) {
7217 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7219 } else {
7220 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7223 return true;
7226 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7227 const char *devicename)
7229 struct spoolss_DeviceMode *r;
7231 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7232 if (r == NULL) {
7233 return NULL;
7236 r->devicename = talloc_strdup(r, devicename);
7237 r->specversion = DMSPEC_NT4_AND_ABOVE;
7238 r->driverversion = 0x0600;
7239 r->size = 0x00dc;
7240 r->__driverextra_length = 0;
7241 r->fields = DEVMODE_FORMNAME |
7242 DEVMODE_TTOPTION |
7243 DEVMODE_PRINTQUALITY |
7244 DEVMODE_DEFAULTSOURCE |
7245 DEVMODE_COPIES |
7246 DEVMODE_SCALE |
7247 DEVMODE_PAPERSIZE |
7248 DEVMODE_ORIENTATION;
7249 r->orientation = DMORIENT_PORTRAIT;
7250 r->papersize = DMPAPER_LETTER;
7251 r->paperlength = 0;
7252 r->paperwidth = 0;
7253 r->scale = 100;
7254 r->copies = 55;
7255 r->defaultsource = DMBIN_FORMSOURCE;
7256 r->printquality = DMRES_HIGH;
7257 r->color = DMRES_MONOCHROME;
7258 r->duplex = DMDUP_SIMPLEX;
7259 r->yresolution = 0;
7260 r->ttoption = DMTT_SUBDEV;
7261 r->collate = DMCOLLATE_FALSE;
7262 r->formname = talloc_strdup(r, "Letter");
7264 return r;
7267 static bool test_architecture_buffer(struct torture_context *tctx,
7268 void *private_data)
7270 struct test_spoolss_context *ctx =
7271 talloc_get_type_abort(private_data, struct test_spoolss_context);
7273 struct spoolss_OpenPrinterEx r;
7274 struct spoolss_UserLevel1 u1;
7275 struct policy_handle handle;
7276 uint32_t architectures[] = {
7277 PROCESSOR_ARCHITECTURE_INTEL,
7278 PROCESSOR_ARCHITECTURE_IA64,
7279 PROCESSOR_ARCHITECTURE_AMD64
7281 uint32_t needed[3];
7282 int i;
7283 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7284 struct dcerpc_binding_handle *b = p->binding_handle;
7286 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7288 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7290 u1.size = 0;
7291 u1.client = NULL;
7292 u1.user = NULL;
7293 u1.build = 0;
7294 u1.major = 3;
7295 u1.minor = 0;
7296 u1.processor = architectures[i];
7298 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7299 r.in.datatype = NULL;
7300 r.in.devmode_ctr.devmode= NULL;
7301 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7302 r.in.level = 1;
7303 r.in.userlevel.level1 = &u1;
7304 r.out.handle = &handle;
7306 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7307 torture_assert_werr_ok(tctx, r.out.result, "");
7310 struct spoolss_EnumPrinters e;
7311 uint32_t count;
7312 union spoolss_PrinterInfo *info;
7314 e.in.flags = PRINTER_ENUM_LOCAL;
7315 e.in.server = NULL;
7316 e.in.level = 2;
7317 e.in.buffer = NULL;
7318 e.in.offered = 0;
7319 e.out.count = &count;
7320 e.out.info = &info;
7321 e.out.needed = &needed[i];
7323 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7324 #if 0
7325 torture_comment(tctx, "needed was %d\n", needed[i]);
7326 #endif
7329 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7332 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7333 if (needed[i-1] != needed[i]) {
7334 torture_fail(tctx,
7335 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7336 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7340 return true;
7343 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7344 void *private_data)
7346 struct test_spoolss_context *ctx =
7347 talloc_get_type_abort(private_data, struct test_spoolss_context);
7348 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7349 struct dcerpc_binding_handle *b = p->binding_handle;
7351 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7354 static bool test_PrintServer_Forms(struct torture_context *tctx,
7355 void *private_data)
7357 struct test_spoolss_context *ctx =
7358 talloc_get_type_abort(private_data, struct test_spoolss_context);
7359 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7360 struct dcerpc_binding_handle *b = p->binding_handle;
7362 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7365 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7366 void *private_data)
7368 struct test_spoolss_context *ctx =
7369 talloc_get_type_abort(private_data, struct test_spoolss_context);
7370 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7371 struct dcerpc_binding_handle *b = p->binding_handle;
7373 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7376 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7378 NTSTATUS status;
7380 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7382 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7384 torture_assert(tctx,
7385 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7386 "failed to open printserver");
7387 torture_assert(tctx,
7388 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7389 "failed to get environment");
7391 return true;
7394 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7396 struct test_spoolss_context *t;
7398 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7400 return torture_rpc_spoolss_setup_common(tctx, t);
7403 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7405 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7407 return true;
7410 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7412 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7413 bool ret;
7415 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7416 talloc_free(t);
7418 return ret;
7421 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7423 struct dcerpc_pipe *p;
7424 struct dcerpc_binding_handle *b;
7425 const char *server_name_slash;
7426 const char *driver_name;
7427 const char *printer_name;
7428 const char *port_name;
7430 torture_assert_ntstatus_ok(tctx,
7431 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7432 "Error connecting to server");
7434 p = t->spoolss_pipe;
7435 b = p->binding_handle;
7436 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7438 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7439 t->driver.info8.driver_name = TORTURE_DRIVER;
7440 t->driver.info8.driver_path = "pscript5.dll";
7441 t->driver.info8.data_file = "cups6.ppd";
7442 t->driver.info8.config_file = "ps5ui.dll";
7443 t->driver.info8.help_file = "pscript.hlp";
7444 t->driver.info8.default_datatype = "RAW";
7445 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7446 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7447 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7448 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7449 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7450 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7451 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7452 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7453 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7454 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7456 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7458 t->info2.drivername = "Microsoft XPS Document Writer";
7459 t->info2.portname = "LPT1:";
7461 printer_name = t->info2.printername;
7462 port_name = t->info2.portname;
7464 torture_assert(tctx,
7465 fillup_printserver_info(tctx, p, &t->driver),
7466 "failed to fillup printserver info");
7468 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7470 torture_assert(tctx,
7471 compose_local_driver_directory(tctx, t->driver.remote.environment,
7472 t->driver.local.driver_directory,
7473 &t->driver.local.driver_directory),
7474 "failed to compose local driver directory");
7476 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7477 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7478 t->info2.drivername, t->driver.remote.environment);
7479 t->have_driver = true;
7480 goto try_add;
7483 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7484 t->info2.drivername, t->driver.remote.environment);
7485 torture_comment(tctx, "trying to upload own driver\n");
7487 if (!directory_exist(t->driver.local.driver_directory)) {
7488 torture_warning(tctx, "no local driver is available!");
7489 t->have_driver = false;
7490 goto try_add;
7493 torture_assert(tctx,
7494 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7495 "failed to upload printer driver");
7497 torture_assert(tctx,
7498 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7499 "failed to add driver");
7501 t->added_driver = true;
7502 t->have_driver = true;
7504 try_add:
7505 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7507 if (t->wellknown) {
7508 torture_assert(tctx,
7509 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7510 "failed to add wellknown printer");
7511 } else {
7512 torture_assert(tctx,
7513 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7514 "failed to add printer");
7517 return true;
7520 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7522 struct torture_printer_context *t;
7524 *data = t = talloc_zero(tctx, struct torture_printer_context);
7526 t->ex = false;
7527 t->wellknown = false;
7528 t->info2.printername = TORTURE_PRINTER;
7529 t->devmode = NULL;
7531 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7534 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7536 struct torture_printer_context *t;
7538 *data = t = talloc_zero(tctx, struct torture_printer_context);
7540 t->ex = true;
7541 t->wellknown = false;
7542 t->info2.printername = TORTURE_PRINTER_EX;
7543 t->devmode = NULL;
7545 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7548 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7550 struct torture_printer_context *t;
7552 *data = t = talloc_zero(tctx, struct torture_printer_context);
7554 t->ex = false;
7555 t->wellknown = true;
7556 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7557 t->devmode = NULL;
7559 /* FIXME */
7560 if (t->wellknown) {
7561 torture_skip(tctx, "skipping AddPrinter level 1");
7564 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7567 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7569 struct torture_printer_context *t;
7571 *data = t = talloc_zero(tctx, struct torture_printer_context);
7573 t->ex = true;
7574 t->wellknown = true;
7575 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7576 t->devmode = NULL;
7578 /* FIXME */
7579 if (t->wellknown) {
7580 torture_skip(tctx, "skipping AddPrinterEx level 1");
7583 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7586 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7588 struct torture_printer_context *t;
7590 *data = t = talloc_zero(tctx, struct torture_printer_context);
7592 t->ex = true;
7593 t->wellknown = false;
7594 t->info2.printername = TORTURE_PRINTER_EX;
7595 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7597 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7600 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7602 bool found = false;
7603 struct dcerpc_pipe *p = t->spoolss_pipe;
7604 struct dcerpc_binding_handle *b;
7605 const char *printer_name = t->info2.printername;
7607 if (t->added_driver) {
7608 torture_assert(tctx,
7609 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7610 "failed to remove printer driver");
7613 if (p) {
7614 b = p->binding_handle;
7617 if (!t->wellknown) {
7618 torture_assert(tctx,
7619 test_DeletePrinter(tctx, b, &t->handle),
7620 "failed to delete printer");
7622 torture_assert(tctx,
7623 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7624 printer_name, &found),
7625 "failed to enumerate printers");
7627 torture_assert(tctx, !found, "deleted printer still there");
7630 return true;
7633 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7635 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7636 bool ret;
7638 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7639 talloc_free(t);
7641 return ret;
7644 static bool test_print_test(struct torture_context *tctx,
7645 void *private_data)
7647 struct torture_printer_context *t =
7648 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7649 struct dcerpc_pipe *p = t->spoolss_pipe;
7650 struct dcerpc_binding_handle *b = p->binding_handle;
7652 torture_assert(tctx,
7653 test_PausePrinter(tctx, b, &t->handle),
7654 "failed to pause printer");
7656 torture_assert(tctx,
7657 test_DoPrintTest(tctx, b, &t->handle),
7658 "failed to do print test");
7660 torture_assert(tctx,
7661 test_ResumePrinter(tctx, b, &t->handle),
7662 "failed to resume printer");
7664 return true;
7667 static bool test_print_test_extended(struct torture_context *tctx,
7668 void *private_data)
7670 struct torture_printer_context *t =
7671 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7672 struct dcerpc_pipe *p = t->spoolss_pipe;
7673 struct dcerpc_binding_handle *b = p->binding_handle;
7674 bool ret = true;
7676 torture_assert(tctx,
7677 test_PausePrinter(tctx, b, &t->handle),
7678 "failed to pause printer");
7680 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7681 if (ret == false) {
7682 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7683 if (torture_setting_bool(tctx, "samba3", false)) {
7684 torture_comment(tctx, "non-critical for samba3\n");
7685 ret = true;
7686 tctx->last_result = TORTURE_SKIP;
7690 torture_assert(tctx,
7691 test_ResumePrinter(tctx, b, &t->handle),
7692 "failed to resume printer");
7694 return ret;
7697 static bool test_printer_sd(struct torture_context *tctx,
7698 void *private_data)
7700 struct torture_printer_context *t =
7701 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7702 struct dcerpc_pipe *p = t->spoolss_pipe;
7703 struct dcerpc_binding_handle *b = p->binding_handle;
7705 torture_assert(tctx,
7706 test_PrinterInfo_SD(tctx, b, &t->handle),
7707 "failed to test security descriptors");
7709 return true;
7712 static bool test_printer_dm(struct torture_context *tctx,
7713 void *private_data)
7715 struct torture_printer_context *t =
7716 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7717 struct dcerpc_pipe *p = t->spoolss_pipe;
7719 torture_assert(tctx,
7720 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7721 "failed to test devicemodes");
7723 return true;
7726 static bool test_printer_info_winreg(struct torture_context *tctx,
7727 void *private_data)
7729 struct torture_printer_context *t =
7730 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7731 struct dcerpc_pipe *p = t->spoolss_pipe;
7733 torture_assert(tctx,
7734 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7735 "failed to test printer info winreg");
7737 return true;
7740 static bool test_printer_change_id(struct torture_context *tctx,
7741 void *private_data)
7743 struct torture_printer_context *t =
7744 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7745 struct dcerpc_pipe *p = t->spoolss_pipe;
7747 torture_assert(tctx,
7748 test_ChangeID(tctx, p, &t->handle),
7749 "failed to test change id");
7751 return true;
7754 static bool test_printer_keys(struct torture_context *tctx,
7755 void *private_data)
7757 struct torture_printer_context *t =
7758 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7759 struct dcerpc_pipe *p = t->spoolss_pipe;
7760 struct dcerpc_binding_handle *b = p->binding_handle;
7762 torture_assert(tctx,
7763 test_printer_all_keys(tctx, b, &t->handle),
7764 "failed to test printer keys");
7766 return true;
7769 static bool test_printer_data_consistency(struct torture_context *tctx,
7770 void *private_data)
7772 struct torture_printer_context *t =
7773 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7774 struct dcerpc_pipe *p = t->spoolss_pipe;
7776 torture_assert(tctx,
7777 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7778 "failed to test printer data consistency");
7780 return true;
7783 static bool test_printer_data_keys(struct torture_context *tctx,
7784 void *private_data)
7786 struct torture_printer_context *t =
7787 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7788 struct dcerpc_pipe *p = t->spoolss_pipe;
7790 torture_assert(tctx,
7791 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7792 "failed to test printer data keys");
7794 return true;
7797 static bool test_printer_data_values(struct torture_context *tctx,
7798 void *private_data)
7800 struct torture_printer_context *t =
7801 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7802 struct dcerpc_pipe *p = t->spoolss_pipe;
7804 torture_assert(tctx,
7805 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7806 "failed to test printer data values");
7808 return true;
7811 static bool test_printer_data_set(struct torture_context *tctx,
7812 void *private_data)
7814 struct torture_printer_context *t =
7815 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7816 struct dcerpc_pipe *p = t->spoolss_pipe;
7818 torture_assert(tctx,
7819 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7820 "failed to test printer data set");
7822 return true;
7825 static bool test_printer_data_winreg(struct torture_context *tctx,
7826 void *private_data)
7828 struct torture_printer_context *t =
7829 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7830 struct dcerpc_pipe *p = t->spoolss_pipe;
7832 torture_assert(tctx,
7833 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7834 "failed to test printer data winreg");
7836 return true;
7839 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7840 void *private_data)
7842 struct torture_printer_context *t =
7843 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7844 struct dcerpc_pipe *p = t->spoolss_pipe;
7846 torture_assert(tctx,
7847 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7848 "failed to test printer data winreg dsspooler");
7850 return true;
7853 static bool test_driver_info_winreg(struct torture_context *tctx,
7854 void *private_data)
7856 struct torture_printer_context *t =
7857 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7858 struct dcerpc_pipe *p = t->spoolss_pipe;
7859 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7861 if (!t->have_driver) {
7862 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7865 torture_assert(tctx,
7866 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7867 "failed to test driver info winreg");
7869 return true;
7872 void torture_tcase_printer(struct torture_tcase *tcase)
7874 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7875 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7876 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7877 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7878 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7879 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7880 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7881 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7882 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7883 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7884 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7885 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7886 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7887 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7888 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7889 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7890 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7891 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7894 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7896 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7897 struct torture_tcase *tcase;
7899 tcase = torture_suite_add_tcase(suite, "addprinter");
7901 torture_tcase_set_fixture(tcase,
7902 torture_rpc_spoolss_printer_setup,
7903 torture_rpc_spoolss_printer_teardown);
7905 torture_tcase_printer(tcase);
7907 tcase = torture_suite_add_tcase(suite, "addprinterex");
7909 torture_tcase_set_fixture(tcase,
7910 torture_rpc_spoolss_printerex_setup,
7911 torture_rpc_spoolss_printer_teardown);
7913 torture_tcase_printer(tcase);
7915 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7917 torture_tcase_set_fixture(tcase,
7918 torture_rpc_spoolss_printerwkn_setup,
7919 torture_rpc_spoolss_printer_teardown);
7921 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7923 torture_tcase_set_fixture(tcase,
7924 torture_rpc_spoolss_printerexwkn_setup,
7925 torture_rpc_spoolss_printer_teardown);
7927 #if 0
7928 /* test is not correct */
7929 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7931 torture_tcase_set_fixture(tcase,
7932 torture_rpc_spoolss_printerdm_setup,
7933 torture_rpc_spoolss_printer_teardown);
7935 torture_tcase_printer(tcase);
7936 #endif
7937 return suite;
7940 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7942 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7943 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7945 torture_tcase_set_fixture(tcase,
7946 torture_rpc_spoolss_setup,
7947 torture_rpc_spoolss_teardown);
7949 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7950 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7951 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7952 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7953 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7954 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7955 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7956 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7957 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7958 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7959 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7960 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7961 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7962 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7963 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7964 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7965 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7966 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7967 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7968 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7970 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7972 return suite;
7975 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7976 struct dcerpc_binding_handle *b,
7977 const char *server,
7978 const char *environment,
7979 const char **dir_p)
7981 struct spoolss_GetPrinterDriverDirectory r;
7982 uint32_t needed;
7984 r.in.server = server;
7985 r.in.environment = environment;
7986 r.in.level = 1;
7987 r.in.buffer = NULL;
7988 r.in.offered = 0;
7989 r.out.needed = &needed;
7991 torture_assert_ntstatus_ok(tctx,
7992 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7993 "failed to query driver directory");
7995 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7996 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7997 r.in.buffer = &blob;
7998 r.in.offered = needed;
8000 torture_assert_ntstatus_ok(tctx,
8001 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8002 "failed to query driver directory");
8005 torture_assert_werr_ok(tctx, r.out.result,
8006 "failed to query driver directory");
8008 if (dir_p) {
8009 *dir_p = r.out.info->info1.directory_name;
8012 return true;
8015 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8017 if (info_ctr == NULL) {
8018 return NULL;
8021 switch (info_ctr->level) {
8022 case 1:
8023 return info_ctr->info.info1->driver_name;
8024 case 2:
8025 return info_ctr->info.info2->driver_name;
8026 case 3:
8027 return info_ctr->info.info3->driver_name;
8028 case 4:
8029 return info_ctr->info.info4->driver_name;
8030 case 6:
8031 return info_ctr->info.info6->driver_name;
8032 case 8:
8033 return info_ctr->info.info8->driver_name;
8034 default:
8035 return NULL;
8039 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8041 if (info_ctr == NULL) {
8042 return NULL;
8045 switch (info_ctr->level) {
8046 case 2:
8047 return info_ctr->info.info2->architecture;
8048 case 3:
8049 return info_ctr->info.info3->architecture;
8050 case 4:
8051 return info_ctr->info.info4->architecture;
8052 case 6:
8053 return info_ctr->info.info6->architecture;
8054 case 8:
8055 return info_ctr->info.info8->architecture;
8056 default:
8057 return NULL;
8062 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8063 struct dcerpc_binding_handle *b,
8064 const char *servername,
8065 struct spoolss_AddDriverInfoCtr *info_ctr,
8066 WERROR expected_result)
8068 struct spoolss_AddPrinterDriver r;
8069 const char *drivername = get_driver_from_info(info_ctr);
8070 const char *environment = get_environment_from_info(info_ctr);
8072 r.in.servername = servername;
8073 r.in.info_ctr = info_ctr;
8075 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8076 drivername, info_ctr->level, environment);
8078 torture_assert_ntstatus_ok(tctx,
8079 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8080 "spoolss_AddPrinterDriver failed");
8081 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8082 "spoolss_AddPrinterDriver failed with unexpected result");
8084 return true;
8088 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8089 struct dcerpc_binding_handle *b,
8090 const char *servername,
8091 struct spoolss_AddDriverInfoCtr *info_ctr,
8092 uint32_t flags,
8093 WERROR expected_result)
8095 struct spoolss_AddPrinterDriverEx r;
8096 const char *drivername = get_driver_from_info(info_ctr);
8097 const char *environment = get_environment_from_info(info_ctr);
8099 r.in.servername = servername;
8100 r.in.info_ctr = info_ctr;
8101 r.in.flags = flags;
8103 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8104 drivername, info_ctr->level, environment);
8106 torture_assert_ntstatus_ok(tctx,
8107 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8108 "AddPrinterDriverEx failed");
8109 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8110 "AddPrinterDriverEx failed with unexpected result");
8112 return true;
8115 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8116 if (path && strlen(path)) {\
8117 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8120 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8121 struct dcerpc_binding_handle *b,
8122 const char *server_name,
8123 struct spoolss_AddDriverInfo8 *r,
8124 uint32_t flags,
8125 bool ex,
8126 const char *remote_driver_dir)
8128 struct spoolss_AddDriverInfoCtr info_ctr;
8129 struct spoolss_AddDriverInfo1 info1;
8131 ZERO_STRUCT(info1);
8133 info_ctr.level = 1;
8134 info_ctr.info.info1 = &info1;
8136 if (ex) {
8137 torture_assert(tctx,
8138 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8139 "failed to test AddPrinterDriverEx level 1");
8140 } else {
8141 torture_assert(tctx,
8142 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8143 "failed to test AddPrinterDriver level 1");
8146 info1.driver_name = r->driver_name;
8148 if (ex) {
8149 torture_assert(tctx,
8150 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8151 "failed to test AddPrinterDriverEx level 1");
8152 } else {
8153 torture_assert(tctx,
8154 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8155 "failed to test AddPrinterDriver level 1");
8158 return true;
8161 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8162 struct dcerpc_binding_handle *b,
8163 const char *server_name,
8164 struct spoolss_AddDriverInfo8 *r,
8165 uint32_t flags,
8166 bool ex,
8167 const char *remote_driver_dir)
8169 struct spoolss_AddDriverInfoCtr info_ctr;
8170 struct spoolss_AddDriverInfo2 info2;
8171 union spoolss_DriverInfo info;
8173 ZERO_STRUCT(info2);
8175 info_ctr.level = 2;
8176 info_ctr.info.info2 = &info2;
8178 if (ex) {
8179 torture_assert(tctx,
8180 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8181 "failed to test AddPrinterDriverEx level 2");
8182 } else {
8183 torture_assert(tctx,
8184 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8185 "failed to test AddPrinterDriver level 2");
8188 info2.driver_name = r->driver_name;
8190 if (ex) {
8191 torture_assert(tctx,
8192 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8193 "failed to test AddPrinterDriverEx level 2");
8194 } else {
8195 torture_assert(tctx,
8196 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8197 "failed to test AddPrinterDriver level 2");
8200 info2.version = r->version;
8202 if (ex) {
8203 torture_assert(tctx,
8204 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8205 "failed to test AddPrinterDriverEx level 2");
8206 } else {
8207 torture_assert(tctx,
8208 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8209 "failed to test AddPrinterDriver level 2");
8212 info2.architecture = r->architecture;
8214 if (ex) {
8215 torture_assert(tctx,
8216 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8217 "failed to test AddPrinterDriverEx level 2");
8218 } else {
8219 torture_assert(tctx,
8220 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8221 "failed to test AddPrinterDriver level 2");
8224 info2.driver_path = r->driver_path;
8226 if (ex) {
8227 torture_assert(tctx,
8228 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8229 "failed to test AddPrinterDriverEx level 2");
8230 } else {
8231 torture_assert(tctx,
8232 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8233 "failed to test AddPrinterDriver level 2");
8236 info2.data_file = r->data_file;
8238 if (ex) {
8239 torture_assert(tctx,
8240 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8241 "failed to test AddPrinterDriverEx level 2");
8242 } else {
8243 torture_assert(tctx,
8244 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8245 "failed to test AddPrinterDriver level 2");
8248 info2.config_file = r->config_file;
8250 if (ex) {
8251 torture_assert(tctx,
8252 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8253 "failed to test AddPrinterDriverEx");
8256 if (ex) {
8257 torture_assert(tctx,
8258 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8259 "failed to test AddPrinterDriverEx level 2");
8260 } else {
8261 torture_assert(tctx,
8262 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8263 "failed to test AddPrinterDriver level 2");
8266 torture_assert(tctx,
8267 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8268 "failed to find added printer driver");
8270 if (remote_driver_dir) {
8271 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8272 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8273 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8276 return true;
8279 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8280 struct dcerpc_binding_handle *b,
8281 const char *server_name,
8282 struct spoolss_AddDriverInfo8 *r,
8283 uint32_t flags,
8284 bool ex,
8285 const char *remote_driver_dir)
8287 struct spoolss_AddDriverInfoCtr info_ctr;
8288 struct spoolss_AddDriverInfo3 info3;
8289 union spoolss_DriverInfo info;
8291 info3.driver_name = r->driver_name;
8292 info3.version = r->version;
8293 info3.architecture = r->architecture;
8294 info3.driver_path = r->driver_path;
8295 info3.data_file = r->data_file;
8296 info3.config_file = r->config_file;
8297 info3.help_file = r->help_file;
8298 info3.monitor_name = r->monitor_name;
8299 info3.default_datatype = r->default_datatype;
8300 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8301 info3.dependent_files = r->dependent_files;
8303 info_ctr.level = 3;
8304 info_ctr.info.info3 = &info3;
8306 if (ex) {
8307 torture_assert(tctx,
8308 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8309 "failed to test AddPrinterDriverEx level 3");
8310 } else {
8311 torture_assert(tctx,
8312 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8313 "failed to test AddPrinterDriver level 3");
8316 torture_assert(tctx,
8317 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8318 "failed to find added printer driver");
8320 if (remote_driver_dir) {
8321 int i;
8322 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8323 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8324 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8325 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8326 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8327 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8331 return true;
8334 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8335 struct dcerpc_binding_handle *b,
8336 const char *server_name,
8337 struct spoolss_AddDriverInfo8 *r,
8338 uint32_t flags,
8339 bool ex,
8340 const char *remote_driver_dir)
8342 struct spoolss_AddDriverInfoCtr info_ctr;
8343 struct spoolss_AddDriverInfo4 info4;
8344 union spoolss_DriverInfo info;
8346 info4.version = r->version;
8347 info4.driver_name = r->driver_name;
8348 info4.architecture = r->architecture;
8349 info4.driver_path = r->driver_path;
8350 info4.data_file = r->data_file;
8351 info4.config_file = r->config_file;
8352 info4.help_file = r->help_file;
8353 info4.monitor_name = r->monitor_name;
8354 info4.default_datatype = r->default_datatype;
8355 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8356 info4.dependent_files = r->dependent_files;
8357 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8358 info4.previous_names = r->previous_names;
8360 info_ctr.level = 4;
8361 info_ctr.info.info4 = &info4;
8363 if (ex) {
8364 torture_assert(tctx,
8365 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8366 "failed to test AddPrinterDriverEx level 4");
8367 } else {
8368 torture_assert(tctx,
8369 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8370 "failed to test AddPrinterDriver level 4");
8373 torture_assert(tctx,
8374 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8375 "failed to find added printer driver");
8377 if (remote_driver_dir) {
8378 int i;
8379 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8380 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8381 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8382 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8383 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8384 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8388 return true;
8391 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8392 struct dcerpc_binding_handle *b,
8393 const char *server_name,
8394 struct spoolss_AddDriverInfo8 *r,
8395 uint32_t flags,
8396 bool ex,
8397 const char *remote_driver_dir)
8399 struct spoolss_AddDriverInfoCtr info_ctr;
8400 struct spoolss_AddDriverInfo6 info6;
8401 union spoolss_DriverInfo info;
8403 info6.version = r->version;
8404 info6.driver_name = r->driver_name;
8405 info6.architecture = r->architecture;
8406 info6.driver_path = r->driver_path;
8407 info6.data_file = r->data_file;
8408 info6.config_file = r->config_file;
8409 info6.help_file = r->help_file;
8410 info6.monitor_name = r->monitor_name;
8411 info6.default_datatype = r->default_datatype;
8412 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8413 info6.dependent_files = r->dependent_files;
8414 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8415 info6.previous_names = r->previous_names;
8416 info6.driver_date = r->driver_date;
8417 info6.driver_version = r->driver_version;
8418 info6.manufacturer_name = r->manufacturer_name;
8419 info6.manufacturer_url = r->manufacturer_url;
8420 info6.hardware_id = r->hardware_id;
8421 info6.provider = r->provider;
8423 info_ctr.level = 6;
8424 info_ctr.info.info6 = &info6;
8426 if (ex) {
8427 torture_assert(tctx,
8428 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8429 "failed to test AddPrinterDriverEx level 6");
8430 } else {
8431 torture_assert(tctx,
8432 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8433 "failed to test AddPrinterDriver level 6");
8436 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8438 if (!ex) {
8439 return true;
8442 torture_assert(tctx,
8443 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8444 "failed to find added printer driver");
8446 if (remote_driver_dir) {
8447 int i;
8448 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8449 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8450 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8451 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8452 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8453 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8457 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8459 return true;
8462 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8463 struct dcerpc_binding_handle *b,
8464 const char *server_name,
8465 struct spoolss_AddDriverInfo8 *r,
8466 uint32_t flags,
8467 bool ex,
8468 const char *remote_driver_dir)
8470 struct spoolss_AddDriverInfoCtr info_ctr;
8471 union spoolss_DriverInfo info;
8473 info_ctr.level = 8;
8474 info_ctr.info.info8 = r;
8476 if (ex) {
8477 torture_assert(tctx,
8478 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8479 "failed to test AddPrinterDriverEx level 8");
8480 } else {
8481 torture_assert(tctx,
8482 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8483 "failed to test AddPrinterDriver level 8");
8486 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8488 if (!ex) {
8489 return true;
8492 torture_assert(tctx,
8493 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8494 "failed to find added printer driver");
8496 if (remote_driver_dir) {
8497 int i;
8498 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8499 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8500 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8501 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8502 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8503 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8507 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8509 return true;
8512 #undef ASSERT_DRIVER_PATH
8514 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8515 struct dcerpc_binding_handle *b,
8516 const char *server,
8517 const char *driver,
8518 const char *environment,
8519 WERROR expected_result)
8521 struct spoolss_DeletePrinterDriver r;
8523 r.in.server = server;
8524 r.in.architecture = environment;
8525 r.in.driver = driver;
8527 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8529 torture_assert_ntstatus_ok(tctx,
8530 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8531 "DeletePrinterDriver failed");
8532 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8533 "DeletePrinterDriver failed with unexpected result");
8535 return true;
8538 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8539 struct dcerpc_binding_handle *b,
8540 const char *server,
8541 const char *driver,
8542 const char *environment,
8543 uint32_t delete_flags,
8544 uint32_t version,
8545 WERROR expected_result)
8547 struct spoolss_DeletePrinterDriverEx r;
8549 r.in.server = server;
8550 r.in.architecture = environment;
8551 r.in.driver = driver;
8552 r.in.delete_flags = delete_flags;
8553 r.in.version = version;
8555 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8557 torture_assert_ntstatus_ok(tctx,
8558 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8559 "DeletePrinterDriverEx failed");
8560 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8561 "DeletePrinterDriverEx failed with unexpected result");
8563 return true;
8566 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8567 struct dcerpc_binding_handle *b,
8568 const char *server_name,
8569 const char *driver,
8570 const char *environment)
8572 torture_assert(tctx,
8573 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8574 "failed to delete driver");
8576 torture_assert(tctx,
8577 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8578 "failed to delete driver");
8580 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8581 torture_fail(tctx, "deleted driver still enumerated");
8584 torture_assert(tctx,
8585 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8586 "2nd delete failed");
8588 return true;
8591 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8592 struct dcerpc_binding_handle *b,
8593 const char *server_name,
8594 const char *driver,
8595 const char *environment,
8596 uint32_t delete_flags,
8597 uint32_t version)
8599 torture_assert(tctx,
8600 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8601 "failed to delete driver");
8603 torture_assert(tctx,
8604 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8605 "failed to delete driver");
8607 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8608 torture_fail(tctx, "deleted driver still enumerated");
8611 torture_assert(tctx,
8612 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8613 "2nd delete failed");
8615 return true;
8618 static bool test_PrinterDriver_args(struct torture_context *tctx,
8619 struct dcerpc_binding_handle *b,
8620 const char *server_name,
8621 uint32_t level,
8622 struct spoolss_AddDriverInfo8 *r,
8623 uint32_t add_flags,
8624 uint32_t delete_flags,
8625 uint32_t delete_version,
8626 bool ex,
8627 const char *remote_driver_dir)
8629 bool ret = true;
8631 switch (level) {
8632 case 1:
8633 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8634 break;
8635 case 2:
8636 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8637 break;
8638 case 3:
8639 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8640 break;
8641 case 4:
8642 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8643 break;
8644 case 6:
8645 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8646 break;
8647 case 8:
8648 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8649 break;
8650 default:
8651 return false;
8654 if (ret == false) {
8655 return ret;
8658 if (level == 1) {
8659 return ret;
8662 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8664 if (!ex && (level == 6 || level == 8)) {
8665 return ret;
8669 struct dcerpc_pipe *p2;
8670 struct policy_handle hive_handle;
8671 struct dcerpc_binding_handle *b2;
8673 torture_assert_ntstatus_ok(tctx,
8674 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8675 "could not open winreg pipe");
8676 b2 = p2->binding_handle;
8678 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8680 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8682 test_winreg_CloseKey(tctx, b2, &hive_handle);
8684 talloc_free(p2);
8687 if (ex) {
8688 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8689 } else {
8690 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8694 static bool fillup_printserver_info(struct torture_context *tctx,
8695 struct dcerpc_pipe *p,
8696 struct torture_driver_context *d)
8698 struct policy_handle server_handle;
8699 struct dcerpc_binding_handle *b = p->binding_handle;
8700 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8702 torture_assert(tctx,
8703 test_OpenPrinter_server(tctx, p, &server_handle),
8704 "failed to open printserver");
8705 torture_assert(tctx,
8706 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8707 "failed to get environment");
8708 torture_assert(tctx,
8709 test_ClosePrinter(tctx, b, &server_handle),
8710 "failed to close printserver");
8712 torture_assert(tctx,
8713 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8714 d->local.environment ? d->local.environment : d->remote.environment,
8715 &d->remote.driver_directory),
8716 "failed to get driver directory");
8718 return true;
8721 static const char *driver_directory_dir(const char *driver_directory)
8723 char *p;
8725 p = strrchr(driver_directory, '\\');
8726 if (p) {
8727 return p+1;
8730 return NULL;
8733 static const char *driver_directory_share(struct torture_context *tctx,
8734 const char *driver_directory)
8736 const char *p;
8737 char *tok;
8739 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8740 driver_directory += 2;
8743 p = talloc_strdup(tctx, driver_directory);
8745 torture_assert(tctx,
8746 next_token_talloc(tctx, &p, &tok, "\\"),
8747 "cannot explode uri");
8748 torture_assert(tctx,
8749 next_token_talloc(tctx, &p, &tok, "\\"),
8750 "cannot explode uri");
8752 return tok;
8755 static bool upload_printer_driver_file(struct torture_context *tctx,
8756 struct smbcli_state *cli,
8757 struct torture_driver_context *d,
8758 const char *file_name)
8760 XFILE *f;
8761 int fnum;
8762 uint8_t *buf;
8763 int maxwrite = 64512;
8764 off_t nread = 0;
8765 size_t start = 0;
8766 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8767 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8768 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8770 if (!file_name || strlen(file_name) == 0) {
8771 return true;
8774 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8776 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8777 if (fnum == -1) {
8778 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8781 f = x_fopen(local_name, O_RDONLY, 0);
8782 if (f == NULL) {
8783 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8786 buf = talloc_array(tctx, uint8_t, maxwrite);
8787 if (!buf) {
8788 return false;
8791 while (!x_feof(f)) {
8792 int n = maxwrite;
8793 int ret;
8795 if ((n = x_fread(buf, 1, n, f)) < 1) {
8796 if((n == 0) && x_feof(f))
8797 break; /* Empty local file. */
8799 torture_warning(tctx,
8800 "failed to read file: %s\n", strerror(errno));
8801 break;
8804 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8806 if (n != ret) {
8807 torture_warning(tctx,
8808 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8809 break;
8812 nread += n;
8815 x_fclose(f);
8817 torture_assert_ntstatus_ok(tctx,
8818 smbcli_close(cli->tree, fnum),
8819 "failed to close file");
8821 return true;
8824 static bool connect_printer_driver_share(struct torture_context *tctx,
8825 const char *server_name,
8826 const char *share_name,
8827 struct smbcli_state **cli)
8829 struct smbcli_options smb_options;
8830 struct smbcli_session_options smb_session_options;
8832 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8833 share_name, server_name);
8835 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8836 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8838 torture_assert_ntstatus_ok(tctx,
8839 smbcli_full_connection(tctx, cli, server_name,
8840 lpcfg_smb_ports(tctx->lp_ctx),
8841 share_name, NULL,
8842 lpcfg_socket_options(tctx->lp_ctx),
8843 cmdline_credentials,
8844 lpcfg_resolve_context(tctx->lp_ctx),
8845 tctx->ev,
8846 &smb_options,
8847 &smb_session_options,
8848 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8849 "failed to open driver share");
8851 return true;
8854 static bool upload_printer_driver(struct torture_context *tctx,
8855 const char *server_name,
8856 struct torture_driver_context *d)
8858 struct smbcli_state *cli;
8859 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8860 int i;
8862 torture_assert(tctx,
8863 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8864 "failed to connect to driver share");
8866 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8867 server_name, share_name);
8869 torture_assert(tctx,
8870 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8871 "failed to upload driver_path");
8872 torture_assert(tctx,
8873 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8874 "failed to upload data_file");
8875 torture_assert(tctx,
8876 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8877 "failed to upload config_file");
8878 torture_assert(tctx,
8879 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8880 "failed to upload help_file");
8881 if (d->info8.dependent_files) {
8882 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8883 torture_assert(tctx,
8884 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8885 "failed to upload dependent_files");
8889 talloc_free(cli);
8891 return true;
8894 static bool remove_printer_driver_file(struct torture_context *tctx,
8895 struct smbcli_state *cli,
8896 struct torture_driver_context *d,
8897 const char *file_name)
8899 const char *remote_name;
8900 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8902 if (!file_name || strlen(file_name) == 0) {
8903 return true;
8906 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8908 torture_comment(tctx, "Removing %s\n", remote_name);
8910 torture_assert_ntstatus_ok(tctx,
8911 smbcli_unlink(cli->tree, remote_name),
8912 "failed to unlink");
8914 return true;
8917 static bool remove_printer_driver(struct torture_context *tctx,
8918 const char *server_name,
8919 struct torture_driver_context *d)
8921 struct smbcli_state *cli;
8922 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8923 int i;
8925 torture_assert(tctx,
8926 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8927 "failed to connect to driver share");
8929 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8930 server_name, share_name);
8932 torture_assert(tctx,
8933 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8934 "failed to remove driver_path");
8935 torture_assert(tctx,
8936 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8937 "failed to remove data_file");
8938 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
8939 torture_assert(tctx,
8940 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8941 "failed to remove config_file");
8943 torture_assert(tctx,
8944 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8945 "failed to remove help_file");
8946 if (d->info8.dependent_files) {
8947 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8948 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8949 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8950 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8951 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8952 continue;
8954 torture_assert(tctx,
8955 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8956 "failed to remove dependent_files");
8960 talloc_free(cli);
8962 return true;
8966 static bool test_add_driver_arg(struct torture_context *tctx,
8967 struct dcerpc_pipe *p,
8968 struct torture_driver_context *d)
8970 bool ret = true;
8971 struct dcerpc_binding_handle *b = p->binding_handle;
8972 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8973 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8974 int i;
8975 struct spoolss_AddDriverInfo8 info8;
8976 uint32_t add_flags = APD_COPY_NEW_FILES;
8977 uint32_t delete_flags = 0;
8979 ZERO_STRUCT(info8);
8981 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8982 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8984 torture_assert(tctx,
8985 fillup_printserver_info(tctx, p, d),
8986 "failed to fillup printserver info");
8988 if (!directory_exist(d->local.driver_directory)) {
8989 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8992 torture_assert(tctx,
8993 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8994 "failed to upload printer driver");
8996 info8.version = d->info8.version;
8997 info8.driver_name = d->info8.driver_name;
8998 info8.architecture = d->local.environment;
8999 info8.driver_path = d->info8.driver_path;
9000 info8.data_file = d->info8.data_file;
9001 info8.config_file = d->info8.config_file;
9003 for (i=0; i < ARRAY_SIZE(levels); i++) {
9005 if (torture_setting_bool(tctx, "samba3", false)) {
9006 switch (levels[i]) {
9007 case 2:
9008 case 4:
9009 case 8:
9010 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9011 continue;
9012 default:
9013 break;
9016 if (torture_setting_bool(tctx, "w2k3", false)) {
9017 switch (levels[i]) {
9018 case 8:
9019 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9020 continue;
9021 default:
9022 break;
9026 torture_comment(tctx,
9027 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9028 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9030 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
9033 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9034 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9035 if (d->info8.config_file) {
9036 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9039 for (i=0; i < ARRAY_SIZE(levels); i++) {
9041 if (torture_setting_bool(tctx, "samba3", false)) {
9042 switch (levels[i]) {
9043 case 2:
9044 case 4:
9045 case 8:
9046 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9047 continue;
9048 default:
9049 break;
9052 if (torture_setting_bool(tctx, "w2k3", false)) {
9053 switch (levels[i]) {
9054 case 8:
9055 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9056 continue;
9057 default:
9058 break;
9062 torture_comment(tctx,
9063 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9064 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9066 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
9069 torture_assert(tctx,
9070 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9071 "failed to remove printer driver");
9073 torture_comment(tctx, "\n");
9075 return ret;
9078 static bool test_add_driver_ex_64(struct torture_context *tctx,
9079 struct dcerpc_pipe *p)
9081 struct torture_driver_context *d;
9083 d = talloc_zero(tctx, struct torture_driver_context);
9085 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9086 d->info8.driver_name = TORTURE_DRIVER_EX;
9087 d->info8.architecture = NULL;
9088 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9089 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9090 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9091 d->local.environment = talloc_strdup(d, "Windows x64");
9092 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9093 d->ex = true;
9095 return test_add_driver_arg(tctx, p, d);
9098 static bool test_add_driver_ex_32(struct torture_context *tctx,
9099 struct dcerpc_pipe *p)
9101 struct torture_driver_context *d;
9103 d = talloc_zero(tctx, struct torture_driver_context);
9105 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9106 d->info8.driver_name = TORTURE_DRIVER_EX;
9107 d->info8.architecture = NULL;
9108 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9109 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9110 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9111 d->local.environment = talloc_strdup(d, "Windows NT x86");
9112 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9113 d->ex = true;
9115 return test_add_driver_arg(tctx, p, d);
9118 static bool test_add_driver_64(struct torture_context *tctx,
9119 struct dcerpc_pipe *p)
9121 struct torture_driver_context *d;
9123 d = talloc_zero(tctx, struct torture_driver_context);
9125 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9126 d->info8.driver_name = TORTURE_DRIVER;
9127 d->info8.architecture = NULL;
9128 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9129 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9130 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9131 d->local.environment = talloc_strdup(d, "Windows x64");
9132 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9133 d->ex = false;
9135 return test_add_driver_arg(tctx, p, d);
9138 static bool test_add_driver_32(struct torture_context *tctx,
9139 struct dcerpc_pipe *p)
9141 struct torture_driver_context *d;
9143 d = talloc_zero(tctx, struct torture_driver_context);
9145 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9146 d->info8.driver_name = TORTURE_DRIVER;
9147 d->info8.architecture = NULL;
9148 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9149 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9150 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9151 d->local.environment = talloc_strdup(d, "Windows NT x86");
9152 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9153 d->ex = false;
9155 return test_add_driver_arg(tctx, p, d);
9158 static bool test_add_driver_adobe(struct torture_context *tctx,
9159 struct dcerpc_pipe *p)
9161 struct torture_driver_context *d;
9163 d = talloc_zero(tctx, struct torture_driver_context);
9165 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9166 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9167 d->info8.architecture = NULL;
9168 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9169 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9170 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9171 #if 0
9172 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9173 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9174 #endif
9175 d->local.environment = talloc_strdup(d, "Windows 4.0");
9176 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9177 d->ex = false;
9179 return test_add_driver_arg(tctx, p, d);
9182 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9183 struct dcerpc_pipe *p)
9185 struct torture_driver_context *d;
9186 struct spoolss_StringArray *a;
9188 if (!torture_setting_bool(tctx, "samba3", false)) {
9189 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9192 d = talloc_zero(tctx, struct torture_driver_context);
9194 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9195 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9196 d->info8.architecture = NULL;
9197 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9198 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9199 d->info8.config_file = NULL;
9200 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9201 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9202 d->info8.default_datatype = talloc_strdup(d, "RAW");
9204 a = talloc_zero(d, struct spoolss_StringArray);
9205 a->string = talloc_zero_array(a, const char *, 7);
9206 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9207 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9208 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9209 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9210 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9211 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9213 d->info8.dependent_files = a;
9214 d->local.environment = talloc_strdup(d, "Windows 4.0");
9215 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9216 d->ex = false;
9218 return test_add_driver_arg(tctx, p, d);
9221 static bool test_add_driver_timestamps(struct torture_context *tctx,
9222 struct dcerpc_pipe *p)
9224 struct torture_driver_context *d;
9225 struct timeval t = timeval_current();
9227 if (torture_setting_bool(tctx, "samba3", false)) {
9228 torture_skip(tctx, "skipping timestamps test against samba");
9231 d = talloc_zero(tctx, struct torture_driver_context);
9233 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9234 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9235 d->info8.architecture = NULL;
9236 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9237 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9238 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9239 d->info8.driver_date = timeval_to_nttime(&t);
9240 d->local.environment = talloc_strdup(d, "Windows NT x86");
9241 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9242 d->ex = true;
9244 torture_assert(tctx,
9245 test_add_driver_arg(tctx, p, d),
9246 "");
9248 unix_to_nt_time(&d->info8.driver_date, 1);
9250 torture_assert(tctx,
9251 test_add_driver_arg(tctx, p, d),
9252 "");
9254 return true;
9257 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9259 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9261 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9262 "driver", &ndr_table_spoolss);
9263 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9264 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9266 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9267 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9269 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9271 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9273 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9275 return suite;