spoolss: Make OpenPrinterEx work with NDR64 by using UserInfo Container.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / spoolss.c
blob064d3b434dab140b27ae0bd099137fff4e5001dd
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Stefan Metzmacher 2005
7 Copyright (C) Jelmer Vernooij 2007
8 Copyright (C) Guenther Deschner 2009-2011
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "libcli/smb2/smb2.h"
39 #include "libcli/smb2/smb2_calls.h"
40 #include "lib/cmdline/popt_common.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
45 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
46 #define TORTURE_PRINTER "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX "torture_printer_ex"
49 #define TORTURE_DRIVER "torture_driver"
50 #define TORTURE_DRIVER_EX "torture_driver_ex"
51 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
52 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
53 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
54 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
55 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
56 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
57 #define TORTURE_PRINTER_STATIC1 "print1"
59 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
60 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
61 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
62 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
63 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
64 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
66 struct test_spoolss_context {
67 struct dcerpc_pipe *spoolss_pipe;
69 /* server environment */
70 const char *environment;
72 /* print server handle */
73 struct policy_handle server_handle;
75 /* for EnumPorts */
76 uint32_t port_count[3];
77 union spoolss_PortInfo *ports[3];
79 /* for EnumPrinterDrivers */
80 uint32_t driver_count[8];
81 union spoolss_DriverInfo *drivers[8];
83 /* for EnumMonitors */
84 uint32_t monitor_count[3];
85 union spoolss_MonitorInfo *monitors[3];
87 /* for EnumPrintProcessors */
88 uint32_t print_processor_count[2];
89 union spoolss_PrintProcessorInfo *print_processors[2];
91 /* for EnumPrinters */
92 uint32_t printer_count[6];
93 union spoolss_PrinterInfo *printers[6];
96 struct torture_driver_context {
97 struct {
98 const char *driver_directory;
99 const char *environment;
100 } local;
101 struct {
102 const char *driver_directory;
103 const char *environment;
104 } remote;
105 struct spoolss_AddDriverInfo8 info8;
106 bool ex;
109 struct torture_printer_context {
110 struct dcerpc_pipe *spoolss_pipe;
111 struct spoolss_SetPrinterInfo2 info2;
112 struct torture_driver_context driver;
113 bool ex;
114 bool wellknown;
115 bool added_driver;
116 bool have_driver;
117 struct spoolss_DeviceMode *devmode;
118 struct policy_handle handle;
121 static bool upload_printer_driver(struct torture_context *tctx,
122 const char *server_name,
123 struct torture_driver_context *d);
124 static bool remove_printer_driver(struct torture_context *tctx,
125 const char *server_name,
126 struct torture_driver_context *d);
127 static bool fillup_printserver_info(struct torture_context *tctx,
128 struct dcerpc_pipe *p,
129 struct torture_driver_context *d);
130 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
131 struct dcerpc_binding_handle *b,
132 const char *server_name,
133 struct spoolss_AddDriverInfo8 *r,
134 uint32_t flags,
135 bool ex,
136 const char *remote_driver_dir);
138 #define COMPARE_STRING(tctx, c,r,e) \
139 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
141 /* not every compiler supports __typeof__() */
142 #if (__GNUC__ >= 3)
143 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
144 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
145 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
147 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
148 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
150 } while(0)
151 #else
152 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
153 #endif
155 #define COMPARE_UINT32(tctx, c, r, e) do {\
156 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
157 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
158 } while(0)
160 #define COMPARE_UINT64(tctx, c, r, e) do {\
161 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
162 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
163 } while(0)
166 #define COMPARE_NTTIME(tctx, c, r, e) do {\
167 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
168 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
169 } while(0)
171 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
172 int __i; \
173 if (!c.e && !r.e) { \
174 break; \
176 if (c.e && !r.e) { \
177 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
179 if (!c.e && r.e) { \
180 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
182 for (__i=0;c.e[__i] != NULL; __i++) { \
183 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
185 } while(0)
187 #define CHECK_ALIGN(size, n) do {\
188 if (size % n) {\
189 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
190 size, n, size + n - (size % n));\
192 } while(0)
194 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
196 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
197 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
198 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
199 uint32_t round_size = DO_ROUND(size, align);\
200 if (round_size != needed) {\
201 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
202 CHECK_ALIGN(size, align);\
205 } while(0)
207 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
208 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
209 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
210 uint32_t round_size = DO_ROUND(size, align);\
211 if (round_size != needed) {\
212 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
213 CHECK_ALIGN(size, align);\
216 } while(0)
218 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
219 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
220 uint32_t size = ndr_size_##fn(info, level, 0);\
221 uint32_t round_size = DO_ROUND(size, align);\
222 if (round_size != needed) {\
223 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
224 CHECK_ALIGN(size, align);\
227 } while(0)
229 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
230 const union spoolss_PrinterInfo *i,
231 uint32_t level,
232 union spoolss_SetPrinterInfo *s)
234 switch (level) {
235 case 0:
236 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
237 break;
238 case 2:
239 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
240 s->info2->servername = i->info2.servername;
241 s->info2->printername = i->info2.printername;
242 s->info2->sharename = i->info2.sharename;
243 s->info2->portname = i->info2.portname;
244 s->info2->drivername = i->info2.drivername;
245 s->info2->comment = i->info2.comment;
246 s->info2->location = i->info2.location;
247 s->info2->devmode_ptr = 0;
248 s->info2->sepfile = i->info2.sepfile;
249 s->info2->printprocessor = i->info2.printprocessor;
250 s->info2->datatype = i->info2.datatype;
251 s->info2->parameters = i->info2.parameters;
252 s->info2->secdesc_ptr = 0;
253 s->info2->attributes = i->info2.attributes;
254 s->info2->priority = i->info2.priority;
255 s->info2->defaultpriority = i->info2.defaultpriority;
256 s->info2->starttime = i->info2.starttime;
257 s->info2->untiltime = i->info2.untiltime;
258 s->info2->status = i->info2.status;
259 s->info2->cjobs = i->info2.cjobs;
260 s->info2->averageppm = i->info2.averageppm;
261 break;
262 case 3:
263 case 4:
264 case 5:
265 case 6:
266 case 7:
267 case 8:
268 case 9:
269 default:
270 return false;
273 return true;
276 static bool test_OpenPrinter_server(struct torture_context *tctx,
277 struct dcerpc_pipe *p,
278 struct policy_handle *server_handle)
280 NTSTATUS status;
281 struct spoolss_OpenPrinter op;
282 struct dcerpc_binding_handle *b = p->binding_handle;
284 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
285 op.in.datatype = NULL;
286 op.in.devmode_ctr.devmode= NULL;
287 op.in.access_mask = 0;
288 op.out.handle = server_handle;
290 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
292 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
293 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
294 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
296 return true;
299 static bool test_EnumPorts(struct torture_context *tctx,
300 void *private_data)
302 struct test_spoolss_context *ctx =
303 talloc_get_type_abort(private_data, struct test_spoolss_context);
304 struct dcerpc_pipe *p = ctx->spoolss_pipe;
305 struct dcerpc_binding_handle *b = p->binding_handle;
306 NTSTATUS status;
307 struct spoolss_EnumPorts r;
308 uint16_t levels[] = { 1, 2 };
309 int i, j;
311 for (i=0;i<ARRAY_SIZE(levels);i++) {
312 int level = levels[i];
313 DATA_BLOB blob;
314 uint32_t needed;
315 uint32_t count;
316 union spoolss_PortInfo *info;
318 r.in.servername = "";
319 r.in.level = level;
320 r.in.buffer = NULL;
321 r.in.offered = 0;
322 r.out.needed = &needed;
323 r.out.count = &count;
324 r.out.info = &info;
326 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
328 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
329 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
330 if (W_ERROR_IS_OK(r.out.result)) {
331 /* TODO: do some more checks here */
332 continue;
334 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
335 "EnumPorts unexpected return code");
337 blob = data_blob_talloc_zero(ctx, needed);
338 r.in.buffer = &blob;
339 r.in.offered = needed;
341 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
342 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
344 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
346 torture_assert(tctx, info, "EnumPorts returned no info");
348 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
350 ctx->port_count[level] = count;
351 ctx->ports[level] = info;
354 for (i=1;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 int old_level = levels[i-1];
357 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
358 "EnumPorts invalid value");
360 /* if the array sizes are not the same we would maybe segfault in the following code */
362 for (i=0;i<ARRAY_SIZE(levels);i++) {
363 int level = levels[i];
364 for (j=0;j<ctx->port_count[level];j++) {
365 union spoolss_PortInfo *cur = &ctx->ports[level][j];
366 union spoolss_PortInfo *ref = &ctx->ports[2][j];
367 switch (level) {
368 case 1:
369 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
370 break;
371 case 2:
372 /* level 2 is our reference, and it makes no sense to compare it to itself */
373 break;
378 return true;
381 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
382 void *private_data)
384 struct test_spoolss_context *ctx =
385 talloc_get_type_abort(private_data, struct test_spoolss_context);
387 NTSTATUS status;
388 struct dcerpc_pipe *p = ctx->spoolss_pipe;
389 struct dcerpc_binding_handle *b = p->binding_handle;
390 struct spoolss_GetPrintProcessorDirectory r;
391 struct {
392 uint16_t level;
393 const char *server;
394 } levels[] = {{
395 .level = 1,
396 .server = NULL
398 .level = 1,
399 .server = ""
401 .level = 78,
402 .server = ""
404 .level = 1,
405 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
407 .level = 1024,
408 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
411 int i;
412 uint32_t needed;
414 for (i=0;i<ARRAY_SIZE(levels);i++) {
415 int level = levels[i].level;
416 DATA_BLOB blob;
418 r.in.server = levels[i].server;
419 r.in.environment = ctx->environment;
420 r.in.level = level;
421 r.in.buffer = NULL;
422 r.in.offered = 0;
423 r.out.needed = &needed;
425 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
427 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
428 torture_assert_ntstatus_ok(tctx, status,
429 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
430 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
431 "GetPrintProcessorDirectory unexpected return code");
433 blob = data_blob_talloc_zero(tctx, needed);
434 r.in.buffer = &blob;
435 r.in.offered = needed;
437 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
438 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
440 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
442 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
445 return true;
449 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
450 void *private_data)
452 struct test_spoolss_context *ctx =
453 talloc_get_type_abort(private_data, struct test_spoolss_context);
455 NTSTATUS status;
456 struct dcerpc_pipe *p = ctx->spoolss_pipe;
457 struct dcerpc_binding_handle *b = p->binding_handle;
458 struct spoolss_GetPrinterDriverDirectory r;
459 struct {
460 uint16_t level;
461 const char *server;
462 } levels[] = {{
463 .level = 1,
464 .server = NULL
466 .level = 1,
467 .server = ""
469 .level = 78,
470 .server = ""
472 .level = 1,
473 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
475 .level = 1024,
476 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
479 int i;
480 uint32_t needed;
482 for (i=0;i<ARRAY_SIZE(levels);i++) {
483 int level = levels[i].level;
484 DATA_BLOB blob;
486 r.in.server = levels[i].server;
487 r.in.environment = ctx->environment;
488 r.in.level = level;
489 r.in.buffer = NULL;
490 r.in.offered = 0;
491 r.out.needed = &needed;
493 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
495 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
496 torture_assert_ntstatus_ok(tctx, status,
497 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
498 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
499 "GetPrinterDriverDirectory unexpected return code");
501 blob = data_blob_talloc_zero(tctx, needed);
502 r.in.buffer = &blob;
503 r.in.offered = needed;
505 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
506 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
508 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
510 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
513 return true;
516 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
517 struct dcerpc_binding_handle *b,
518 const char *server_name,
519 const char *environment,
520 uint32_t level,
521 uint32_t *count_p,
522 union spoolss_DriverInfo **info_p)
524 struct spoolss_EnumPrinterDrivers r;
525 uint32_t needed;
526 uint32_t count;
527 union spoolss_DriverInfo *info;
529 r.in.server = server_name;
530 r.in.environment = environment;
531 r.in.level = level;
532 r.in.buffer = NULL;
533 r.in.offered = 0;
534 r.out.needed = &needed;
535 r.out.count = &count;
536 r.out.info = &info;
538 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
539 r.in.environment, r.in.level);
541 torture_assert_ntstatus_ok(tctx,
542 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
543 "EnumPrinterDrivers failed");
544 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
545 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
546 r.in.buffer = &blob;
547 r.in.offered = needed;
549 torture_assert_ntstatus_ok(tctx,
550 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
551 "EnumPrinterDrivers failed");
554 torture_assert_werr_ok(tctx, r.out.result,
555 "EnumPrinterDrivers failed");
557 if (count_p) {
558 *count_p = count;
560 if (info_p) {
561 *info_p = info;
564 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
566 return true;
570 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
571 struct dcerpc_binding_handle *b,
572 const char *server_name,
573 const char *environment,
574 uint32_t level,
575 const char *driver_name,
576 union spoolss_DriverInfo *info_p)
578 uint32_t count;
579 union spoolss_DriverInfo *info;
580 int i;
581 const char *environment_ret = NULL;
583 torture_assert(tctx,
584 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
585 "failed to enumerate printer drivers");
587 for (i=0; i < count; i++) {
588 const char *driver_name_ret;
589 switch (level) {
590 case 1:
591 driver_name_ret = info[i].info1.driver_name;
592 break;
593 case 2:
594 driver_name_ret = info[i].info2.driver_name;
595 environment_ret = info[i].info2.architecture;
596 break;
597 case 3:
598 driver_name_ret = info[i].info3.driver_name;
599 environment_ret = info[i].info3.architecture;
600 break;
601 case 4:
602 driver_name_ret = info[i].info4.driver_name;
603 environment_ret = info[i].info4.architecture;
604 break;
605 case 5:
606 driver_name_ret = info[i].info5.driver_name;
607 environment_ret = info[i].info5.architecture;
608 break;
609 case 6:
610 driver_name_ret = info[i].info6.driver_name;
611 environment_ret = info[i].info6.architecture;
612 break;
613 case 7:
614 driver_name_ret = info[i].info7.driver_name;
615 break;
616 case 8:
617 driver_name_ret = info[i].info8.driver_name;
618 environment_ret = info[i].info8.architecture;
619 break;
620 default:
621 break;
623 if (environment_ret) {
624 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
626 if (strequal(driver_name, driver_name_ret)) {
627 if (info_p) {
628 *info_p = info[i];
630 return true;
634 return false;
637 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
638 void *private_data)
640 struct test_spoolss_context *ctx =
641 talloc_get_type_abort(private_data, struct test_spoolss_context);
642 struct dcerpc_pipe *p = ctx->spoolss_pipe;
643 struct dcerpc_binding_handle *b = p->binding_handle;
644 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
645 int i, j, a;
647 /* FIXME: gd, come back and fix "" as server, and handle
648 * priority of returned error codes in torture test and samba 3
649 * server */
650 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
651 const char *environments[2];
653 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
654 environments[1] = ctx->environment;
656 for (a=0;a<ARRAY_SIZE(environments);a++) {
658 for (i=0;i<ARRAY_SIZE(levels);i++) {
659 int level = levels[i];
660 uint32_t count;
661 union spoolss_DriverInfo *info;
663 torture_assert(tctx,
664 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
665 "failed to enumerate drivers");
667 ctx->driver_count[level] = count;
668 ctx->drivers[level] = info;
671 for (i=1;i<ARRAY_SIZE(levels);i++) {
672 int level = levels[i];
673 int old_level = levels[i-1];
675 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
676 "EnumPrinterDrivers invalid value");
679 for (i=0;i<ARRAY_SIZE(levels);i++) {
680 int level = levels[i];
682 for (j=0;j<ctx->driver_count[level];j++) {
683 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
684 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
686 switch (level) {
687 case 1:
688 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
689 break;
690 case 2:
691 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
692 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
693 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
694 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
695 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
696 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
697 break;
698 case 3:
699 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
704 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
705 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
706 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
707 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
708 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
709 break;
710 case 4:
711 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
716 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
717 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
718 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
719 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
720 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
721 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
722 break;
723 case 5:
724 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
725 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
726 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
727 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
728 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
729 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
730 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
731 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
732 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
733 break;
734 case 6:
735 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
740 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
741 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
742 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
745 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
746 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
747 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
748 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
749 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
750 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
751 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
752 break;
753 case 8:
754 /* level 8 is our reference, and it makes no sense to compare it to itself */
755 break;
761 return true;
764 static bool test_EnumMonitors(struct torture_context *tctx,
765 void *private_data)
767 struct test_spoolss_context *ctx =
768 talloc_get_type_abort(private_data, struct test_spoolss_context);
769 struct dcerpc_pipe *p = ctx->spoolss_pipe;
770 struct dcerpc_binding_handle *b = p->binding_handle;
771 NTSTATUS status;
772 struct spoolss_EnumMonitors r;
773 uint16_t levels[] = { 1, 2 };
774 int i, j;
776 for (i=0;i<ARRAY_SIZE(levels);i++) {
777 int level = levels[i];
778 DATA_BLOB blob;
779 uint32_t needed;
780 uint32_t count;
781 union spoolss_MonitorInfo *info;
783 r.in.servername = "";
784 r.in.level = level;
785 r.in.buffer = NULL;
786 r.in.offered = 0;
787 r.out.needed = &needed;
788 r.out.count = &count;
789 r.out.info = &info;
791 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
793 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
794 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
795 if (W_ERROR_IS_OK(r.out.result)) {
796 /* TODO: do some more checks here */
797 continue;
799 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
800 "EnumMonitors failed");
802 blob = data_blob_talloc_zero(ctx, needed);
803 r.in.buffer = &blob;
804 r.in.offered = needed;
806 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
807 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
809 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
811 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
813 ctx->monitor_count[level] = count;
814 ctx->monitors[level] = info;
817 for (i=1;i<ARRAY_SIZE(levels);i++) {
818 int level = levels[i];
819 int old_level = levels[i-1];
820 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
821 "EnumMonitors invalid value");
824 for (i=0;i<ARRAY_SIZE(levels);i++) {
825 int level = levels[i];
826 for (j=0;j<ctx->monitor_count[level];j++) {
827 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
828 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
829 switch (level) {
830 case 1:
831 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
832 break;
833 case 2:
834 /* level 2 is our reference, and it makes no sense to compare it to itself */
835 break;
840 return true;
843 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
844 struct dcerpc_binding_handle *b,
845 const char *environment,
846 uint32_t level,
847 uint32_t *count_p,
848 union spoolss_PrintProcessorInfo **info_p,
849 WERROR expected_result)
851 struct spoolss_EnumPrintProcessors r;
852 DATA_BLOB blob;
853 uint32_t needed;
854 uint32_t count;
855 union spoolss_PrintProcessorInfo *info;
857 r.in.servername = "";
858 r.in.environment = environment;
859 r.in.level = level;
860 r.in.buffer = NULL;
861 r.in.offered = 0;
862 r.out.needed = &needed;
863 r.out.count = &count;
864 r.out.info = &info;
866 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
867 r.in.environment, r.in.level);
869 torture_assert_ntstatus_ok(tctx,
870 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
871 "EnumPrintProcessors failed");
872 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
873 blob = data_blob_talloc_zero(tctx, needed);
874 r.in.buffer = &blob;
875 r.in.offered = needed;
876 torture_assert_ntstatus_ok(tctx,
877 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
878 "EnumPrintProcessors failed");
880 torture_assert_werr_equal(tctx, r.out.result, expected_result,
881 "EnumPrintProcessors failed");
883 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
885 if (count_p) {
886 *count_p = count;
888 if (info_p) {
889 *info_p = info;
892 return true;
895 static bool test_EnumPrintProcessors(struct torture_context *tctx,
896 void *private_data)
898 struct test_spoolss_context *ctx =
899 talloc_get_type_abort(private_data, struct test_spoolss_context);
901 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
902 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
903 int i;
904 struct dcerpc_pipe *p = ctx->spoolss_pipe;
905 struct dcerpc_binding_handle *b = p->binding_handle;
907 torture_assert(tctx,
908 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
909 "test_EnumPrintProcessors_level failed");
911 for (i=0;i<ARRAY_SIZE(levels);i++) {
912 union spoolss_PrintProcessorInfo *info;
913 uint32_t count;
914 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
916 torture_assert(tctx,
917 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
918 "test_EnumPrintProcessors_level failed");
921 return true;
924 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
925 struct dcerpc_binding_handle *b,
926 const char *print_processor_name,
927 uint32_t level,
928 uint32_t *count_p,
929 union spoolss_PrintProcDataTypesInfo **info_p,
930 WERROR expected_result)
932 struct spoolss_EnumPrintProcDataTypes r;
933 DATA_BLOB blob;
934 uint32_t needed;
935 uint32_t count;
936 union spoolss_PrintProcDataTypesInfo *info;
938 r.in.servername = "";
939 r.in.print_processor_name = print_processor_name;
940 r.in.level = level;
941 r.in.buffer = NULL;
942 r.in.offered = 0;
943 r.out.needed = &needed;
944 r.out.count = &count;
945 r.out.info = &info;
947 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
948 r.in.print_processor_name, r.in.level);
950 torture_assert_ntstatus_ok(tctx,
951 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
952 "EnumPrintProcDataTypes failed");
953 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
954 blob = data_blob_talloc_zero(tctx, needed);
955 r.in.buffer = &blob;
956 r.in.offered = needed;
957 torture_assert_ntstatus_ok(tctx,
958 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
959 "EnumPrintProcDataTypes failed");
961 torture_assert_werr_equal(tctx, r.out.result, expected_result,
962 "EnumPrintProcDataTypes failed");
964 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
966 if (count_p) {
967 *count_p = count;
969 if (info_p) {
970 *info_p = info;
973 return true;
976 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
977 void *private_data)
979 struct test_spoolss_context *ctx =
980 talloc_get_type_abort(private_data, struct test_spoolss_context);
982 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
983 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
984 int i;
985 struct dcerpc_pipe *p = ctx->spoolss_pipe;
986 struct dcerpc_binding_handle *b = p->binding_handle;
988 torture_assert(tctx,
989 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
990 "test_EnumPrintProcDataTypes_level failed");
992 torture_assert(tctx,
993 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
994 "test_EnumPrintProcDataTypes_level failed");
996 for (i=0;i<ARRAY_SIZE(levels);i++) {
997 int level = levels[i];
998 uint32_t count;
999 union spoolss_PrintProcDataTypesInfo *info;
1000 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1002 torture_assert(tctx,
1003 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1004 "test_EnumPrintProcDataTypes_level failed");
1008 union spoolss_PrintProcessorInfo *info;
1009 uint32_t count;
1011 torture_assert(tctx,
1012 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1013 "test_EnumPrintProcessors_level failed");
1015 for (i=0; i < count; i++) {
1016 torture_assert(tctx,
1017 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1018 "test_EnumPrintProcDataTypes_level failed");
1023 return true;
1026 static bool test_EnumPrinters(struct torture_context *tctx,
1027 void *private_data)
1029 struct test_spoolss_context *ctx =
1030 talloc_get_type_abort(private_data, struct test_spoolss_context);
1031 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1032 struct dcerpc_binding_handle *b = p->binding_handle;
1033 struct spoolss_EnumPrinters r;
1034 NTSTATUS status;
1035 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1036 int i, j;
1038 for (i=0;i<ARRAY_SIZE(levels);i++) {
1039 int level = levels[i];
1040 DATA_BLOB blob;
1041 uint32_t needed;
1042 uint32_t count;
1043 union spoolss_PrinterInfo *info;
1045 r.in.flags = PRINTER_ENUM_LOCAL;
1046 r.in.server = "";
1047 r.in.level = level;
1048 r.in.buffer = NULL;
1049 r.in.offered = 0;
1050 r.out.needed = &needed;
1051 r.out.count = &count;
1052 r.out.info = &info;
1054 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1056 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1057 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1058 if (W_ERROR_IS_OK(r.out.result)) {
1059 /* TODO: do some more checks here */
1060 continue;
1062 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1063 "EnumPrinters unexpected return code");
1065 blob = data_blob_talloc_zero(ctx, needed);
1066 r.in.buffer = &blob;
1067 r.in.offered = needed;
1069 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1070 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1072 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1074 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1076 ctx->printer_count[level] = count;
1077 ctx->printers[level] = info;
1080 for (i=1;i<ARRAY_SIZE(levels);i++) {
1081 int level = levels[i];
1082 int old_level = levels[i-1];
1083 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1084 "EnumPrinters invalid value");
1087 for (i=0;i<ARRAY_SIZE(levels);i++) {
1088 int level = levels[i];
1089 for (j=0;j<ctx->printer_count[level];j++) {
1090 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1091 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1092 switch (level) {
1093 case 0:
1094 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1095 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1097 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1099 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1112 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1113 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1116 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1117 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1118 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1119 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1120 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1121 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1122 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1123 break;
1124 case 1:
1125 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1126 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1127 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1128 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1129 break;
1130 case 2:
1131 /* level 2 is our reference, and it makes no sense to compare it to itself */
1132 break;
1133 case 4:
1134 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1135 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1136 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1137 break;
1138 case 5:
1139 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1140 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1141 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1142 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1143 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1144 break;
1149 /* TODO:
1150 * - verify that the port of a printer was in the list returned by EnumPorts
1153 return true;
1156 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1157 struct dcerpc_binding_handle *b,
1158 struct policy_handle *handle,
1159 const char *driver_name,
1160 const char *environment);
1162 bool test_GetPrinter_level(struct torture_context *tctx,
1163 struct dcerpc_binding_handle *b,
1164 struct policy_handle *handle,
1165 uint32_t level,
1166 union spoolss_PrinterInfo *info)
1168 struct spoolss_GetPrinter r;
1169 uint32_t needed;
1171 r.in.handle = handle;
1172 r.in.level = level;
1173 r.in.buffer = NULL;
1174 r.in.offered = 0;
1175 r.out.needed = &needed;
1177 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1179 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1180 "GetPrinter failed");
1182 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1183 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1184 r.in.buffer = &blob;
1185 r.in.offered = needed;
1187 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1188 "GetPrinter failed");
1191 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1193 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1195 if (info && r.out.info) {
1196 *info = *r.out.info;
1199 return true;
1203 static bool test_GetPrinter(struct torture_context *tctx,
1204 struct dcerpc_binding_handle *b,
1205 struct policy_handle *handle,
1206 const char *environment)
1208 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1209 int i;
1211 for (i=0;i<ARRAY_SIZE(levels);i++) {
1213 union spoolss_PrinterInfo info;
1215 ZERO_STRUCT(info);
1217 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1218 "failed to call GetPrinter");
1220 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1221 torture_assert(tctx,
1222 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1223 "failed to call test_GetPrinterDriver2");
1227 return true;
1230 static bool test_SetPrinter(struct torture_context *tctx,
1231 struct dcerpc_binding_handle *b,
1232 struct policy_handle *handle,
1233 struct spoolss_SetPrinterInfoCtr *info_ctr,
1234 struct spoolss_DevmodeContainer *devmode_ctr,
1235 struct sec_desc_buf *secdesc_ctr,
1236 enum spoolss_PrinterControl command)
1238 struct spoolss_SetPrinter r;
1240 r.in.handle = handle;
1241 r.in.info_ctr = info_ctr;
1242 r.in.devmode_ctr = devmode_ctr;
1243 r.in.secdesc_ctr = secdesc_ctr;
1244 r.in.command = command;
1246 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1248 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1249 "failed to call SetPrinter");
1250 torture_assert_werr_ok(tctx, r.out.result,
1251 "failed to call SetPrinter");
1253 return true;
1256 static bool test_SetPrinter_errors(struct torture_context *tctx,
1257 struct dcerpc_binding_handle *b,
1258 struct policy_handle *handle)
1260 struct spoolss_SetPrinter r;
1261 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1262 int i;
1264 struct spoolss_SetPrinterInfoCtr info_ctr;
1265 struct spoolss_DevmodeContainer devmode_ctr;
1266 struct sec_desc_buf secdesc_ctr;
1268 info_ctr.level = 0;
1269 info_ctr.info.info0 = NULL;
1271 ZERO_STRUCT(devmode_ctr);
1272 ZERO_STRUCT(secdesc_ctr);
1274 r.in.handle = handle;
1275 r.in.info_ctr = &info_ctr;
1276 r.in.devmode_ctr = &devmode_ctr;
1277 r.in.secdesc_ctr = &secdesc_ctr;
1278 r.in.command = 0;
1280 torture_comment(tctx, "Testing SetPrinter all zero\n");
1282 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1283 "failed to call SetPrinter");
1284 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1285 "failed to call SetPrinter");
1287 again:
1288 for (i=0; i < ARRAY_SIZE(levels); i++) {
1290 struct spoolss_SetPrinterInfo0 info0;
1291 struct spoolss_SetPrinterInfo1 info1;
1292 struct spoolss_SetPrinterInfo2 info2;
1293 struct spoolss_SetPrinterInfo3 info3;
1294 struct spoolss_SetPrinterInfo4 info4;
1295 struct spoolss_SetPrinterInfo5 info5;
1296 struct spoolss_SetPrinterInfo6 info6;
1297 struct spoolss_SetPrinterInfo7 info7;
1298 struct spoolss_SetPrinterInfo8 info8;
1299 struct spoolss_SetPrinterInfo9 info9;
1302 info_ctr.level = levels[i];
1303 switch (levels[i]) {
1304 case 0:
1305 ZERO_STRUCT(info0);
1306 info_ctr.info.info0 = &info0;
1307 break;
1308 case 1:
1309 ZERO_STRUCT(info1);
1310 info_ctr.info.info1 = &info1;
1311 break;
1312 case 2:
1313 ZERO_STRUCT(info2);
1314 info_ctr.info.info2 = &info2;
1315 break;
1316 case 3:
1317 ZERO_STRUCT(info3);
1318 info_ctr.info.info3 = &info3;
1319 break;
1320 case 4:
1321 ZERO_STRUCT(info4);
1322 info_ctr.info.info4 = &info4;
1323 break;
1324 case 5:
1325 ZERO_STRUCT(info5);
1326 info_ctr.info.info5 = &info5;
1327 break;
1328 case 6:
1329 ZERO_STRUCT(info6);
1330 info_ctr.info.info6 = &info6;
1331 break;
1332 case 7:
1333 ZERO_STRUCT(info7);
1334 info_ctr.info.info7 = &info7;
1335 break;
1336 case 8:
1337 ZERO_STRUCT(info8);
1338 info_ctr.info.info8 = &info8;
1339 break;
1340 case 9:
1341 ZERO_STRUCT(info9);
1342 info_ctr.info.info9 = &info9;
1343 break;
1346 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1347 info_ctr.level, r.in.command);
1349 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1350 "failed to call SetPrinter");
1352 switch (r.in.command) {
1353 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1354 /* is ignored for all levels other then 0 */
1355 if (info_ctr.level > 0) {
1356 /* ignored then */
1357 break;
1359 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1360 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1361 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1362 if (info_ctr.level > 0) {
1363 /* is invalid for all levels other then 0 */
1364 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1365 "unexpected error code returned");
1366 continue;
1367 } else {
1368 torture_assert_werr_ok(tctx, r.out.result,
1369 "failed to call SetPrinter with non 0 command");
1370 continue;
1372 break;
1374 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1375 /* FIXME: gd needs further investigation */
1376 default:
1377 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1378 "unexpected error code returned");
1379 continue;
1382 switch (info_ctr.level) {
1383 case 1:
1384 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1385 "unexpected error code returned");
1386 break;
1387 case 2:
1388 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1389 "unexpected error code returned");
1390 break;
1391 case 3:
1392 case 4:
1393 case 5:
1394 case 7:
1395 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1396 "unexpected error code returned");
1397 break;
1398 case 9:
1399 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1400 "unexpected error code returned");
1401 break;
1402 default:
1403 torture_assert_werr_ok(tctx, r.out.result,
1404 "failed to call SetPrinter");
1405 break;
1409 if (r.in.command < 5) {
1410 r.in.command++;
1411 goto again;
1414 return true;
1417 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1419 if ((r->level == 2) && (r->info.info2)) {
1420 r->info.info2->secdesc_ptr = 0;
1421 r->info.info2->devmode_ptr = 0;
1425 static bool test_PrinterInfo(struct torture_context *tctx,
1426 struct dcerpc_binding_handle *b,
1427 struct policy_handle *handle)
1429 NTSTATUS status;
1430 struct spoolss_SetPrinter s;
1431 struct spoolss_GetPrinter q;
1432 struct spoolss_GetPrinter q0;
1433 struct spoolss_SetPrinterInfoCtr info_ctr;
1434 union spoolss_PrinterInfo info;
1435 struct spoolss_DevmodeContainer devmode_ctr;
1436 struct sec_desc_buf secdesc_ctr;
1437 uint32_t needed;
1438 bool ret = true;
1439 int i;
1441 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1443 uint32_t status_list[] = {
1444 /* these do not stick
1445 PRINTER_STATUS_PAUSED,
1446 PRINTER_STATUS_ERROR,
1447 PRINTER_STATUS_PENDING_DELETION, */
1448 PRINTER_STATUS_PAPER_JAM,
1449 PRINTER_STATUS_PAPER_OUT,
1450 PRINTER_STATUS_MANUAL_FEED,
1451 PRINTER_STATUS_PAPER_PROBLEM,
1452 PRINTER_STATUS_OFFLINE,
1453 PRINTER_STATUS_IO_ACTIVE,
1454 PRINTER_STATUS_BUSY,
1455 PRINTER_STATUS_PRINTING,
1456 PRINTER_STATUS_OUTPUT_BIN_FULL,
1457 PRINTER_STATUS_NOT_AVAILABLE,
1458 PRINTER_STATUS_WAITING,
1459 PRINTER_STATUS_PROCESSING,
1460 PRINTER_STATUS_INITIALIZING,
1461 PRINTER_STATUS_WARMING_UP,
1462 PRINTER_STATUS_TONER_LOW,
1463 PRINTER_STATUS_NO_TONER,
1464 PRINTER_STATUS_PAGE_PUNT,
1465 PRINTER_STATUS_USER_INTERVENTION,
1466 PRINTER_STATUS_OUT_OF_MEMORY,
1467 PRINTER_STATUS_DOOR_OPEN,
1468 PRINTER_STATUS_SERVER_UNKNOWN,
1469 PRINTER_STATUS_POWER_SAVE,
1470 /* these do not stick
1471 0x02000000,
1472 0x04000000,
1473 0x08000000,
1474 0x10000000,
1475 0x20000000,
1476 0x40000000,
1477 0x80000000 */
1479 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1480 uint32_t attribute_list[] = {
1481 PRINTER_ATTRIBUTE_QUEUED,
1482 /* fails with WERR_INVALID_DATATYPE:
1483 PRINTER_ATTRIBUTE_DIRECT, */
1484 /* does not stick
1485 PRINTER_ATTRIBUTE_DEFAULT, */
1486 PRINTER_ATTRIBUTE_SHARED,
1487 /* does not stick
1488 PRINTER_ATTRIBUTE_NETWORK, */
1489 PRINTER_ATTRIBUTE_HIDDEN,
1490 PRINTER_ATTRIBUTE_LOCAL,
1491 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1492 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1493 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1494 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1495 /* does not stick
1496 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1497 /* fails with WERR_INVALID_DATATYPE:
1498 PRINTER_ATTRIBUTE_RAW_ONLY, */
1499 /* these do not stick
1500 PRINTER_ATTRIBUTE_PUBLISHED,
1501 PRINTER_ATTRIBUTE_FAX,
1502 PRINTER_ATTRIBUTE_TS,
1503 0x00010000,
1504 0x00020000,
1505 0x00040000,
1506 0x00080000,
1507 0x00100000,
1508 0x00200000,
1509 0x00400000,
1510 0x00800000,
1511 0x01000000,
1512 0x02000000,
1513 0x04000000,
1514 0x08000000,
1515 0x10000000,
1516 0x20000000,
1517 0x40000000,
1518 0x80000000 */
1521 ZERO_STRUCT(devmode_ctr);
1522 ZERO_STRUCT(secdesc_ctr);
1524 s.in.handle = handle;
1525 s.in.command = 0;
1526 s.in.info_ctr = &info_ctr;
1527 s.in.devmode_ctr = &devmode_ctr;
1528 s.in.secdesc_ctr = &secdesc_ctr;
1530 q.in.handle = handle;
1531 q.out.info = &info;
1532 q0 = q;
1534 #define TESTGETCALL(call, r) \
1535 r.in.buffer = NULL; \
1536 r.in.offered = 0;\
1537 r.out.needed = &needed; \
1538 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1539 if (!NT_STATUS_IS_OK(status)) { \
1540 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1541 r.in.level, nt_errstr(status), __location__); \
1542 ret = false; \
1543 break; \
1545 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1546 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1547 r.in.buffer = &blob; \
1548 r.in.offered = needed; \
1550 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1551 if (!NT_STATUS_IS_OK(status)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, nt_errstr(status), __location__); \
1554 ret = false; \
1555 break; \
1557 if (!W_ERROR_IS_OK(r.out.result)) { \
1558 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1559 r.in.level, win_errstr(r.out.result), __location__); \
1560 ret = false; \
1561 break; \
1565 #define TESTSETCALL_EXP(call, r, err) \
1566 clear_info2(&info_ctr);\
1567 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1568 if (!NT_STATUS_IS_OK(status)) { \
1569 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1570 r.in.info_ctr->level, nt_errstr(status), __location__); \
1571 ret = false; \
1572 break; \
1574 if (!W_ERROR_IS_OK(err)) { \
1575 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1576 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1577 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1578 ret = false; \
1580 break; \
1582 if (!W_ERROR_IS_OK(r.out.result)) { \
1583 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1584 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1585 ret = false; \
1586 break; \
1589 #define TESTSETCALL(call, r) \
1590 TESTSETCALL_EXP(call, r, WERR_OK)
1592 #define STRING_EQUAL(s1, s2, field) \
1593 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1594 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1595 #field, s2, __location__); \
1596 ret = false; \
1597 break; \
1600 #define MEM_EQUAL(s1, s2, length, field) \
1601 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1602 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1603 #field, (const char *)s2, __location__); \
1604 ret = false; \
1605 break; \
1608 #define INT_EQUAL(i1, i2, field) \
1609 if (i1 != i2) { \
1610 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1611 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1612 ret = false; \
1613 break; \
1616 #define SD_EQUAL(sd1, sd2, field) \
1617 if (!security_descriptor_equal(sd1, sd2)) { \
1618 torture_comment(tctx, "Failed to set %s (%s)\n", \
1619 #field, __location__); \
1620 ret = false; \
1621 break; \
1624 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1625 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626 q.in.level = lvl1; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.level = lvl1; \
1629 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630 info_ctr.info.info ## lvl1->field1 = value;\
1631 TESTSETCALL_EXP(SetPrinter, s, err) \
1632 info_ctr.info.info ## lvl1->field1 = ""; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl1->field1 = value; \
1635 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1636 q.in.level = lvl2; \
1637 TESTGETCALL(GetPrinter, q) \
1638 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1640 } while (0)
1642 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1643 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1644 } while (0);
1646 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1647 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1648 q.in.level = lvl1; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.level = lvl1; \
1651 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1652 info_ctr.info.info ## lvl1->field1 = value; \
1653 TESTSETCALL(SetPrinter, s) \
1654 info_ctr.info.info ## lvl1->field1 = 0; \
1655 TESTGETCALL(GetPrinter, q) \
1656 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1657 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1658 q.in.level = lvl2; \
1659 TESTGETCALL(GetPrinter, q) \
1660 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1661 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1662 } while (0)
1664 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1665 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1666 } while (0)
1668 q0.in.level = 0;
1669 do { TESTGETCALL(GetPrinter, q0) } while (0);
1671 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1672 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1674 /* level 0 printername does not stick */
1675 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1676 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1677 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1680 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1681 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1682 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1685 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1686 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1687 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1691 /* servername can be set but does not stick
1692 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1693 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1697 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1698 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1703 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1704 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1705 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1706 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1707 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1708 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1709 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1710 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1711 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1712 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1714 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1715 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1716 attribute_list[i],
1717 (attribute_list[i] | default_attribute)
1718 ); */
1719 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1720 attribute_list[i],
1721 (attribute_list[i] | default_attribute)
1723 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1724 attribute_list[i],
1725 (attribute_list[i] | default_attribute)
1727 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1728 attribute_list[i],
1729 (attribute_list[i] | default_attribute)
1731 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1732 attribute_list[i],
1733 (attribute_list[i] | default_attribute)
1734 ); */
1735 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1736 attribute_list[i],
1737 (attribute_list[i] | default_attribute)
1739 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1740 attribute_list[i],
1741 (attribute_list[i] | default_attribute)
1743 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1744 attribute_list[i],
1745 (attribute_list[i] | default_attribute)
1747 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1748 attribute_list[i],
1749 (attribute_list[i] | default_attribute)
1750 ); */
1751 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1752 attribute_list[i],
1753 (attribute_list[i] | default_attribute)
1755 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1756 attribute_list[i],
1757 (attribute_list[i] | default_attribute)
1759 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1760 attribute_list[i],
1761 (attribute_list[i] | default_attribute)
1765 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1766 /* level 2 sets do not stick
1767 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1770 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1775 /* priorities need to be between 0 and 99
1776 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1777 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1780 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1781 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1784 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1786 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1787 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1789 /* does not stick
1790 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1791 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1793 /* does not stick
1794 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1795 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1797 /* FIXME: gd also test devmode and secdesc behavior */
1800 /* verify composition of level 1 description field */
1801 const char *description;
1802 const char *tmp;
1804 q0.in.level = 1;
1805 do { TESTGETCALL(GetPrinter, q0) } while (0);
1807 description = talloc_strdup(tctx, q0.out.info->info1.description);
1809 q0.in.level = 2;
1810 do { TESTGETCALL(GetPrinter, q0) } while (0);
1812 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1813 q0.out.info->info2.printername,
1814 q0.out.info->info2.drivername,
1815 q0.out.info->info2.location);
1817 do { STRING_EQUAL(description, tmp, "description")} while (0);
1820 return ret;
1823 static bool test_security_descriptor_equal(struct torture_context *tctx,
1824 const struct security_descriptor *sd1,
1825 const struct security_descriptor *sd2)
1827 if (sd1 == sd2) {
1828 return true;
1831 if (!sd1 || !sd2) {
1832 torture_comment(tctx, "%s\n", __location__);
1833 return false;
1836 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1837 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1839 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1840 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1842 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1843 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1846 return false;
1848 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1849 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1850 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1851 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1852 return false;
1855 return true;
1858 static bool test_sd_set_level(struct torture_context *tctx,
1859 struct dcerpc_binding_handle *b,
1860 struct policy_handle *handle,
1861 uint32_t level,
1862 struct security_descriptor *sd)
1864 struct spoolss_SetPrinterInfoCtr info_ctr;
1865 struct spoolss_DevmodeContainer devmode_ctr;
1866 struct sec_desc_buf secdesc_ctr;
1867 union spoolss_SetPrinterInfo sinfo;
1869 ZERO_STRUCT(devmode_ctr);
1870 ZERO_STRUCT(secdesc_ctr);
1872 switch (level) {
1873 case 2: {
1874 union spoolss_PrinterInfo info;
1875 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1876 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1878 info_ctr.level = 2;
1879 info_ctr.info = sinfo;
1881 break;
1883 case 3: {
1884 struct spoolss_SetPrinterInfo3 info3;
1886 info3.sec_desc_ptr = 0;
1888 info_ctr.level = 3;
1889 info_ctr.info.info3 = &info3;
1891 break;
1893 default:
1894 return false;
1897 secdesc_ctr.sd = sd;
1899 torture_assert(tctx,
1900 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1902 return true;
1905 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1906 struct dcerpc_binding_handle *b,
1907 struct policy_handle *handle)
1909 union spoolss_PrinterInfo info;
1910 struct security_descriptor *sd1, *sd2;
1911 int i;
1913 /* just compare level 2 and level 3 */
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1917 sd1 = info.info2.secdesc;
1919 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1921 sd2 = info.info3.secdesc;
1923 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1924 "SD level 2 != SD level 3");
1927 /* query level 2, set level 2, query level 2 */
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd1 = info.info2.secdesc;
1933 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1935 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1937 sd2 = info.info2.secdesc;
1938 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1939 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1940 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1943 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1944 "SD level 2 != SD level 2 after SD has been set via level 2");
1947 /* query level 2, set level 3, query level 2 */
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd1 = info.info2.secdesc;
1953 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1955 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1957 sd2 = info.info2.secdesc;
1959 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1960 "SD level 2 != SD level 2 after SD has been set via level 3");
1962 /* set modified sd level 3, query level 2 */
1964 for (i=0; i < 93; i++) {
1965 struct security_ace a;
1966 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1967 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1968 a.flags = 0;
1969 a.size = 0; /* autogenerated */
1970 a.access_mask = 0;
1971 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1972 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1975 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1977 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1978 sd2 = info.info2.secdesc;
1980 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1981 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1982 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1985 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1986 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1989 return true;
1993 * wrapper call that saves original sd, runs tests, and restores sd
1996 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1997 struct dcerpc_binding_handle *b,
1998 struct policy_handle *handle)
2000 union spoolss_PrinterInfo info;
2001 struct security_descriptor *sd;
2002 bool ret = true;
2004 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2006 /* save original sd */
2008 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2009 "failed to get initial security descriptor");
2011 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2013 /* run tests */
2015 ret = test_PrinterInfo_SDs(tctx, b, handle);
2017 /* restore original sd */
2019 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2020 "failed to restore initial security descriptor");
2022 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2023 ret ? "succeeded" : "failed");
2026 return ret;
2029 static bool test_devmode_set_level(struct torture_context *tctx,
2030 struct dcerpc_binding_handle *b,
2031 struct policy_handle *handle,
2032 uint32_t level,
2033 struct spoolss_DeviceMode *devmode)
2035 struct spoolss_SetPrinterInfoCtr info_ctr;
2036 struct spoolss_DevmodeContainer devmode_ctr;
2037 struct sec_desc_buf secdesc_ctr;
2038 union spoolss_SetPrinterInfo sinfo;
2040 ZERO_STRUCT(devmode_ctr);
2041 ZERO_STRUCT(secdesc_ctr);
2043 switch (level) {
2044 case 2: {
2045 union spoolss_PrinterInfo info;
2046 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2047 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2049 info_ctr.level = 2;
2050 info_ctr.info = sinfo;
2052 break;
2054 case 8: {
2055 struct spoolss_SetPrinterInfo8 info8;
2057 info8.devmode_ptr = 0;
2059 info_ctr.level = 8;
2060 info_ctr.info.info8 = &info8;
2062 break;
2064 default:
2065 return false;
2068 devmode_ctr.devmode = devmode;
2070 torture_assert(tctx,
2071 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2073 return true;
2077 static bool test_devicemode_equal(struct torture_context *tctx,
2078 const struct spoolss_DeviceMode *d1,
2079 const struct spoolss_DeviceMode *d2)
2081 if (d1 == d2) {
2082 return true;
2085 if (!d1 || !d2) {
2086 torture_comment(tctx, "%s\n", __location__);
2087 return false;
2089 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2090 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2091 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2092 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2093 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2094 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2095 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2096 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2097 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2098 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2099 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2100 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2101 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2102 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2103 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2104 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2105 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2106 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2107 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2108 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2109 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2110 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2111 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2112 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2113 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2114 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2115 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2116 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2117 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2118 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2119 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2121 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2122 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2123 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2125 return true;
2128 static bool test_devicemode_full(struct torture_context *tctx,
2129 struct dcerpc_binding_handle *b,
2130 struct policy_handle *handle)
2132 struct spoolss_SetPrinter s;
2133 struct spoolss_GetPrinter q;
2134 struct spoolss_GetPrinter q0;
2135 struct spoolss_SetPrinterInfoCtr info_ctr;
2136 struct spoolss_SetPrinterInfo8 info8;
2137 union spoolss_PrinterInfo info;
2138 struct spoolss_DevmodeContainer devmode_ctr;
2139 struct sec_desc_buf secdesc_ctr;
2140 uint32_t needed;
2141 bool ret = true;
2142 NTSTATUS status;
2144 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2145 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2146 q.in.level = lvl1; \
2147 TESTGETCALL(GetPrinter, q) \
2148 info_ctr.level = lvl1; \
2149 if (lvl1 == 2) {\
2150 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2151 } else if (lvl1 == 8) {\
2152 info_ctr.info.info ## lvl1 = &info8; \
2154 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2155 devmode_ctr.devmode->field1 = value; \
2156 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2157 if (W_ERROR_IS_OK(expected_result)) { \
2158 TESTGETCALL(GetPrinter, q) \
2159 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2160 q.in.level = lvl2; \
2161 TESTGETCALL(GetPrinter, q) \
2162 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2164 } while (0)
2166 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2167 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2168 } while (0)
2170 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2171 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2172 } while (0)
2174 ZERO_STRUCT(devmode_ctr);
2175 ZERO_STRUCT(secdesc_ctr);
2176 ZERO_STRUCT(info8);
2178 s.in.handle = handle;
2179 s.in.command = 0;
2180 s.in.info_ctr = &info_ctr;
2181 s.in.devmode_ctr = &devmode_ctr;
2182 s.in.secdesc_ctr = &secdesc_ctr;
2184 q.in.handle = handle;
2185 q.out.info = &info;
2186 q0 = q;
2188 #if 0
2189 const char *devicename;/* [charset(UTF16)] */
2190 enum spoolss_DeviceModeSpecVersion specversion;
2191 uint16_t driverversion;
2192 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2193 uint32_t fields;
2194 #endif
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2199 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2201 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2202 torture_assert(tctx,
2203 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2204 "failed to set devmode");
2206 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2207 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2209 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2210 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2211 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2212 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2213 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2214 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2215 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2216 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2217 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2218 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2219 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2220 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2221 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2222 #if 0
2223 const char *formname;/* [charset(UTF16)] */
2224 #endif
2225 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2226 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2227 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2228 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2229 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2230 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2231 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2232 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2233 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2234 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2237 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2238 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2240 return ret;
2243 static bool call_OpenPrinterEx(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 const char *name,
2246 struct spoolss_DeviceMode *devmode,
2247 struct policy_handle *handle);
2249 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2250 struct dcerpc_pipe *p,
2251 struct policy_handle *handle,
2252 const char *name)
2254 union spoolss_PrinterInfo info;
2255 struct spoolss_DeviceMode *devmode;
2256 struct spoolss_DeviceMode *devmode2;
2257 struct policy_handle handle_devmode;
2258 struct dcerpc_binding_handle *b = p->binding_handle;
2260 /* simply compare level8 and level2 devmode */
2262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264 devmode = info.info8.devmode;
2266 if (devmode && devmode->size == 0) {
2267 torture_fail(tctx,
2268 "devmode of zero size!");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2273 devmode2 = info.info2.devmode;
2275 if (devmode2 && devmode2->size == 0) {
2276 torture_fail(tctx,
2277 "devmode of zero size!");
2280 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2281 "DM level 8 != DM level 2");
2284 /* set devicemode level 8 and see if it persists */
2286 devmode->copies = 93;
2287 devmode->formname = talloc_strdup(tctx, "Legal");
2289 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2291 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2293 devmode2 = info.info8.devmode;
2295 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2296 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2298 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2300 devmode2 = info.info2.devmode;
2302 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2303 "modified DM level 8 != DM level 2");
2306 /* set devicemode level 2 and see if it persists */
2308 devmode->copies = 39;
2309 devmode->formname = talloc_strdup(tctx, "Executive");
2311 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2313 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2315 devmode2 = info.info8.devmode;
2317 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2318 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2320 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2322 devmode2 = info.info2.devmode;
2324 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2325 "modified DM level 8 != DM level 2");
2328 /* check every single bit in public part of devicemode */
2330 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2331 "failed to set every single devicemode component");
2334 /* change formname upon open and see if it persists in getprinter calls */
2336 devmode->formname = talloc_strdup(tctx, "A4");
2337 devmode->copies = 42;
2339 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2340 "failed to open printer handle");
2342 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2344 devmode2 = info.info8.devmode;
2346 if (strequal(devmode->devicename, devmode2->devicename)) {
2347 torture_warning(tctx, "devicenames are the same\n");
2348 } else {
2349 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2350 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2353 if (strequal(devmode->formname, devmode2->formname)) {
2354 torture_warning(tctx, "formname are the same\n");
2355 } else {
2356 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2357 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2360 if (devmode->copies == devmode2->copies) {
2361 torture_warning(tctx, "copies are the same\n");
2362 } else {
2363 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2364 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2367 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2369 devmode2 = info.info2.devmode;
2371 if (strequal(devmode->devicename, devmode2->devicename)) {
2372 torture_warning(tctx, "devicenames are the same\n");
2373 } else {
2374 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2375 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2378 if (strequal(devmode->formname, devmode2->formname)) {
2379 torture_warning(tctx, "formname is the same\n");
2380 } else {
2381 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2382 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2385 if (devmode->copies == devmode2->copies) {
2386 torture_warning(tctx, "copies are the same\n");
2387 } else {
2388 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2389 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2392 test_ClosePrinter(tctx, b, &handle_devmode);
2394 return true;
2398 * wrapper call that saves original devmode, runs tests, and restores devmode
2401 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2402 struct dcerpc_pipe *p,
2403 struct policy_handle *handle,
2404 const char *name,
2405 struct spoolss_DeviceMode *addprinter_devmode)
2407 union spoolss_PrinterInfo info;
2408 struct spoolss_DeviceMode *devmode;
2409 bool ret = true;
2410 struct dcerpc_binding_handle *b = p->binding_handle;
2412 torture_comment(tctx, "Testing Printer Devicemodes\n");
2414 /* save original devmode */
2416 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2417 "failed to get initial global devicemode");
2419 devmode = info.info8.devmode;
2421 if (devmode && devmode->size == 0) {
2422 torture_fail(tctx,
2423 "devmode of zero size!");
2426 if (addprinter_devmode) {
2427 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2428 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2432 /* run tests */
2434 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2436 /* restore original devmode */
2438 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2439 "failed to restore initial global device mode");
2441 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2442 ret ? "succeeded" : "failed");
2445 return ret;
2448 bool test_ClosePrinter(struct torture_context *tctx,
2449 struct dcerpc_binding_handle *b,
2450 struct policy_handle *handle)
2452 NTSTATUS status;
2453 struct spoolss_ClosePrinter r;
2455 r.in.handle = handle;
2456 r.out.handle = handle;
2458 torture_comment(tctx, "Testing ClosePrinter\n");
2460 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2464 return true;
2467 static bool test_GetForm_args(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 const char *form_name,
2471 uint32_t level,
2472 union spoolss_FormInfo *info_p)
2474 NTSTATUS status;
2475 struct spoolss_GetForm r;
2476 uint32_t needed;
2478 r.in.handle = handle;
2479 r.in.form_name = form_name;
2480 r.in.level = level;
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2485 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2487 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2488 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2492 r.in.buffer = &blob;
2493 r.in.offered = needed;
2494 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 torture_assert(tctx, r.out.info, "No form info returned");
2502 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2504 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2506 if (info_p) {
2507 *info_p = *r.out.info;
2510 return true;
2513 static bool test_GetForm(struct torture_context *tctx,
2514 struct dcerpc_binding_handle *b,
2515 struct policy_handle *handle,
2516 const char *form_name,
2517 uint32_t level)
2519 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2522 static bool test_EnumForms(struct torture_context *tctx,
2523 struct dcerpc_binding_handle *b,
2524 struct policy_handle *handle,
2525 bool print_server,
2526 uint32_t level,
2527 uint32_t *count_p,
2528 union spoolss_FormInfo **info_p)
2530 struct spoolss_EnumForms r;
2531 uint32_t needed;
2532 uint32_t count;
2533 union spoolss_FormInfo *info;
2535 r.in.handle = handle;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2540 r.out.count = &count;
2541 r.out.info = &info;
2543 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2545 torture_assert_ntstatus_ok(tctx,
2546 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2547 "EnumForms failed");
2549 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2550 torture_skip(tctx, "EnumForms level 2 not supported");
2553 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2554 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2557 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2558 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2559 r.in.buffer = &blob;
2560 r.in.offered = needed;
2562 torture_assert_ntstatus_ok(tctx,
2563 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2564 "EnumForms failed");
2566 torture_assert(tctx, info, "No forms returned");
2569 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2571 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2573 if (info_p) {
2574 *info_p = info;
2576 if (count_p) {
2577 *count_p = count;
2580 return true;
2583 static bool test_EnumForms_all(struct torture_context *tctx,
2584 struct dcerpc_binding_handle *b,
2585 struct policy_handle *handle,
2586 bool print_server)
2588 uint32_t levels[] = { 1, 2 };
2589 int i, j;
2591 for (i=0; i<ARRAY_SIZE(levels); i++) {
2593 uint32_t count = 0;
2594 union spoolss_FormInfo *info = NULL;
2596 torture_assert(tctx,
2597 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2598 "failed to enum forms");
2600 for (j = 0; j < count; j++) {
2601 if (!print_server) {
2602 torture_assert(tctx,
2603 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2604 "failed to get form");
2609 return true;
2612 static bool test_EnumForms_find_one(struct torture_context *tctx,
2613 struct dcerpc_binding_handle *b,
2614 struct policy_handle *handle,
2615 bool print_server,
2616 const char *form_name)
2618 union spoolss_FormInfo *info;
2619 uint32_t count;
2620 bool found = false;
2621 int i;
2623 torture_assert(tctx,
2624 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2625 "failed to enumerate forms");
2627 for (i=0; i<count; i++) {
2628 if (strequal(form_name, info[i].info1.form_name)) {
2629 found = true;
2630 break;
2634 return found;
2637 static bool test_DeleteForm(struct torture_context *tctx,
2638 struct dcerpc_binding_handle *b,
2639 struct policy_handle *handle,
2640 const char *form_name,
2641 WERROR expected_result)
2643 struct spoolss_DeleteForm r;
2645 r.in.handle = handle;
2646 r.in.form_name = form_name;
2648 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2650 torture_assert_ntstatus_ok(tctx,
2651 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2652 "DeleteForm failed");
2653 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2654 "DeleteForm gave unexpected result");
2655 if (W_ERROR_IS_OK(r.out.result)) {
2656 torture_assert_ntstatus_ok(tctx,
2657 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2658 "2nd DeleteForm failed");
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2660 "2nd DeleteForm failed");
2663 return true;
2666 static bool test_AddForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 uint32_t level,
2670 union spoolss_AddFormInfo *info,
2671 WERROR expected_result)
2673 struct spoolss_AddForm r;
2675 if (level != 1) {
2676 torture_skip(tctx, "only level 1 supported");
2679 r.in.handle = handle;
2680 r.in.level = level;
2681 r.in.info = *info;
2683 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2684 r.in.info.info1->form_name, r.in.level,
2685 r.in.info.info1->flags);
2687 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2688 "AddForm failed");
2689 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2690 "AddForm gave unexpected result");
2692 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2693 "2nd AddForm failed");
2694 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2695 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2696 "2nd AddForm gave unexpected result");
2697 } else {
2698 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2699 "2nd AddForm gave unexpected result");
2702 return true;
2705 static bool test_SetForm(struct torture_context *tctx,
2706 struct dcerpc_binding_handle *b,
2707 struct policy_handle *handle,
2708 const char *form_name,
2709 uint32_t level,
2710 union spoolss_AddFormInfo *info)
2712 struct spoolss_SetForm r;
2714 r.in.handle = handle;
2715 r.in.form_name = form_name;
2716 r.in.level = level;
2717 r.in.info = *info;
2719 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2720 form_name, r.in.level);
2722 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2723 "SetForm failed");
2725 torture_assert_werr_ok(tctx, r.out.result,
2726 "SetForm failed");
2728 return true;
2731 static bool test_GetForm_winreg(struct torture_context *tctx,
2732 struct dcerpc_binding_handle *b,
2733 struct policy_handle *handle,
2734 const char *key_name,
2735 const char *form_name,
2736 enum winreg_Type *w_type,
2737 uint32_t *w_size,
2738 uint32_t *w_length,
2739 uint8_t **w_data);
2741 static bool test_Forms_args(struct torture_context *tctx,
2742 struct dcerpc_binding_handle *b,
2743 struct policy_handle *handle,
2744 bool print_server,
2745 const char *printer_name,
2746 struct dcerpc_binding_handle *winreg_handle,
2747 struct policy_handle *hive_handle,
2748 const char *form_name,
2749 struct spoolss_AddFormInfo1 *info1,
2750 WERROR expected_add_result,
2751 WERROR expected_delete_result)
2753 union spoolss_FormInfo info;
2754 union spoolss_AddFormInfo add_info;
2756 enum winreg_Type w_type;
2757 uint32_t w_size;
2758 uint32_t w_length;
2759 uint8_t *w_data;
2761 add_info.info1 = info1;
2763 torture_assert(tctx,
2764 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2765 "failed to add form");
2767 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2769 struct spoolss_FormInfo1 i1;
2771 torture_assert(tctx,
2772 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2773 "failed to get form via winreg");
2775 i1.size.width = IVAL(w_data, 0);
2776 i1.size.height = IVAL(w_data, 4);
2777 i1.area.left = IVAL(w_data, 8);
2778 i1.area.top = IVAL(w_data, 12);
2779 i1.area.right = IVAL(w_data, 16);
2780 i1.area.bottom = IVAL(w_data, 20);
2781 /* skip index here */
2782 i1.flags = IVAL(w_data, 28);
2784 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2785 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2786 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2787 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2788 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2789 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2790 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2791 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2792 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2793 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2796 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2797 torture_assert(tctx,
2798 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2799 "failed to get added form");
2801 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2802 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2803 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2804 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2805 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2806 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2807 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2809 if (winreg_handle && hive_handle) {
2811 struct spoolss_FormInfo1 i1;
2813 i1.size.width = IVAL(w_data, 0);
2814 i1.size.height = IVAL(w_data, 4);
2815 i1.area.left = IVAL(w_data, 8);
2816 i1.area.top = IVAL(w_data, 12);
2817 i1.area.right = IVAL(w_data, 16);
2818 i1.area.bottom = IVAL(w_data, 20);
2819 /* skip index here */
2820 i1.flags = IVAL(w_data, 28);
2822 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2823 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2824 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2825 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2826 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2827 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2828 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2831 add_info.info1->size.width = 1234;
2833 torture_assert(tctx,
2834 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2835 "failed to set form");
2836 torture_assert(tctx,
2837 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2838 "failed to get setted form");
2840 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2843 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2844 torture_assert(tctx,
2845 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2846 "Newly added form not found in enum call");
2849 torture_assert(tctx,
2850 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2851 "failed to delete form");
2853 return true;
2856 static bool test_Forms(struct torture_context *tctx,
2857 struct dcerpc_binding_handle *b,
2858 struct policy_handle *handle,
2859 bool print_server,
2860 const char *printer_name,
2861 struct dcerpc_binding_handle *winreg_handle,
2862 struct policy_handle *hive_handle)
2864 const struct spoolss_FormSize size = {
2865 .width = 50,
2866 .height = 25
2868 const struct spoolss_FormArea area = {
2869 .left = 5,
2870 .top = 10,
2871 .right = 45,
2872 .bottom = 15
2874 int i;
2876 struct {
2877 struct spoolss_AddFormInfo1 info1;
2878 WERROR expected_add_result;
2879 WERROR expected_delete_result;
2880 } forms[] = {
2882 .info1 = {
2883 .flags = SPOOLSS_FORM_USER,
2884 .form_name = "testform_user",
2885 .size = size,
2886 .area = area,
2888 .expected_add_result = WERR_OK,
2889 .expected_delete_result = WERR_OK
2892 weird, we can add a builtin form but we can never remove it
2893 again - gd
2896 .info1 = {
2897 .flags = SPOOLSS_FORM_BUILTIN,
2898 .form_name = "testform_builtin",
2899 .size = size,
2900 .area = area,
2902 .expected_add_result = WERR_OK,
2903 .expected_delete_result = WERR_INVALID_PARAM,
2907 .info1 = {
2908 .flags = SPOOLSS_FORM_PRINTER,
2909 .form_name = "testform_printer",
2910 .size = size,
2911 .area = area,
2913 .expected_add_result = WERR_OK,
2914 .expected_delete_result = WERR_OK
2917 .info1 = {
2918 .flags = SPOOLSS_FORM_USER,
2919 .form_name = "Letter",
2920 .size = size,
2921 .area = area,
2923 .expected_add_result = WERR_FILE_EXISTS,
2924 .expected_delete_result = WERR_INVALID_PARAM
2927 .info1 = {
2928 .flags = SPOOLSS_FORM_BUILTIN,
2929 .form_name = "Letter",
2930 .size = size,
2931 .area = area,
2933 .expected_add_result = WERR_FILE_EXISTS,
2934 .expected_delete_result = WERR_INVALID_PARAM
2937 .info1 = {
2938 .flags = SPOOLSS_FORM_PRINTER,
2939 .form_name = "Letter",
2940 .size = size,
2941 .area = area,
2943 .expected_add_result = WERR_FILE_EXISTS,
2944 .expected_delete_result = WERR_INVALID_PARAM
2947 .info1 = {
2948 .flags = 12345,
2949 .form_name = "invalid_flags",
2950 .size = size,
2951 .area = area,
2953 .expected_add_result = WERR_INVALID_PARAM,
2954 .expected_delete_result = WERR_INVALID_FORM_NAME
2959 for (i=0; i < ARRAY_SIZE(forms); i++) {
2960 torture_assert(tctx,
2961 test_Forms_args(tctx, b, handle, print_server, printer_name,
2962 winreg_handle, hive_handle,
2963 forms[i].info1.form_name,
2964 &forms[i].info1,
2965 forms[i].expected_add_result,
2966 forms[i].expected_delete_result),
2967 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2970 return true;
2973 static bool test_EnumPorts_old(struct torture_context *tctx,
2974 void *private_data)
2976 struct test_spoolss_context *ctx =
2977 talloc_get_type_abort(private_data, struct test_spoolss_context);
2979 NTSTATUS status;
2980 struct spoolss_EnumPorts r;
2981 uint32_t needed;
2982 uint32_t count;
2983 union spoolss_PortInfo *info;
2984 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2985 struct dcerpc_binding_handle *b = p->binding_handle;
2987 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2988 dcerpc_server_name(p));
2989 r.in.level = 2;
2990 r.in.buffer = NULL;
2991 r.in.offered = 0;
2992 r.out.needed = &needed;
2993 r.out.count = &count;
2994 r.out.info = &info;
2996 torture_comment(tctx, "Testing EnumPorts\n");
2998 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3000 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3002 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3003 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3004 r.in.buffer = &blob;
3005 r.in.offered = needed;
3007 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3008 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3009 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3011 torture_assert(tctx, info, "No ports returned");
3014 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3016 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3018 return true;
3021 static bool test_AddPort(struct torture_context *tctx,
3022 void *private_data)
3024 struct test_spoolss_context *ctx =
3025 talloc_get_type_abort(private_data, struct test_spoolss_context);
3027 NTSTATUS status;
3028 struct spoolss_AddPort r;
3029 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3030 struct dcerpc_binding_handle *b = p->binding_handle;
3032 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3033 dcerpc_server_name(p));
3034 r.in.unknown = 0;
3035 r.in.monitor_name = "foo";
3037 torture_comment(tctx, "Testing AddPort\n");
3039 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3041 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3043 /* win2k3 returns WERR_NOT_SUPPORTED */
3045 #if 0
3047 if (!W_ERROR_IS_OK(r.out.result)) {
3048 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3049 return false;
3052 #endif
3054 return true;
3057 static bool test_GetJob_args(struct torture_context *tctx,
3058 struct dcerpc_binding_handle *b,
3059 struct policy_handle *handle,
3060 uint32_t job_id,
3061 uint32_t level,
3062 union spoolss_JobInfo *info_p)
3064 NTSTATUS status;
3065 struct spoolss_GetJob r;
3066 union spoolss_JobInfo info;
3067 uint32_t needed;
3069 r.in.handle = handle;
3070 r.in.job_id = job_id;
3071 r.in.level = level;
3072 r.in.buffer = NULL;
3073 r.in.offered = 0;
3074 r.out.needed = &needed;
3075 r.out.info = &info;
3077 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3079 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3080 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3081 if (level == 0) {
3082 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3085 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3086 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3087 r.in.buffer = &blob;
3088 r.in.offered = needed;
3090 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3091 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3094 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3095 torture_assert(tctx, r.out.info, "No job info returned");
3097 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3099 if (info_p) {
3100 *info_p = *r.out.info;
3103 return true;
3106 static bool test_GetJob(struct torture_context *tctx,
3107 struct dcerpc_binding_handle *b,
3108 struct policy_handle *handle,
3109 uint32_t job_id)
3111 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3112 uint32_t i;
3114 for (i=0; i < ARRAY_SIZE(levels); i++) {
3115 torture_assert(tctx,
3116 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3117 "GetJob failed");
3120 return true;
3123 static bool test_SetJob(struct torture_context *tctx,
3124 struct dcerpc_binding_handle *b,
3125 struct policy_handle *handle,
3126 uint32_t job_id,
3127 struct spoolss_JobInfoContainer *ctr,
3128 enum spoolss_JobControl command)
3130 NTSTATUS status;
3131 struct spoolss_SetJob r;
3133 r.in.handle = handle;
3134 r.in.job_id = job_id;
3135 r.in.ctr = ctr;
3136 r.in.command = command;
3138 switch (command) {
3139 case SPOOLSS_JOB_CONTROL_PAUSE:
3140 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3141 break;
3142 case SPOOLSS_JOB_CONTROL_RESUME:
3143 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3144 break;
3145 case SPOOLSS_JOB_CONTROL_CANCEL:
3146 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3147 break;
3148 case SPOOLSS_JOB_CONTROL_RESTART:
3149 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3150 break;
3151 case SPOOLSS_JOB_CONTROL_DELETE:
3152 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3153 break;
3154 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3155 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3156 break;
3157 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3158 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3159 break;
3160 case SPOOLSS_JOB_CONTROL_RETAIN:
3161 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3162 break;
3163 case SPOOLSS_JOB_CONTROL_RELEASE:
3164 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3165 break;
3166 default:
3167 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3168 break;
3171 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3172 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3173 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3175 return true;
3178 static bool test_AddJob(struct torture_context *tctx,
3179 struct dcerpc_binding_handle *b,
3180 struct policy_handle *handle)
3182 NTSTATUS status;
3183 struct spoolss_AddJob r;
3184 uint32_t needed;
3186 r.in.level = 0;
3187 r.in.handle = handle;
3188 r.in.offered = 0;
3189 r.out.needed = &needed;
3190 r.in.buffer = r.out.buffer = NULL;
3192 torture_comment(tctx, "Testing AddJob\n");
3194 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3195 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3197 r.in.level = 1;
3199 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3200 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3202 return true;
3206 static bool test_EnumJobs_args(struct torture_context *tctx,
3207 struct dcerpc_binding_handle *b,
3208 struct policy_handle *handle,
3209 uint32_t level,
3210 uint32_t *count_p,
3211 union spoolss_JobInfo **info_p)
3213 NTSTATUS status;
3214 struct spoolss_EnumJobs r;
3215 uint32_t needed;
3216 uint32_t count;
3217 union spoolss_JobInfo *info;
3219 r.in.handle = handle;
3220 r.in.firstjob = 0;
3221 r.in.numjobs = 0xffffffff;
3222 r.in.level = level;
3223 r.in.buffer = NULL;
3224 r.in.offered = 0;
3225 r.out.needed = &needed;
3226 r.out.count = &count;
3227 r.out.info = &info;
3229 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3231 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3233 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3235 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3236 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3237 r.in.buffer = &blob;
3238 r.in.offered = needed;
3240 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3242 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3243 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3244 torture_assert(tctx, info, "No jobs returned");
3246 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3248 } else {
3249 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3252 if (count_p) {
3253 *count_p = count;
3255 if (info_p) {
3256 *info_p = info;
3259 return true;
3262 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3263 struct dcerpc_binding_handle *b,
3264 struct policy_handle *handle,
3265 const char *document_name,
3266 uint32_t *job_id)
3268 NTSTATUS status;
3269 struct spoolss_StartDocPrinter s;
3270 struct spoolss_DocumentInfo1 info1;
3271 struct spoolss_StartPagePrinter sp;
3272 struct spoolss_WritePrinter w;
3273 struct spoolss_EndPagePrinter ep;
3274 struct spoolss_EndDocPrinter e;
3275 int i;
3276 uint32_t num_written;
3278 torture_comment(tctx, "Testing StartDocPrinter\n");
3280 s.in.handle = handle;
3281 s.in.level = 1;
3282 s.in.info.info1 = &info1;
3283 s.out.job_id = job_id;
3284 info1.document_name = document_name;
3285 info1.output_file = NULL;
3286 info1.datatype = "RAW";
3288 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3289 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3290 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3292 for (i=1; i < 4; i++) {
3293 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3295 sp.in.handle = handle;
3297 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3298 torture_assert_ntstatus_ok(tctx, status,
3299 "dcerpc_spoolss_StartPagePrinter failed");
3300 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3302 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3304 w.in.handle = handle;
3305 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3306 w.out.num_written = &num_written;
3308 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3309 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3310 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3312 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3314 ep.in.handle = handle;
3316 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3317 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3318 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3321 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3323 e.in.handle = handle;
3325 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3326 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3327 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3329 return true;
3332 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3333 struct dcerpc_binding_handle *b,
3334 struct policy_handle *handle,
3335 uint32_t num_jobs,
3336 uint32_t *job_ids)
3338 uint32_t count;
3339 union spoolss_JobInfo *info = NULL;
3340 int i;
3342 torture_assert(tctx,
3343 test_AddJob(tctx, b, handle),
3344 "AddJob failed");
3346 torture_assert(tctx,
3347 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3348 "EnumJobs level 1 failed");
3350 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3352 for (i=0; i < num_jobs; i++) {
3353 union spoolss_JobInfo ginfo;
3354 const char *document_name;
3355 const char *new_document_name = "any_other_docname";
3356 struct spoolss_JobInfoContainer ctr;
3357 struct spoolss_SetJobInfo1 info1;
3359 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3361 torture_assert(tctx,
3362 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3363 "failed to call test_GetJob");
3365 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3367 document_name = ginfo.info1.document_name;
3369 info1.job_id = ginfo.info1.job_id;
3370 info1.printer_name = ginfo.info1.printer_name;
3371 info1.server_name = ginfo.info1.server_name;
3372 info1.user_name = ginfo.info1.user_name;
3373 info1.document_name = new_document_name;
3374 info1.data_type = ginfo.info1.data_type;
3375 info1.text_status = ginfo.info1.text_status;
3376 info1.status = ginfo.info1.status;
3377 info1.priority = ginfo.info1.priority;
3378 info1.position = ginfo.info1.position;
3379 info1.total_pages = ginfo.info1.total_pages;
3380 info1.pages_printed = ginfo.info1.pages_printed;
3381 info1.submitted = ginfo.info1.submitted;
3383 ctr.level = 1;
3384 ctr.info.info1 = &info1;
3386 torture_assert(tctx,
3387 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3388 "failed to call test_SetJob level 1");
3390 torture_assert(tctx,
3391 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3392 "failed to call test_GetJob");
3394 if (strequal(ginfo.info1.document_name, document_name)) {
3395 torture_warning(tctx,
3396 "document_name did *NOT* change from '%s' to '%s'\n",
3397 document_name, new_document_name);
3401 for (i=0; i < num_jobs; i++) {
3402 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3403 torture_warning(tctx, "failed to pause printjob\n");
3405 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3406 torture_warning(tctx, "failed to resume printjob\n");
3410 return true;
3413 static bool test_DoPrintTest(struct torture_context *tctx,
3414 struct dcerpc_binding_handle *b,
3415 struct policy_handle *handle)
3417 bool ret = true;
3418 uint32_t num_jobs = 8;
3419 uint32_t *job_ids;
3420 int i;
3422 torture_comment(tctx, "Testing real print operations\n");
3424 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3426 for (i=0; i < num_jobs; i++) {
3427 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3430 for (i=0; i < num_jobs; i++) {
3431 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3434 if (ret == true) {
3435 torture_comment(tctx, "real print operations test succeeded\n\n");
3438 return ret;
3441 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3442 struct dcerpc_binding_handle *b,
3443 struct policy_handle *handle)
3445 bool ret = true;
3446 uint32_t num_jobs = 8;
3447 uint32_t *job_ids;
3448 int i;
3449 torture_comment(tctx, "Testing real print operations (extended)\n");
3451 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3453 for (i=0; i < num_jobs; i++) {
3454 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3457 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3459 for (i=0; i < num_jobs; i++) {
3460 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3463 if (ret == true) {
3464 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3467 return ret;
3470 static bool test_PausePrinter(struct torture_context *tctx,
3471 struct dcerpc_binding_handle *b,
3472 struct policy_handle *handle)
3474 NTSTATUS status;
3475 struct spoolss_SetPrinter r;
3476 struct spoolss_SetPrinterInfoCtr info_ctr;
3477 struct spoolss_DevmodeContainer devmode_ctr;
3478 struct sec_desc_buf secdesc_ctr;
3480 info_ctr.level = 0;
3481 info_ctr.info.info0 = NULL;
3483 ZERO_STRUCT(devmode_ctr);
3484 ZERO_STRUCT(secdesc_ctr);
3486 r.in.handle = handle;
3487 r.in.info_ctr = &info_ctr;
3488 r.in.devmode_ctr = &devmode_ctr;
3489 r.in.secdesc_ctr = &secdesc_ctr;
3490 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3492 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3494 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3496 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3498 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3500 return true;
3503 static bool test_ResumePrinter(struct torture_context *tctx,
3504 struct dcerpc_binding_handle *b,
3505 struct policy_handle *handle)
3507 NTSTATUS status;
3508 struct spoolss_SetPrinter r;
3509 struct spoolss_SetPrinterInfoCtr info_ctr;
3510 struct spoolss_DevmodeContainer devmode_ctr;
3511 struct sec_desc_buf secdesc_ctr;
3513 info_ctr.level = 0;
3514 info_ctr.info.info0 = NULL;
3516 ZERO_STRUCT(devmode_ctr);
3517 ZERO_STRUCT(secdesc_ctr);
3519 r.in.handle = handle;
3520 r.in.info_ctr = &info_ctr;
3521 r.in.devmode_ctr = &devmode_ctr;
3522 r.in.secdesc_ctr = &secdesc_ctr;
3523 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3525 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3527 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3529 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3531 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3533 return true;
3536 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3537 struct dcerpc_binding_handle *b,
3538 struct policy_handle *handle,
3539 const char *value_name,
3540 enum winreg_Type *expected_type,
3541 enum winreg_Type *type_p,
3542 uint8_t **data_p,
3543 uint32_t *needed_p)
3545 NTSTATUS status;
3546 struct spoolss_GetPrinterData r;
3547 uint32_t needed;
3548 enum winreg_Type type;
3549 union spoolss_PrinterData data;
3551 r.in.handle = handle;
3552 r.in.value_name = value_name;
3553 r.in.offered = 0;
3554 r.out.needed = &needed;
3555 r.out.type = &type;
3556 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3558 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3560 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3561 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3563 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3564 if (expected_type) {
3565 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3567 r.in.offered = needed;
3568 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3569 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3570 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3573 torture_assert_werr_ok(tctx, r.out.result,
3574 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3576 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3578 if (type_p) {
3579 *type_p = type;
3582 if (data_p) {
3583 *data_p = r.out.data;
3586 if (needed_p) {
3587 *needed_p = needed;
3590 return true;
3593 static bool test_GetPrinterData(struct torture_context *tctx,
3594 struct dcerpc_binding_handle *b,
3595 struct policy_handle *handle,
3596 const char *value_name,
3597 enum winreg_Type *type_p,
3598 uint8_t **data_p,
3599 uint32_t *needed_p)
3601 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3602 NULL, type_p, data_p, needed_p);
3605 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3606 struct dcerpc_pipe *p,
3607 struct policy_handle *handle,
3608 const char *key_name,
3609 const char *value_name,
3610 enum winreg_Type *expected_type,
3611 enum winreg_Type *type_p,
3612 uint8_t **data_p,
3613 uint32_t *needed_p)
3615 NTSTATUS status;
3616 struct spoolss_GetPrinterDataEx r;
3617 enum winreg_Type type;
3618 uint32_t needed;
3619 union spoolss_PrinterData data;
3620 struct dcerpc_binding_handle *b = p->binding_handle;
3622 r.in.handle = handle;
3623 r.in.key_name = key_name;
3624 r.in.value_name = value_name;
3625 r.in.offered = 0;
3626 r.out.type = &type;
3627 r.out.needed = &needed;
3628 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3630 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3631 r.in.key_name, r.in.value_name);
3633 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3634 if (!NT_STATUS_IS_OK(status)) {
3635 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3636 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3638 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3641 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3642 if (expected_type) {
3643 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3645 r.in.offered = needed;
3646 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3647 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3648 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3651 torture_assert_werr_ok(tctx, r.out.result,
3652 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3654 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3656 if (type_p) {
3657 *type_p = type;
3660 if (data_p) {
3661 *data_p = r.out.data;
3664 if (needed_p) {
3665 *needed_p = needed;
3668 return true;
3671 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3672 struct dcerpc_pipe *p,
3673 struct policy_handle *handle,
3674 const char *key_name,
3675 const char *value_name,
3676 enum winreg_Type *type_p,
3677 uint8_t **data_p,
3678 uint32_t *needed_p)
3680 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3681 NULL, type_p, data_p, needed_p);
3684 static bool test_get_environment(struct torture_context *tctx,
3685 struct dcerpc_binding_handle *b,
3686 struct policy_handle *handle,
3687 const char **architecture)
3689 DATA_BLOB blob;
3690 enum winreg_Type type;
3691 uint8_t *data;
3692 uint32_t needed;
3694 torture_assert(tctx,
3695 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3696 "failed to get Architecture");
3698 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3700 blob = data_blob_const(data, needed);
3701 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3703 return true;
3706 static bool test_GetPrinterData_list(struct torture_context *tctx,
3707 void *private_data)
3709 struct test_spoolss_context *ctx =
3710 talloc_get_type_abort(private_data, struct test_spoolss_context);
3711 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3712 struct dcerpc_binding_handle *b = p->binding_handle;
3713 const char *list[] = {
3714 "W3SvcInstalled",
3715 "BeepEnabled",
3716 "EventLog",
3717 /* "NetPopup", not on w2k8 */
3718 /* "NetPopupToComputer", not on w2k8 */
3719 "MajorVersion",
3720 "MinorVersion",
3721 "DefaultSpoolDirectory",
3722 "Architecture",
3723 "DsPresent",
3724 "OSVersion",
3725 /* "OSVersionEx", not on s3 */
3726 "DNSMachineName"
3728 int i;
3730 for (i=0; i < ARRAY_SIZE(list); i++) {
3731 enum winreg_Type type, type_ex;
3732 uint8_t *data, *data_ex;
3733 uint32_t needed, needed_ex;
3735 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3736 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3737 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3738 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3739 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3740 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3741 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3744 return true;
3747 static bool test_EnumPrinterData(struct torture_context *tctx,
3748 struct dcerpc_pipe *p,
3749 struct policy_handle *handle,
3750 uint32_t enum_index,
3751 uint32_t value_offered,
3752 uint32_t data_offered,
3753 enum winreg_Type *type_p,
3754 uint32_t *value_needed_p,
3755 uint32_t *data_needed_p,
3756 const char **value_name_p,
3757 uint8_t **data_p,
3758 WERROR *result_p)
3760 struct spoolss_EnumPrinterData r;
3761 uint32_t data_needed;
3762 uint32_t value_needed;
3763 enum winreg_Type type;
3764 struct dcerpc_binding_handle *b = p->binding_handle;
3766 r.in.handle = handle;
3767 r.in.enum_index = enum_index;
3768 r.in.value_offered = value_offered;
3769 r.in.data_offered = data_offered;
3770 r.out.data_needed = &data_needed;
3771 r.out.value_needed = &value_needed;
3772 r.out.type = &type;
3773 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3774 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3776 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3778 torture_assert_ntstatus_ok(tctx,
3779 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3780 "EnumPrinterData failed");
3782 if (type_p) {
3783 *type_p = type;
3785 if (value_needed_p) {
3786 *value_needed_p = value_needed;
3788 if (data_needed_p) {
3789 *data_needed_p = data_needed;
3791 if (value_name_p) {
3792 *value_name_p = r.out.value_name;
3794 if (data_p) {
3795 *data_p = r.out.data;
3797 if (result_p) {
3798 *result_p = r.out.result;
3801 return true;
3805 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3806 struct dcerpc_pipe *p,
3807 struct policy_handle *handle)
3809 uint32_t enum_index = 0;
3810 enum winreg_Type type;
3811 uint32_t value_needed;
3812 uint32_t data_needed;
3813 uint8_t *data;
3814 const char *value_name;
3815 WERROR result;
3817 torture_comment(tctx, "Testing EnumPrinterData\n");
3819 do {
3820 torture_assert(tctx,
3821 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3822 &type, &value_needed, &data_needed,
3823 &value_name, &data, &result),
3824 "EnumPrinterData failed");
3826 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3827 break;
3830 torture_assert(tctx,
3831 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3832 &type, &value_needed, &data_needed,
3833 &value_name, &data, &result),
3834 "EnumPrinterData failed");
3836 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3837 break;
3840 enum_index++;
3842 } while (W_ERROR_IS_OK(result));
3844 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3846 return true;
3849 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3850 struct dcerpc_binding_handle *b,
3851 struct policy_handle *handle,
3852 const char *key_name,
3853 uint32_t *count_p,
3854 struct spoolss_PrinterEnumValues **info_p)
3856 struct spoolss_EnumPrinterDataEx r;
3857 struct spoolss_PrinterEnumValues *info;
3858 uint32_t needed;
3859 uint32_t count;
3861 r.in.handle = handle;
3862 r.in.key_name = key_name;
3863 r.in.offered = 0;
3864 r.out.needed = &needed;
3865 r.out.count = &count;
3866 r.out.info = &info;
3868 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3870 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3871 "EnumPrinterDataEx failed");
3872 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3873 r.in.offered = needed;
3874 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3875 "EnumPrinterDataEx failed");
3878 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3880 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3882 if (count_p) {
3883 *count_p = count;
3885 if (info_p) {
3886 *info_p = info;
3889 return true;
3892 static bool test_SetPrinterData(struct torture_context *tctx,
3893 struct dcerpc_binding_handle *b,
3894 struct policy_handle *handle,
3895 const char *value_name,
3896 enum winreg_Type type,
3897 uint8_t *data,
3898 uint32_t offered);
3899 static bool test_DeletePrinterData(struct torture_context *tctx,
3900 struct dcerpc_binding_handle *b,
3901 struct policy_handle *handle,
3902 const char *value_name);
3904 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3905 struct dcerpc_pipe *p,
3906 struct policy_handle *handle)
3908 uint32_t count;
3909 struct spoolss_PrinterEnumValues *info;
3910 int i;
3911 uint32_t value_needed, data_needed;
3912 uint32_t value_offered, data_offered;
3913 WERROR result;
3914 struct dcerpc_binding_handle *b = p->binding_handle;
3916 enum winreg_Type type;
3917 DATA_BLOB blob;
3919 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3921 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3922 type = REG_SZ;
3924 torture_assert(tctx,
3925 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3926 "SetPrinterData failed");
3928 blob = data_blob_string_const("torture_data2");
3930 torture_assert(tctx,
3931 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3932 "SetPrinterData failed");
3934 blob = data_blob_talloc(tctx, NULL, 4);
3935 SIVAL(blob.data, 0, 0x11223344);
3937 torture_assert(tctx,
3938 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3939 "SetPrinterData failed");
3941 torture_assert(tctx,
3942 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3943 "failed to call EnumPrinterDataEx");
3945 /* get the max sizes for value and data */
3947 torture_assert(tctx,
3948 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3949 NULL, &value_needed, &data_needed,
3950 NULL, NULL, &result),
3951 "EnumPrinterData failed");
3952 torture_assert_werr_ok(tctx, result, "unexpected result");
3954 /* check if the reply from the EnumPrinterData really matches max values */
3956 for (i=0; i < count; i++) {
3957 if (info[i].value_name_len > value_needed) {
3958 torture_fail(tctx,
3959 talloc_asprintf(tctx,
3960 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3961 info[i].value_name_len, value_needed));
3963 if (info[i].data_length > data_needed) {
3964 torture_fail(tctx,
3965 talloc_asprintf(tctx,
3966 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3967 info[i].data_length, data_needed));
3971 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3972 * sort or not sort the replies by value name, we should be able to do
3973 * the following entry comparison */
3975 data_offered = data_needed;
3976 value_offered = value_needed;
3978 for (i=0; i < count; i++) {
3980 const char *value_name;
3981 uint8_t *data;
3983 torture_assert(tctx,
3984 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3985 &type, &value_needed, &data_needed,
3986 &value_name, &data, &result),
3987 "EnumPrinterData failed");
3989 if (i -1 == count) {
3990 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3991 "unexpected result");
3992 break;
3993 } else {
3994 torture_assert_werr_ok(tctx, result, "unexpected result");
3997 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3998 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3999 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4000 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4001 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4004 torture_assert(tctx,
4005 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4006 "DeletePrinterData failed");
4007 torture_assert(tctx,
4008 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4009 "DeletePrinterData failed");
4010 torture_assert(tctx,
4011 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4012 "DeletePrinterData failed");
4014 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4016 return true;
4019 static bool test_DeletePrinterData(struct torture_context *tctx,
4020 struct dcerpc_binding_handle *b,
4021 struct policy_handle *handle,
4022 const char *value_name)
4024 NTSTATUS status;
4025 struct spoolss_DeletePrinterData r;
4027 r.in.handle = handle;
4028 r.in.value_name = value_name;
4030 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4031 r.in.value_name);
4033 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4035 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4036 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4038 return true;
4041 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4042 struct dcerpc_binding_handle *b,
4043 struct policy_handle *handle,
4044 const char *key_name,
4045 const char *value_name)
4047 struct spoolss_DeletePrinterDataEx r;
4049 r.in.handle = handle;
4050 r.in.key_name = key_name;
4051 r.in.value_name = value_name;
4053 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4054 r.in.key_name, r.in.value_name);
4056 torture_assert_ntstatus_ok(tctx,
4057 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4058 "DeletePrinterDataEx failed");
4059 torture_assert_werr_ok(tctx, r.out.result,
4060 "DeletePrinterDataEx failed");
4062 return true;
4065 static bool test_DeletePrinterKey(struct torture_context *tctx,
4066 struct dcerpc_binding_handle *b,
4067 struct policy_handle *handle,
4068 const char *key_name)
4070 struct spoolss_DeletePrinterKey r;
4072 r.in.handle = handle;
4073 r.in.key_name = key_name;
4075 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4077 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4078 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4079 return true;
4082 torture_assert_ntstatus_ok(tctx,
4083 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4084 "DeletePrinterKey failed");
4085 torture_assert_werr_ok(tctx, r.out.result,
4086 "DeletePrinterKey failed");
4088 return true;
4091 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4092 struct dcerpc_binding_handle *b,
4093 struct policy_handle *handle)
4095 struct winreg_OpenHKLM r;
4097 r.in.system_name = NULL;
4098 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4099 r.out.handle = handle;
4101 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4103 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4104 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4106 return true;
4109 static void init_winreg_String(struct winreg_String *name, const char *s)
4111 name->name = s;
4112 if (s) {
4113 name->name_len = 2 * (strlen_m(s) + 1);
4114 name->name_size = name->name_len;
4115 } else {
4116 name->name_len = 0;
4117 name->name_size = 0;
4121 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4122 struct dcerpc_binding_handle *b,
4123 struct policy_handle *hive_handle,
4124 const char *keyname,
4125 uint32_t options,
4126 struct policy_handle *key_handle)
4128 struct winreg_OpenKey r;
4130 r.in.parent_handle = hive_handle;
4131 init_winreg_String(&r.in.keyname, keyname);
4132 r.in.options = options;
4133 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4134 r.out.handle = key_handle;
4136 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4138 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4139 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4141 return true;
4144 static bool test_winreg_OpenKey(struct torture_context *tctx,
4145 struct dcerpc_binding_handle *b,
4146 struct policy_handle *hive_handle,
4147 const char *keyname,
4148 struct policy_handle *key_handle)
4150 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4151 REG_OPTION_NON_VOLATILE, key_handle);
4154 static bool test_winreg_CloseKey(struct torture_context *tctx,
4155 struct dcerpc_binding_handle *b,
4156 struct policy_handle *handle)
4158 struct winreg_CloseKey r;
4160 r.in.handle = handle;
4161 r.out.handle = handle;
4163 torture_comment(tctx, "Testing winreg_CloseKey\n");
4165 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4166 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4168 return true;
4171 bool test_winreg_QueryValue(struct torture_context *tctx,
4172 struct dcerpc_binding_handle *b,
4173 struct policy_handle *handle,
4174 const char *value_name,
4175 enum winreg_Type *type_p,
4176 uint32_t *data_size_p,
4177 uint32_t *data_length_p,
4178 uint8_t **data_p)
4180 struct winreg_QueryValue r;
4181 enum winreg_Type type = REG_NONE;
4182 uint32_t data_size = 0;
4183 uint32_t data_length = 0;
4184 struct winreg_String valuename;
4185 uint8_t *data = NULL;
4187 init_winreg_String(&valuename, value_name);
4189 data = talloc_zero_array(tctx, uint8_t, 0);
4191 r.in.handle = handle;
4192 r.in.value_name = &valuename;
4193 r.in.type = &type;
4194 r.in.data_size = &data_size;
4195 r.in.data_length = &data_length;
4196 r.in.data = data;
4197 r.out.type = &type;
4198 r.out.data = data;
4199 r.out.data_size = &data_size;
4200 r.out.data_length = &data_length;
4202 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4204 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4205 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4206 *r.in.data_size = *r.out.data_size;
4207 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4208 r.in.data = data;
4209 r.out.data = data;
4210 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4212 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4214 if (type_p) {
4215 *type_p = *r.out.type;
4217 if (data_size_p) {
4218 *data_size_p = *r.out.data_size;
4220 if (data_length_p) {
4221 *data_length_p = *r.out.data_length;
4223 if (data_p) {
4224 *data_p = r.out.data;
4227 return true;
4230 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4231 struct dcerpc_binding_handle *b,
4232 struct policy_handle *handle,
4233 const char *printer_name,
4234 const char *key_name,
4235 const char *value_name,
4236 enum winreg_Type *w_type,
4237 uint32_t *w_size,
4238 uint32_t *w_length,
4239 uint8_t **w_data)
4241 const char *printer_key;
4242 struct policy_handle key_handle;
4244 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4245 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4247 torture_assert(tctx,
4248 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4250 torture_assert(tctx,
4251 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4253 torture_assert(tctx,
4254 test_winreg_CloseKey(tctx, b, &key_handle), "");
4256 return true;
4259 static bool test_GetForm_winreg(struct torture_context *tctx,
4260 struct dcerpc_binding_handle *b,
4261 struct policy_handle *handle,
4262 const char *key_name,
4263 const char *form_name,
4264 enum winreg_Type *w_type,
4265 uint32_t *w_size,
4266 uint32_t *w_length,
4267 uint8_t **w_data)
4269 struct policy_handle key_handle;
4271 torture_assert(tctx,
4272 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4274 torture_assert(tctx,
4275 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4277 torture_assert(tctx,
4278 test_winreg_CloseKey(tctx, b, &key_handle), "");
4280 return true;
4283 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4284 struct dcerpc_binding_handle *b,
4285 struct policy_handle *handle,
4286 const char *symlink_keyname,
4287 const char *symlink_destination)
4289 /* check if the first key is a symlink to the second key */
4291 enum winreg_Type w_type;
4292 uint32_t w_size;
4293 uint32_t w_length;
4294 uint8_t *w_data;
4295 struct policy_handle key_handle;
4296 DATA_BLOB blob;
4297 const char *str;
4299 if (torture_setting_bool(tctx, "samba3", false)) {
4300 torture_skip(tctx, "skip winreg symlink test against samba");
4303 torture_assert(tctx,
4304 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4305 "failed to open key link");
4307 torture_assert(tctx,
4308 test_winreg_QueryValue(tctx, b, &key_handle,
4309 "SymbolicLinkValue",
4310 &w_type, &w_size, &w_length, &w_data),
4311 "failed to query for 'SymbolicLinkValue' attribute");
4313 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4315 blob = data_blob(w_data, w_size);
4316 str = reg_val_data_string(tctx, REG_SZ, blob);
4318 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4320 torture_assert(tctx,
4321 test_winreg_CloseKey(tctx, b, &key_handle),
4322 "failed to close key link");
4324 return true;
4327 static const char *strip_unc(const char *unc)
4329 char *name;
4331 if (!unc) {
4332 return NULL;
4335 if (unc[0] == '\\' && unc[1] == '\\') {
4336 unc +=2;
4339 name = strchr(unc, '\\');
4340 if (name) {
4341 return name+1;
4344 return unc;
4347 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4348 struct dcerpc_binding_handle *b,
4349 struct policy_handle *handle,
4350 const char *printer_name,
4351 struct dcerpc_binding_handle *winreg_handle,
4352 struct policy_handle *hive_handle)
4354 union spoolss_PrinterInfo info;
4355 const char *keys[] = {
4356 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4357 TOP_LEVEL_PRINT_PRINTERS_KEY
4359 int i;
4360 const char *printername, *sharename;
4362 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4364 torture_assert(tctx,
4365 test_GetPrinter_level(tctx, b, handle, 2, &info),
4366 "failed to get printer info level 2");
4368 printername = strip_unc(info.info2.printername);
4369 sharename = strip_unc(info.info2.sharename);
4371 #define test_sz(wname, iname) \
4372 do {\
4373 DATA_BLOB blob;\
4374 const char *str;\
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_SZ, "unexpected type");\
4384 blob = data_blob(w_data, w_size);\
4385 str = reg_val_data_string(tctx, REG_SZ, blob);\
4386 if (w_size == 2 && iname == NULL) {\
4387 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4388 } else {\
4389 torture_assert_str_equal(tctx, str, iname,\
4390 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4392 } while(0);
4394 #define test_dword(wname, iname) \
4395 do {\
4396 uint32_t value;\
4397 enum winreg_Type w_type;\
4398 uint32_t w_size;\
4399 uint32_t w_length;\
4400 uint8_t *w_data;\
4401 torture_assert(tctx,\
4402 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4403 &w_type, &w_size, &w_length, &w_data),\
4404 "failed to query winreg");\
4405 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4406 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4407 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4408 value = IVAL(w_data, 0);\
4409 torture_assert_int_equal(tctx, value, iname,\
4410 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4411 } while(0);
4413 #define test_binary(wname, iname) \
4414 do {\
4415 enum winreg_Type w_type;\
4416 uint32_t w_size;\
4417 uint32_t w_length;\
4418 uint8_t *w_data;\
4419 torture_assert(tctx,\
4420 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4421 &w_type, &w_size, &w_length, &w_data),\
4422 "failed to query winreg");\
4423 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4424 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4425 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4426 "binary unequal");\
4427 } while(0);
4430 #define test_dm(wname, iname) \
4431 do {\
4432 DATA_BLOB blob;\
4433 struct spoolss_DeviceMode dm;\
4434 enum ndr_err_code ndr_err;\
4435 enum winreg_Type w_type;\
4436 uint32_t w_size;\
4437 uint32_t w_length;\
4438 uint8_t *w_data;\
4439 torture_assert(tctx,\
4440 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4441 &w_type, &w_size, &w_length, &w_data),\
4442 "failed to query winreg");\
4443 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4444 blob = data_blob(w_data, w_size);\
4445 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4446 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4447 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4448 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4449 "dm unequal");\
4450 } while(0);
4452 #define test_sd(wname, iname) \
4453 do {\
4454 DATA_BLOB blob;\
4455 struct security_descriptor sd;\
4456 enum ndr_err_code ndr_err;\
4457 enum winreg_Type w_type;\
4458 uint32_t w_size;\
4459 uint32_t w_length;\
4460 uint8_t *w_data;\
4461 torture_assert(tctx,\
4462 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4463 &w_type, &w_size, &w_length, &w_data),\
4464 "failed to query winreg");\
4465 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4466 blob = data_blob(w_data, w_size);\
4467 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4468 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4469 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4470 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4471 "sd unequal");\
4472 } while(0);
4474 #define test_multi_sz(wname, iname) \
4475 do {\
4476 DATA_BLOB blob;\
4477 const char **array;\
4478 enum winreg_Type w_type;\
4479 uint32_t w_size;\
4480 uint32_t w_length;\
4481 uint8_t *w_data;\
4482 int i;\
4483 torture_assert(tctx,\
4484 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4485 &w_type, &w_size, &w_length, &w_data),\
4486 "failed to query winreg");\
4487 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4488 blob = data_blob(w_data, w_size);\
4489 torture_assert(tctx, \
4490 pull_reg_multi_sz(tctx, &blob, &array),\
4491 "failed to pull multi sz");\
4492 for (i=0; array[i] != NULL; i++) {\
4493 torture_assert_str_equal(tctx, array[i], iname[i],\
4494 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4496 } while(0);
4498 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4499 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4500 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4502 torture_warning(tctx, "failed to check for winreg symlink");
4505 for (i=0; i < ARRAY_SIZE(keys); i++) {
4507 const char *printer_key;
4508 struct policy_handle key_handle;
4510 printer_key = talloc_asprintf(tctx, "%s\\%s",
4511 keys[i], printer_name);
4513 torture_assert(tctx,
4514 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4516 test_sz("Name", printername);
4517 test_sz("Share Name", sharename);
4518 test_sz("Port", info.info2.portname);
4519 test_sz("Printer Driver", info.info2.drivername);
4520 test_sz("Description", info.info2.comment);
4521 test_sz("Location", info.info2.location);
4522 test_sz("Separator File", info.info2.sepfile);
4523 test_sz("Print Processor", info.info2.printprocessor);
4524 test_sz("Datatype", info.info2.datatype);
4525 test_sz("Parameters", info.info2.parameters);
4526 /* winreg: 0, spoolss not */
4527 /* test_dword("Attributes", info.info2.attributes); */
4528 test_dword("Priority", info.info2.priority);
4529 test_dword("Default Priority", info.info2.defaultpriority);
4530 /* winreg: 60, spoolss: 0 */
4531 /* test_dword("StartTime", info.info2.starttime); */
4532 /* test_dword("UntilTime", info.info2.untiltime); */
4533 /* winreg != spoolss */
4534 /* test_dword("Status", info.info2.status); */
4535 test_dm("Default DevMode", info.info2.devmode);
4536 test_sd("Security", info.info2.secdesc);
4538 torture_assert(tctx,
4539 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4542 #undef test_dm
4543 #undef test_sd
4545 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4547 return true;
4550 static bool test_PrintProcessors(struct torture_context *tctx,
4551 struct dcerpc_binding_handle *b,
4552 const char *environment,
4553 struct dcerpc_binding_handle *winreg_handle,
4554 struct policy_handle *hive_handle)
4556 union spoolss_PrintProcessorInfo *info;
4557 uint32_t count;
4558 int i;
4560 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4562 torture_assert(tctx,
4563 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4564 "failed to enum print processors level 1");
4566 for (i=0; i < count; i++) {
4568 const char *processor_key;
4569 struct policy_handle key_handle;
4571 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4572 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4573 environment,
4574 info[i].info1.print_processor_name);
4576 torture_assert(tctx,
4577 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4579 /* nothing to check in there so far */
4581 torture_assert(tctx,
4582 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4585 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4587 return true;
4590 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4591 struct dcerpc_binding_handle *b,
4592 struct policy_handle *handle,
4593 const char *driver_name,
4594 const char *architecture,
4595 uint32_t level,
4596 uint32_t client_major_version,
4597 uint32_t client_minor_version,
4598 union spoolss_DriverInfo *info_p,
4599 WERROR *result);
4601 static const char *strip_path(const char *path)
4603 char *p;
4605 if (path == NULL) {
4606 return NULL;
4609 p = strrchr(path, '\\');
4610 if (p) {
4611 return p+1;
4614 return path;
4617 static const char **strip_paths(const char **path_array)
4619 int i;
4621 if (path_array == NULL) {
4622 return NULL;
4625 for (i=0; path_array[i] != NULL; i++) {
4626 path_array[i] = strip_path(path_array[i]);
4629 return path_array;
4632 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4634 time_t t;
4635 struct tm *tm;
4637 if (nt == 0) {
4638 return talloc_strdup(mem_ctx, "01/01/1601");
4641 t = nt_time_to_unix(nt);
4642 tm = localtime(&t);
4644 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4645 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4648 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4650 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4651 (unsigned)((v >> 48) & 0xFFFF),
4652 (unsigned)((v >> 32) & 0xFFFF),
4653 (unsigned)((v >> 16) & 0xFFFF),
4654 (unsigned)(v & 0xFFFF));
4657 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4658 struct dcerpc_binding_handle *b,
4659 struct policy_handle *handle,
4660 const char *printer_name,
4661 const char *driver_name,
4662 const char *environment,
4663 enum spoolss_DriverOSVersion version,
4664 struct dcerpc_binding_handle *winreg_handle,
4665 struct policy_handle *hive_handle,
4666 const char *server_name_slash)
4668 WERROR result;
4669 union spoolss_DriverInfo info;
4670 const char *driver_key;
4671 struct policy_handle key_handle;
4673 const char *driver_path;
4674 const char *data_file;
4675 const char *config_file;
4676 const char *help_file;
4677 const char **dependent_files;
4679 const char *driver_date;
4680 const char *inbox_driver_date;
4682 const char *driver_version;
4683 const char *inbox_driver_version;
4685 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4687 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4688 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4689 environment,
4690 version,
4691 driver_name);
4693 torture_assert(tctx,
4694 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4695 "failed to open driver key");
4697 if (torture_setting_bool(tctx, "samba3", false) ||
4698 torture_setting_bool(tctx, "w2k3", false)) {
4699 goto try_level6;
4702 if (handle) {
4703 torture_assert(tctx,
4704 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4705 "failed to get driver info level 8");
4706 } else {
4707 torture_assert(tctx,
4708 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4709 "failed to get driver info level 8");
4712 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4713 goto try_level6;
4716 driver_path = strip_path(info.info8.driver_path);
4717 data_file = strip_path(info.info8.data_file);
4718 config_file = strip_path(info.info8.config_file);
4719 help_file = strip_path(info.info8.help_file);
4720 dependent_files = strip_paths(info.info8.dependent_files);
4722 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4723 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4725 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4726 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4728 test_sz("Configuration File", config_file);
4729 test_sz("Data File", data_file);
4730 test_sz("Datatype", info.info8.default_datatype);
4731 test_sz("Driver", driver_path);
4732 test_sz("DriverDate", driver_date);
4733 test_sz("DriverVersion", driver_version);
4734 test_sz("HardwareID", info.info8.hardware_id);
4735 test_sz("Help File", help_file);
4736 test_sz("InfPath", info.info8.inf_path);
4737 test_sz("Manufacturer", info.info8.manufacturer_name);
4738 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4739 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4740 test_sz("Monitor", info.info8.monitor_name);
4741 test_sz("OEM URL", info.info8.manufacturer_url);
4742 test_sz("Print Processor", info.info8.print_processor);
4743 test_sz("Provider", info.info8.provider);
4744 test_sz("VendorSetup", info.info8.vendor_setup);
4745 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4746 test_multi_sz("Dependent Files", dependent_files);
4747 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4748 test_multi_sz("Previous Names", info.info8.previous_names);
4749 /* test_dword("Attributes", ?); */
4750 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4751 test_dword("Version", info.info8.version);
4752 /* test_dword("TempDir", ?); */
4754 try_level6:
4756 if (handle) {
4757 torture_assert(tctx,
4758 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4759 "failed to get driver info level 6");
4760 } else {
4761 torture_assert(tctx,
4762 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4763 "failed to get driver info level 6");
4766 driver_path = strip_path(info.info6.driver_path);
4767 data_file = strip_path(info.info6.data_file);
4768 config_file = strip_path(info.info6.config_file);
4769 help_file = strip_path(info.info6.help_file);
4770 dependent_files = strip_paths(info.info6.dependent_files);
4772 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4774 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4776 test_sz("Configuration File", config_file);
4777 test_sz("Data File", data_file);
4778 test_sz("Datatype", info.info6.default_datatype);
4779 test_sz("Driver", driver_path);
4780 if (torture_setting_bool(tctx, "w2k3", false)) {
4781 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4782 push_nttime(blob.data, 0, info.info6.driver_date);
4783 test_binary("DriverDate", blob);
4784 SBVAL(blob.data, 0, info.info6.driver_version);
4785 test_binary("DriverVersion", blob);
4786 } else {
4787 test_sz("DriverDate", driver_date);
4788 test_sz("DriverVersion", driver_version);
4790 test_sz("HardwareID", info.info6.hardware_id);
4791 test_sz("Help File", help_file);
4792 test_sz("Manufacturer", info.info6.manufacturer_name);
4793 test_sz("Monitor", info.info6.monitor_name);
4794 test_sz("OEM URL", info.info6.manufacturer_url);
4795 test_sz("Provider", info.info6.provider);
4796 test_multi_sz("Dependent Files", dependent_files);
4797 test_multi_sz("Previous Names", info.info6.previous_names);
4798 /* test_dword("Attributes", ?); */
4799 test_dword("Version", info.info6.version);
4800 /* test_dword("TempDir", ?); */
4802 if (handle) {
4803 torture_assert(tctx,
4804 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4805 "failed to get driver info level 3");
4806 } else {
4807 torture_assert(tctx,
4808 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4809 "failed to get driver info level 3");
4812 driver_path = strip_path(info.info3.driver_path);
4813 data_file = strip_path(info.info3.data_file);
4814 config_file = strip_path(info.info3.config_file);
4815 help_file = strip_path(info.info3.help_file);
4816 dependent_files = strip_paths(info.info3.dependent_files);
4818 test_sz("Configuration File", config_file);
4819 test_sz("Data File", data_file);
4820 test_sz("Datatype", info.info3.default_datatype);
4821 test_sz("Driver", driver_path);
4822 test_sz("Help File", help_file);
4823 test_sz("Monitor", info.info3.monitor_name);
4824 test_multi_sz("Dependent Files", dependent_files);
4825 /* test_dword("Attributes", ?); */
4826 test_dword("Version", info.info3.version);
4827 /* test_dword("TempDir", ?); */
4830 torture_assert(tctx,
4831 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4833 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4835 return true;
4838 #undef test_sz
4839 #undef test_dword
4841 static bool test_SetPrinterData(struct torture_context *tctx,
4842 struct dcerpc_binding_handle *b,
4843 struct policy_handle *handle,
4844 const char *value_name,
4845 enum winreg_Type type,
4846 uint8_t *data,
4847 uint32_t offered)
4849 struct spoolss_SetPrinterData r;
4851 r.in.handle = handle;
4852 r.in.value_name = value_name;
4853 r.in.type = type;
4854 r.in.data = data;
4855 r.in.offered = offered;
4857 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4858 r.in.value_name);
4860 torture_assert_ntstatus_ok(tctx,
4861 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4862 "SetPrinterData failed");
4863 torture_assert_werr_ok(tctx, r.out.result,
4864 "SetPrinterData failed");
4866 return true;
4869 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4870 struct dcerpc_binding_handle *b,
4871 struct policy_handle *handle,
4872 const char *printer_name,
4873 struct dcerpc_binding_handle *winreg_handle,
4874 struct policy_handle *hive_handle)
4876 const char *values[] = {
4877 "spootyfoot",
4878 "spooty\\foot",
4879 #if 0
4880 /* FIXME: not working with s3 atm. */
4881 "spooty,foot",
4882 "spooty,fo,ot",
4883 #endif
4884 "spooty foot",
4885 #if 0
4886 /* FIXME: not working with s3 atm. */
4887 "spooty\\fo,ot",
4888 "spooty,fo\\ot"
4889 #endif
4891 int i;
4893 for (i=0; i < ARRAY_SIZE(values); i++) {
4895 enum winreg_Type type, expected_type = REG_SZ;
4896 DATA_BLOB blob;
4897 uint8_t *data;
4898 uint32_t needed;
4900 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4901 type = REG_SZ;
4903 torture_assert(tctx,
4904 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4905 "SetPrinterData failed");
4907 torture_assert(tctx,
4908 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4909 "GetPrinterData failed");
4911 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4912 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4913 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4915 if (winreg_handle && hive_handle) {
4917 enum winreg_Type w_type;
4918 uint32_t w_size;
4919 uint32_t w_length;
4920 uint8_t *w_data;
4922 torture_assert(tctx,
4923 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4924 printer_name, "PrinterDriverData", values[i],
4925 &w_type, &w_size, &w_length, &w_data), "");
4927 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4928 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4929 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4930 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4933 torture_assert(tctx,
4934 test_DeletePrinterData(tctx, b, handle, values[i]),
4935 "DeletePrinterData failed");
4938 return true;
4942 static bool test_EnumPrinterKey(struct torture_context *tctx,
4943 struct dcerpc_binding_handle *b,
4944 struct policy_handle *handle,
4945 const char *key_name,
4946 const char ***array);
4948 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4949 struct dcerpc_binding_handle *b,
4950 struct policy_handle *handle,
4951 const char *key_name,
4952 const char *value_name,
4953 enum winreg_Type type,
4954 uint8_t *data,
4955 uint32_t offered)
4957 NTSTATUS status;
4958 struct spoolss_SetPrinterDataEx r;
4960 r.in.handle = handle;
4961 r.in.key_name = key_name;
4962 r.in.value_name = value_name;
4963 r.in.type = type;
4964 r.in.data = data;
4965 r.in.offered = offered;
4967 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4968 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4970 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4972 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4973 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4975 return true;
4978 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4979 struct dcerpc_pipe *p,
4980 struct policy_handle *handle)
4982 struct dcerpc_binding_handle *b = p->binding_handle;
4983 const char *value_name = "dog";
4984 const char *keys[] = {
4985 "torturedataex",
4986 "torture data ex",
4987 "torturedataex_with_subkey\\subkey",
4988 "torturedataex_with_subkey\\subkey:0",
4989 "torturedataex_with_subkey\\subkey:1",
4990 "torturedataex_with_subkey\\subkey\\subsubkey",
4991 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4992 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4993 "torture,data",
4994 "torture,data,ex",
4995 "torture,data\\ex",
4996 "torture\\data,ex",
4997 "torture/data",
4998 "torture/data ex",
4999 "torture/data ex/sub",
5000 "torture//data",
5001 "torture//data ex",
5002 "torture//data ex/sub",
5003 "torture//data ex//sub",
5005 int i;
5007 for (i=0; i < ARRAY_SIZE(keys); i++) {
5009 char *c;
5010 const char *key;
5011 enum winreg_Type type;
5012 DATA_BLOB blob_in, blob_out;
5013 const char **subkeys;
5014 uint32_t ecount;
5015 struct spoolss_PrinterEnumValues *einfo;
5016 uint32_t needed;
5018 blob_in = data_blob_talloc(tctx, NULL, 42);
5020 generate_random_buffer(blob_in.data, blob_in.length);
5022 torture_assert(tctx,
5023 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5024 "failed to call SetPrinterDataEx");
5026 torture_assert(tctx,
5027 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5028 "failed to call GetPrinterDataEx");
5030 blob_out.length = needed;
5031 torture_assert(tctx,
5032 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5033 "failed to call EnumPrinterDataEx");
5035 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5036 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5037 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5039 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5040 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5041 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5042 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5043 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5044 if (einfo[0].data_length > 0) {
5045 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5048 key = talloc_strdup(tctx, keys[i]);
5050 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5051 return false;
5054 c = strchr(key, '\\');
5055 if (c) {
5056 int k;
5058 /* we have subkeys */
5060 *c = 0;
5062 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5063 return false;
5066 for (k=0; subkeys && subkeys[k]; k++) {
5068 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5070 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5071 return false;
5075 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5076 return false;
5079 } else {
5080 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5081 return false;
5086 return true;
5089 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5090 struct dcerpc_pipe *p,
5091 struct policy_handle *handle)
5093 struct dcerpc_binding_handle *b = p->binding_handle;
5094 const char *key = "torturedataex";
5095 const char *values[] = {
5096 "torture_value",
5097 "torture value",
5098 "torture,value",
5099 "torture/value",
5100 "torture\\value",
5101 "torture\\\\value"
5103 int i;
5105 for (i=0; i < ARRAY_SIZE(values); i++) {
5107 enum winreg_Type type;
5108 DATA_BLOB blob_in, blob_out;
5109 uint32_t ecount;
5110 struct spoolss_PrinterEnumValues *einfo;
5111 uint32_t needed;
5113 if (torture_setting_bool(tctx, "samba3", false)) {
5114 char *q;
5115 q = strrchr(values[i], ',');
5116 if (q) {
5117 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5118 values[i]);
5119 continue;
5123 blob_in = data_blob_talloc(tctx, NULL, 42);
5125 generate_random_buffer(blob_in.data, blob_in.length);
5127 torture_assert(tctx,
5128 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5129 "failed to call SetPrinterDataEx");
5131 torture_assert(tctx,
5132 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5133 "failed to call GetPrinterDataEx");
5135 blob_out.length = needed;
5136 torture_assert(tctx,
5137 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5138 "failed to call EnumPrinterDataEx");
5140 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5141 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5142 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5144 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5145 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5146 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5147 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5148 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5149 if (einfo[0].data_length > 0) {
5150 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5153 torture_assert(tctx,
5154 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5155 "failed to call DeletePrinterDataEx");
5158 return true;
5162 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5163 struct dcerpc_pipe *p,
5164 struct policy_handle *handle,
5165 const char *printername,
5166 struct dcerpc_binding_handle *winreg_handle,
5167 struct policy_handle *hive_handle)
5169 struct dcerpc_binding_handle *b = p->binding_handle;
5170 const char *value_name = "dog";
5171 const char *key_name = "torturedataex";
5172 enum winreg_Type types[] = {
5173 REG_SZ,
5174 REG_MULTI_SZ,
5175 REG_DWORD,
5176 REG_BINARY
5178 const char *str = "abcdefghi";
5179 int t, s;
5181 for (t=0; t < ARRAY_SIZE(types); t++) {
5182 for (s=0; s < strlen(str); s++) {
5184 enum winreg_Type type;
5185 const char *string = talloc_strndup(tctx, str, s);
5186 const char *array[2];
5187 DATA_BLOB blob = data_blob_string_const(string);
5188 DATA_BLOB data;
5189 uint8_t *data_out;
5190 uint32_t needed, offered = 0;
5191 uint32_t ecount;
5192 struct spoolss_PrinterEnumValues *einfo;
5194 array[0] = talloc_strdup(tctx, string);
5195 array[1] = NULL;
5197 if (types[t] == REG_DWORD) {
5198 s = 0xffff;
5201 switch (types[t]) {
5202 case REG_BINARY:
5203 data = blob;
5204 offered = blob.length;
5205 break;
5206 case REG_DWORD:
5207 data = data_blob_talloc(tctx, NULL, 4);
5208 SIVAL(data.data, 0, 0x12345678);
5209 offered = 4;
5210 break;
5211 case REG_SZ:
5212 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5213 type = REG_SZ;
5214 offered = data.length;
5215 /*strlen_m_term(data.string)*2;*/
5216 break;
5217 case REG_MULTI_SZ:
5218 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5219 type = REG_MULTI_SZ;
5220 offered = data.length;
5221 break;
5222 default:
5223 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5226 torture_assert(tctx,
5227 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5228 "failed to call SetPrinterDataEx");
5230 torture_assert(tctx,
5231 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5232 "failed to call GetPrinterDataEx");
5234 torture_assert(tctx,
5235 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5236 "failed to call EnumPrinterDataEx");
5238 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5239 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5240 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5242 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5243 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5244 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5245 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5246 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5247 if (einfo[0].data_length > 0) {
5248 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5251 if (winreg_handle && hive_handle) {
5252 enum winreg_Type w_type;
5253 uint32_t w_size;
5254 uint32_t w_length;
5255 uint8_t *w_data;
5257 torture_assert(tctx,
5258 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5259 printername, key_name, value_name,
5260 &w_type, &w_size, &w_length, &w_data), "");
5262 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5263 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5264 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5265 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5268 torture_assert(tctx,
5269 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5270 "failed to call DeletePrinterDataEx");
5274 return true;
5277 static bool test_PrinterData_winreg(struct torture_context *tctx,
5278 struct dcerpc_pipe *p,
5279 struct policy_handle *handle,
5280 const char *printer_name)
5282 struct dcerpc_binding_handle *b = p->binding_handle;
5283 struct dcerpc_pipe *p2;
5284 bool ret = true;
5285 struct policy_handle hive_handle;
5286 struct dcerpc_binding_handle *b2;
5288 torture_assert_ntstatus_ok(tctx,
5289 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5290 "could not open winreg pipe");
5291 b2 = p2->binding_handle;
5293 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5295 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5296 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5298 test_winreg_CloseKey(tctx, b2, &hive_handle);
5300 talloc_free(p2);
5302 return ret;
5305 static bool test_Forms_winreg(struct torture_context *tctx,
5306 struct dcerpc_binding_handle *b,
5307 struct policy_handle *handle,
5308 bool print_server,
5309 const char *printer_name)
5311 struct dcerpc_pipe *p2;
5312 bool ret = true;
5313 struct policy_handle hive_handle;
5314 struct dcerpc_binding_handle *b2;
5316 torture_assert_ntstatus_ok(tctx,
5317 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5318 "could not open winreg pipe");
5319 b2 = p2->binding_handle;
5321 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5323 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5325 test_winreg_CloseKey(tctx, b2, &hive_handle);
5327 talloc_free(p2);
5329 return ret;
5332 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5333 struct dcerpc_pipe *p,
5334 struct policy_handle *handle,
5335 const char *printer_name)
5337 struct dcerpc_binding_handle *b = p->binding_handle;
5338 struct dcerpc_pipe *p2;
5339 bool ret = true;
5340 struct policy_handle hive_handle;
5341 struct dcerpc_binding_handle *b2;
5343 torture_assert_ntstatus_ok(tctx,
5344 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5345 "could not open winreg pipe");
5346 b2 = p2->binding_handle;
5348 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5350 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5352 test_winreg_CloseKey(tctx, b2, &hive_handle);
5354 talloc_free(p2);
5356 return ret;
5359 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5360 struct dcerpc_pipe *p,
5361 struct policy_handle *handle,
5362 const char *printer_name,
5363 const char *driver_name,
5364 const char *environment,
5365 enum spoolss_DriverOSVersion version)
5367 struct dcerpc_binding_handle *b = p->binding_handle;
5368 struct dcerpc_pipe *p2;
5369 bool ret = true;
5370 struct policy_handle hive_handle;
5371 struct dcerpc_binding_handle *b2;
5373 torture_assert_ntstatus_ok(tctx,
5374 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5375 "could not open winreg pipe");
5376 b2 = p2->binding_handle;
5378 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5380 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5382 test_winreg_CloseKey(tctx, b2, &hive_handle);
5384 talloc_free(p2);
5386 return ret;
5389 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5390 struct dcerpc_binding_handle *b,
5391 const char *environment)
5393 struct dcerpc_pipe *p2;
5394 bool ret = true;
5395 struct policy_handle hive_handle;
5396 struct dcerpc_binding_handle *b2;
5398 torture_assert_ntstatus_ok(tctx,
5399 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5400 "could not open winreg pipe");
5401 b2 = p2->binding_handle;
5403 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5405 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5407 test_winreg_CloseKey(tctx, b2, &hive_handle);
5409 talloc_free(p2);
5411 return ret;
5414 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5415 struct dcerpc_pipe *p,
5416 struct policy_handle *handle,
5417 const char *printer_name)
5419 struct spoolss_SetPrinterInfoCtr info_ctr;
5420 struct spoolss_DevmodeContainer devmode_ctr;
5421 struct sec_desc_buf secdesc_ctr;
5422 union spoolss_SetPrinterInfo sinfo;
5423 union spoolss_PrinterInfo info;
5424 struct dcerpc_binding_handle *b = p->binding_handle;
5425 const char *pname;
5427 ZERO_STRUCT(info_ctr);
5428 ZERO_STRUCT(devmode_ctr);
5429 ZERO_STRUCT(secdesc_ctr);
5431 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5433 torture_assert(tctx,
5434 test_GetPrinter_level(tctx, b, handle, 2, &info),
5435 "failed to query Printer level 2");
5437 torture_assert(tctx,
5438 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5439 "failed to convert");
5441 info_ctr.level = 2;
5442 info_ctr.info = sinfo;
5444 #define TEST_SZ(wname, iname) \
5445 do {\
5446 enum winreg_Type type;\
5447 uint8_t *data;\
5448 uint32_t needed;\
5449 DATA_BLOB blob;\
5450 const char *str;\
5451 torture_assert(tctx,\
5452 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5453 "failed to query");\
5454 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5455 blob = data_blob_const(data, needed);\
5456 torture_assert(tctx,\
5457 pull_reg_sz(tctx, &blob, &str),\
5458 "failed to pull REG_SZ");\
5459 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5460 } while(0);
5463 #define TEST_SET_SZ(wname, iname, val) \
5464 do {\
5465 enum winreg_Type type;\
5466 uint8_t *data;\
5467 uint32_t needed;\
5468 DATA_BLOB blob;\
5469 const char *str;\
5470 sinfo.info2->iname = val;\
5471 torture_assert(tctx,\
5472 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5473 "failed to call SetPrinter");\
5474 torture_assert(tctx,\
5475 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5476 "failed to query");\
5477 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5478 blob = data_blob_const(data, needed);\
5479 torture_assert(tctx,\
5480 pull_reg_sz(tctx, &blob, &str),\
5481 "failed to pull REG_SZ");\
5482 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5483 } while(0);
5485 #define TEST_SET_DWORD(wname, iname, val) \
5486 do {\
5487 enum winreg_Type type;\
5488 uint8_t *data;\
5489 uint32_t needed;\
5490 uint32_t value;\
5491 sinfo.info2->iname = val;\
5492 torture_assert(tctx,\
5493 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5494 "failed to call SetPrinter");\
5495 torture_assert(tctx,\
5496 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5497 "failed to query");\
5498 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5499 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5500 value = IVAL(data, 0); \
5501 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5502 } while(0);
5504 TEST_SET_SZ("description", comment, "newval");
5505 TEST_SET_SZ("location", location, "newval");
5506 TEST_SET_SZ("driverName", drivername, "newval");
5507 /* TEST_SET_DWORD("priority", priority, 25); */
5509 torture_assert(tctx,
5510 test_GetPrinter_level(tctx, b, handle, 2, &info),
5511 "failed to query Printer level 2");
5513 TEST_SZ("description", info.info2.comment);
5514 TEST_SZ("driverName", info.info2.drivername);
5515 TEST_SZ("location", info.info2.location);
5517 pname = strrchr(info.info2.printername, '\\');
5518 if (pname == NULL) {
5519 pname = info.info2.printername;
5520 } else {
5521 pname++;
5523 TEST_SZ("printerName", pname);
5524 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5525 /* TEST_SZ("printShareName", info.info2.sharename); */
5527 /* FIXME gd: complete the list */
5529 #undef TEST_SZ
5530 #undef TEST_SET_SZ
5531 #undef TEST_DWORD
5533 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5535 return true;
5538 static bool test_print_processors_winreg(struct torture_context *tctx,
5539 void *private_data)
5541 struct test_spoolss_context *ctx =
5542 talloc_get_type_abort(private_data, struct test_spoolss_context);
5543 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5544 struct dcerpc_binding_handle *b = p->binding_handle;
5546 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5549 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5550 struct dcerpc_binding_handle *b,
5551 struct policy_handle *handle,
5552 uint32_t *change_id)
5554 enum winreg_Type type;
5555 uint8_t *data;
5556 uint32_t needed;
5558 torture_assert(tctx,
5559 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5560 "failed to call GetPrinterData");
5562 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5563 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5565 *change_id = IVAL(data, 0);
5567 return true;
5570 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5571 struct dcerpc_pipe *p,
5572 struct policy_handle *handle,
5573 uint32_t *change_id)
5575 enum winreg_Type type;
5576 uint8_t *data;
5577 uint32_t needed;
5579 torture_assert(tctx,
5580 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5581 "failed to call GetPrinterData");
5583 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5584 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5586 *change_id = IVAL(data, 0);
5588 return true;
5591 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5592 struct dcerpc_binding_handle *b,
5593 struct policy_handle *handle,
5594 uint32_t *change_id)
5596 union spoolss_PrinterInfo info;
5598 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5599 "failed to query Printer level 0");
5601 *change_id = info.info0.change_id;
5603 return true;
5606 static bool test_ChangeID(struct torture_context *tctx,
5607 struct dcerpc_pipe *p,
5608 struct policy_handle *handle)
5610 uint32_t change_id, change_id_ex, change_id_info;
5611 uint32_t change_id2, change_id_ex2, change_id_info2;
5612 union spoolss_PrinterInfo info;
5613 const char *comment;
5614 struct dcerpc_binding_handle *b = p->binding_handle;
5616 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5618 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5619 "failed to query for ChangeID");
5620 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5621 "failed to query for ChangeID");
5622 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5623 "failed to query for ChangeID");
5625 torture_assert_int_equal(tctx, change_id, change_id_ex,
5626 "change_ids should all be equal");
5627 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5628 "change_ids should all be equal");
5631 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5633 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5634 "failed to query for ChangeID");
5635 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5636 "failed to query Printer level 2");
5637 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5638 "failed to query for ChangeID");
5639 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5640 "failed to query for ChangeID");
5641 torture_assert_int_equal(tctx, change_id, change_id_ex,
5642 "change_id should not have changed");
5643 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5644 "change_id should not have changed");
5647 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5649 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5650 "failed to query for ChangeID");
5651 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5652 "failed to query for ChangeID");
5653 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5654 "failed to query for ChangeID");
5655 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5656 "failed to query Printer level 2");
5657 comment = talloc_strdup(tctx, info.info2.comment);
5660 struct spoolss_SetPrinterInfoCtr info_ctr;
5661 struct spoolss_DevmodeContainer devmode_ctr;
5662 struct sec_desc_buf secdesc_ctr;
5663 union spoolss_SetPrinterInfo sinfo;
5665 ZERO_STRUCT(info_ctr);
5666 ZERO_STRUCT(devmode_ctr);
5667 ZERO_STRUCT(secdesc_ctr);
5670 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5671 sinfo.info2->comment = "torture_comment";
5673 info_ctr.level = 2;
5674 info_ctr.info = sinfo;
5676 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5677 "failed to call SetPrinter");
5679 sinfo.info2->comment = comment;
5681 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5682 "failed to call SetPrinter");
5686 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5687 "failed to query for ChangeID");
5688 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5689 "failed to query for ChangeID");
5690 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5691 "failed to query for ChangeID");
5693 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5694 "change_ids should all be equal");
5695 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5696 "change_ids should all be equal");
5698 torture_assert(tctx, (change_id < change_id2),
5699 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5700 change_id2, change_id));
5701 torture_assert(tctx, (change_id_ex < change_id_ex2),
5702 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5703 change_id_ex2, change_id_ex));
5704 torture_assert(tctx, (change_id_info < change_id_info2),
5705 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5706 change_id_info2, change_id_info));
5708 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5710 return true;
5713 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5714 struct dcerpc_pipe *p,
5715 struct policy_handle *handle)
5717 NTSTATUS status;
5718 struct dcerpc_binding *b;
5719 struct dcerpc_pipe *p2;
5720 struct spoolss_ClosePrinter cp;
5722 /* only makes sense on SMB */
5723 if (p->conn->transport.transport != NCACN_NP) {
5724 return true;
5727 torture_comment(tctx, "Testing close on secondary pipe\n");
5729 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5730 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5732 status = dcerpc_secondary_connection(p, &p2, b);
5733 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5735 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5736 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5738 cp.in.handle = handle;
5739 cp.out.handle = handle;
5741 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5742 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5743 "ERROR: Allowed close on secondary connection");
5745 talloc_free(p2);
5747 return true;
5750 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5751 struct dcerpc_binding_handle *b, const char *name)
5753 NTSTATUS status;
5754 struct spoolss_OpenPrinter op;
5755 struct spoolss_OpenPrinterEx opEx;
5756 struct policy_handle handle;
5757 bool ret = true;
5759 op.in.printername = name;
5760 op.in.datatype = NULL;
5761 op.in.devmode_ctr.devmode= NULL;
5762 op.in.access_mask = 0;
5763 op.out.handle = &handle;
5765 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5767 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5768 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5769 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5770 "unexpected result");
5772 if (W_ERROR_IS_OK(op.out.result)) {
5773 ret &=test_ClosePrinter(tctx, b, &handle);
5776 opEx.in.printername = name;
5777 opEx.in.datatype = NULL;
5778 opEx.in.devmode_ctr.devmode = NULL;
5779 opEx.in.access_mask = 0;
5780 opEx.in.userlevel_ctr.level = 1;
5781 opEx.in.userlevel_ctr.user_info.level1 = NULL;
5782 opEx.out.handle = &handle;
5784 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5786 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5787 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5788 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5789 "unexpected result");
5791 if (W_ERROR_IS_OK(opEx.out.result)) {
5792 ret &=test_ClosePrinter(tctx, b, &handle);
5795 return ret;
5798 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5799 void *private_data)
5801 struct test_spoolss_context *ctx =
5802 talloc_get_type_abort(private_data, struct test_spoolss_context);
5804 const char *badnames[] = {
5805 "__INVALID_PRINTER__",
5806 "\\\\__INVALID_HOST__",
5808 "\\\\\\",
5809 "\\\\\\__INVALID_PRINTER__"
5811 const char *badname;
5812 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5813 const char *server_name = dcerpc_server_name(p);
5814 struct dcerpc_binding_handle *b = p->binding_handle;
5815 int i;
5817 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5818 torture_assert(tctx,
5819 test_OpenPrinter_badname(tctx, b, badnames[i]),
5820 "");
5823 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5824 torture_assert(tctx,
5825 test_OpenPrinter_badname(tctx, b, badname),
5826 "");
5828 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5829 torture_assert(tctx,
5830 test_OpenPrinter_badname(tctx, b, badname),
5831 "");
5833 return true;
5836 static bool test_OpenPrinter(struct torture_context *tctx,
5837 struct dcerpc_pipe *p,
5838 const char *name,
5839 const char *environment,
5840 bool open_only)
5842 NTSTATUS status;
5843 struct spoolss_OpenPrinter r;
5844 struct policy_handle handle;
5845 bool ret = true;
5846 struct dcerpc_binding_handle *b = p->binding_handle;
5848 r.in.printername = name;
5849 r.in.datatype = NULL;
5850 r.in.devmode_ctr.devmode= NULL;
5851 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5852 r.out.handle = &handle;
5854 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5856 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5858 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5860 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5862 if (open_only) {
5863 goto close_printer;
5866 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5867 ret = false;
5870 if (!torture_setting_bool(tctx, "samba3", false)) {
5871 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5872 ret = false;
5876 close_printer:
5877 if (!test_ClosePrinter(tctx, b, &handle)) {
5878 ret = false;
5881 return ret;
5884 static bool test_OpenPrinterEx(struct torture_context *tctx,
5885 struct dcerpc_binding_handle *b,
5886 const char *printername,
5887 const char *datatype,
5888 struct spoolss_DeviceMode *devmode,
5889 uint32_t access_mask,
5890 struct spoolss_UserLevelCtr *userlevel_ctr,
5891 struct policy_handle *handle,
5892 WERROR expected_result)
5894 struct spoolss_OpenPrinterEx r;
5896 r.in.printername = printername;
5897 r.in.datatype = datatype;
5898 r.in.devmode_ctr.devmode= devmode;
5899 r.in.access_mask = access_mask;
5900 r.in.userlevel_ctr = *userlevel_ctr;
5901 r.out.handle = handle;
5903 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5905 torture_assert_ntstatus_ok(tctx,
5906 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5907 "OpenPrinterEx failed");
5909 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5910 "OpenPrinterEx failed");
5912 return true;
5915 static bool call_OpenPrinterEx(struct torture_context *tctx,
5916 struct dcerpc_pipe *p,
5917 const char *name,
5918 struct spoolss_DeviceMode *devmode,
5919 struct policy_handle *handle)
5921 struct spoolss_UserLevelCtr userlevel_ctr;
5922 struct spoolss_UserLevel1 userlevel1;
5923 struct dcerpc_binding_handle *b = p->binding_handle;
5925 userlevel1.size = 1234;
5926 userlevel1.client = "hello";
5927 userlevel1.user = "spottyfoot!";
5928 userlevel1.build = 1;
5929 userlevel1.major = 2;
5930 userlevel1.minor = 3;
5931 userlevel1.processor = 4;
5933 userlevel_ctr.level = 1;
5934 userlevel_ctr.user_info.level1 = &userlevel1;
5936 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5937 SEC_FLAG_MAXIMUM_ALLOWED,
5938 &userlevel_ctr,
5939 handle,
5940 WERR_OK);
5943 static bool test_printer_rename(struct torture_context *tctx,
5944 void *private_data)
5946 struct torture_printer_context *t =
5947 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5948 struct dcerpc_pipe *p = t->spoolss_pipe;
5950 bool ret = true;
5951 union spoolss_PrinterInfo info;
5952 union spoolss_SetPrinterInfo sinfo;
5953 struct spoolss_SetPrinterInfoCtr info_ctr;
5954 struct spoolss_DevmodeContainer devmode_ctr;
5955 struct sec_desc_buf secdesc_ctr;
5956 const char *printer_name;
5957 const char *printer_name_orig;
5958 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5959 struct policy_handle new_handle;
5960 const char *q;
5961 struct dcerpc_binding_handle *b = p->binding_handle;
5963 ZERO_STRUCT(devmode_ctr);
5964 ZERO_STRUCT(secdesc_ctr);
5966 torture_comment(tctx, "Testing Printer rename operations\n");
5968 torture_assert(tctx,
5969 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5970 "failed to call GetPrinter level 2");
5972 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5974 q = strrchr(info.info2.printername, '\\');
5975 if (q) {
5976 torture_warning(tctx,
5977 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5980 torture_assert(tctx,
5981 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5983 sinfo.info2->printername = printer_name_new;
5985 info_ctr.level = 2;
5986 info_ctr.info = sinfo;
5988 torture_assert(tctx,
5989 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5990 "failed to call SetPrinter level 2");
5992 torture_assert(tctx,
5993 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5994 "failed to call GetPrinter level 2");
5996 printer_name = talloc_strdup(tctx, info.info2.printername);
5998 q = strrchr(info.info2.printername, '\\');
5999 if (q) {
6000 torture_warning(tctx,
6001 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6002 q++;
6003 printer_name = q;
6006 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6007 "new printer name was not set");
6009 /* samba currently cannot fully rename printers */
6010 if (!torture_setting_bool(tctx, "samba3", false)) {
6011 torture_assert(tctx,
6012 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6013 "still can open printer with oldname after rename");
6014 } else {
6015 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6018 torture_assert(tctx,
6019 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6020 "failed to open printer with new name");
6022 torture_assert(tctx,
6023 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6024 "failed to call GetPrinter level 2");
6026 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6027 "new printer name was not set");
6029 torture_assert(tctx,
6030 test_ClosePrinter(tctx, b, &new_handle),
6031 "failed to close printer");
6033 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6035 return ret;
6038 static bool test_openprinter(struct torture_context *tctx,
6039 struct dcerpc_binding_handle *b,
6040 const char *real_printername)
6042 struct spoolss_UserLevelCtr userlevel_ctr;
6043 struct policy_handle handle;
6044 struct spoolss_UserLevel1 userlevel1;
6045 const char *printername = NULL;
6046 int i;
6048 struct {
6049 const char *suffix;
6050 WERROR expected_result;
6051 } tests[] = {
6053 .suffix = "rubbish",
6054 .expected_result = WERR_INVALID_PRINTER_NAME
6056 .suffix = ", LocalOnl",
6057 .expected_result = WERR_INVALID_PRINTER_NAME
6059 .suffix = ", localOnly",
6060 .expected_result = WERR_INVALID_PRINTER_NAME
6062 .suffix = ", localonl",
6063 .expected_result = WERR_INVALID_PRINTER_NAME
6065 .suffix = ",LocalOnl",
6066 .expected_result = WERR_INVALID_PRINTER_NAME
6068 .suffix = ",localOnl2",
6069 .expected_result = WERR_INVALID_PRINTER_NAME
6071 .suffix = ", DrvConver2t",
6072 .expected_result = WERR_INVALID_PRINTER_NAME
6074 .suffix = ", drvconvert",
6075 .expected_result = WERR_INVALID_PRINTER_NAME
6077 .suffix = ",drvconvert",
6078 .expected_result = WERR_INVALID_PRINTER_NAME
6080 .suffix = ", DrvConvert",
6081 .expected_result = WERR_OK
6083 .suffix = " , DrvConvert",
6084 .expected_result = WERR_INVALID_PRINTER_NAME
6086 .suffix = ",DrvConvert",
6087 .expected_result = WERR_OK
6089 .suffix = ", DrvConvertsadfasdf",
6090 .expected_result = WERR_OK
6092 .suffix = ",DrvConvertasdfasd",
6093 .expected_result = WERR_OK
6095 .suffix = ", LocalOnly",
6096 .expected_result = WERR_OK
6098 .suffix = " , LocalOnly",
6099 .expected_result = WERR_INVALID_PRINTER_NAME
6101 .suffix = ",LocalOnly",
6102 .expected_result = WERR_OK
6104 .suffix = ", LocalOnlysagi4gjfkd",
6105 .expected_result = WERR_OK
6107 .suffix = ",LocalOnlysagi4gjfkd",
6108 .expected_result = WERR_OK
6112 userlevel1.size = 1234;
6113 userlevel1.client = "hello";
6114 userlevel1.user = "spottyfoot!";
6115 userlevel1.build = 1;
6116 userlevel1.major = 2;
6117 userlevel1.minor = 3;
6118 userlevel1.processor = 4;
6120 userlevel_ctr.level = 1;
6121 userlevel_ctr.user_info.level1 = &userlevel1;
6123 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6125 torture_assert(tctx,
6126 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6127 &userlevel_ctr, &handle,
6128 WERR_OK),
6129 "OpenPrinterEx failed");
6130 test_ClosePrinter(tctx, b, &handle);
6132 for (i=0; i < ARRAY_SIZE(tests); i++) {
6134 printername = talloc_asprintf(tctx, "%s%s",
6135 real_printername,
6136 tests[i].suffix);
6138 torture_assert(tctx,
6139 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6140 &userlevel_ctr, &handle,
6141 tests[i].expected_result),
6142 "OpenPrinterEx failed");
6143 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6144 test_ClosePrinter(tctx, b, &handle);
6148 return true;
6152 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6153 struct dcerpc_pipe *p,
6154 const char *name,
6155 const char *environment)
6157 struct policy_handle handle;
6158 bool ret = true;
6159 struct dcerpc_binding_handle *b = p->binding_handle;
6161 if (!test_openprinter(tctx, b, name)) {
6162 return false;
6165 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6166 return false;
6169 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6170 ret = false;
6173 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6174 ret = false;
6177 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6178 ret = false;
6181 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6182 ret = false;
6185 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6186 ret = false;
6189 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6190 ret = false;
6193 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6194 ret = false;
6197 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6198 ret = false;
6201 if (!test_printer_all_keys(tctx, b, &handle)) {
6202 ret = false;
6205 if (!test_PausePrinter(tctx, b, &handle)) {
6206 ret = false;
6209 if (!test_DoPrintTest(tctx, b, &handle)) {
6210 ret = false;
6213 if (!test_ResumePrinter(tctx, b, &handle)) {
6214 ret = false;
6217 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6218 ret = false;
6221 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6222 ret = false;
6225 if (!torture_setting_bool(tctx, "samba3", false)) {
6226 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6227 ret = false;
6231 if (!test_ClosePrinter(tctx, b, &handle)) {
6232 ret = false;
6235 return ret;
6238 static bool test_EnumPrinters_old(struct torture_context *tctx,
6239 void *private_data)
6241 struct test_spoolss_context *ctx =
6242 talloc_get_type_abort(private_data, struct test_spoolss_context);
6243 struct spoolss_EnumPrinters r;
6244 NTSTATUS status;
6245 uint16_t levels[] = {1, 2, 4, 5};
6246 int i;
6247 bool ret = true;
6248 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6249 struct dcerpc_binding_handle *b = p->binding_handle;
6251 for (i=0;i<ARRAY_SIZE(levels);i++) {
6252 union spoolss_PrinterInfo *info;
6253 int j;
6254 uint32_t needed;
6255 uint32_t count;
6257 r.in.flags = PRINTER_ENUM_LOCAL;
6258 r.in.server = "";
6259 r.in.level = levels[i];
6260 r.in.buffer = NULL;
6261 r.in.offered = 0;
6262 r.out.needed = &needed;
6263 r.out.count = &count;
6264 r.out.info = &info;
6266 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6268 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6269 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6271 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6272 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6273 r.in.buffer = &blob;
6274 r.in.offered = needed;
6275 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6278 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6280 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6282 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6284 if (!info) {
6285 torture_comment(tctx, "No printers returned\n");
6286 return true;
6289 for (j=0;j<count;j++) {
6290 if (r.in.level == 1) {
6291 char *unc = talloc_strdup(tctx, info[j].info1.name);
6292 char *slash, *name, *full_name;
6293 name = unc;
6294 if (unc[0] == '\\' && unc[1] == '\\') {
6295 unc +=2;
6297 slash = strchr(unc, '\\');
6298 if (slash) {
6299 slash++;
6300 name = slash;
6302 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6303 dcerpc_server_name(p), name);
6304 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6305 ret = false;
6307 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6308 ret = false;
6310 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6311 ret = false;
6313 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6314 ret = false;
6320 return ret;
6323 static bool test_EnumPrinters_level(struct torture_context *tctx,
6324 struct dcerpc_binding_handle *b,
6325 uint32_t flags,
6326 const char *servername,
6327 uint32_t level,
6328 uint32_t *count_p,
6329 union spoolss_PrinterInfo **info_p)
6331 struct spoolss_EnumPrinters r;
6332 union spoolss_PrinterInfo *info;
6333 uint32_t needed;
6334 uint32_t count;
6336 r.in.flags = flags;
6337 r.in.server = servername;
6338 r.in.level = level;
6339 r.in.buffer = NULL;
6340 r.in.offered = 0;
6341 r.out.needed = &needed;
6342 r.out.count = &count;
6343 r.out.info = &info;
6345 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6346 r.in.server, r.in.level);
6348 torture_assert_ntstatus_ok(tctx,
6349 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6350 "EnumPrinters failed");
6351 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6352 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6353 r.in.buffer = &blob;
6354 r.in.offered = needed;
6355 torture_assert_ntstatus_ok(tctx,
6356 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6357 "EnumPrinters failed");
6360 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6362 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6364 if (count_p) {
6365 *count_p = count;
6367 if (info_p) {
6368 *info_p = info;
6371 return true;
6374 static const char *get_short_printername(struct torture_context *tctx,
6375 const char *name)
6377 const char *short_name;
6379 if (name[0] == '\\' && name[1] == '\\') {
6380 name += 2;
6381 short_name = strchr(name, '\\');
6382 if (short_name) {
6383 return talloc_strdup(tctx, short_name+1);
6387 return name;
6390 static const char *get_full_printername(struct torture_context *tctx,
6391 const char *name)
6393 const char *full_name = talloc_strdup(tctx, name);
6394 char *p;
6396 if (name && name[0] == '\\' && name[1] == '\\') {
6397 name += 2;
6398 p = strchr(name, '\\');
6399 if (p) {
6400 return full_name;
6404 return NULL;
6407 static bool test_OnePrinter_servername(struct torture_context *tctx,
6408 struct dcerpc_pipe *p,
6409 struct dcerpc_binding_handle *b,
6410 const char *servername,
6411 const char *printername)
6413 union spoolss_PrinterInfo info;
6414 const char *short_name = get_short_printername(tctx, printername);
6415 const char *full_name = get_full_printername(tctx, printername);
6417 if (short_name) {
6418 struct policy_handle handle;
6419 torture_assert(tctx,
6420 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6421 "failed to open printer");
6423 torture_assert(tctx,
6424 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6425 "failed to get printer info");
6427 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6428 "unexpected servername");
6429 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6430 "unexpected printername");
6432 if (info.info2.devmode) {
6433 const char *expected_devicename;
6434 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6435 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6436 "unexpected devicemode devicename");
6439 torture_assert(tctx,
6440 test_ClosePrinter(tctx, b, &handle),
6441 "failed to close printer");
6444 if (full_name) {
6445 struct policy_handle handle;
6447 torture_assert(tctx,
6448 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6449 "failed to open printer");
6451 torture_assert(tctx,
6452 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6453 "failed to get printer info");
6455 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6456 "unexpected servername");
6457 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6458 "unexpected printername");
6460 if (info.info2.devmode) {
6461 const char *expected_devicename;
6462 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6463 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6464 "unexpected devicemode devicename");
6467 torture_assert(tctx,
6468 test_ClosePrinter(tctx, b, &handle),
6469 "failed to close printer");
6472 return true;
6475 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6476 void *private_data)
6478 struct test_spoolss_context *ctx =
6479 talloc_get_type_abort(private_data, struct test_spoolss_context);
6480 int i;
6481 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6482 struct dcerpc_binding_handle *b = p->binding_handle;
6483 uint32_t count;
6484 union spoolss_PrinterInfo *info;
6485 const char *servername;
6486 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6488 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6490 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6492 torture_assert(tctx,
6493 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6494 "failed to enumerate printers");
6496 for (i=0; i < count; i++) {
6498 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6499 "unexpected servername");
6501 torture_assert(tctx,
6502 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6503 "failed to check printer");
6506 servername = "";
6508 torture_assert(tctx,
6509 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6510 "failed to enumerate printers");
6512 for (i=0; i < count; i++) {
6514 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6515 "unexpected servername");
6517 torture_assert(tctx,
6518 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6519 "failed to check printer");
6523 return true;
6527 static bool test_GetPrinterDriver(struct torture_context *tctx,
6528 struct dcerpc_binding_handle *b,
6529 struct policy_handle *handle,
6530 const char *driver_name)
6532 struct spoolss_GetPrinterDriver r;
6533 uint32_t needed;
6535 r.in.handle = handle;
6536 r.in.architecture = "W32X86";
6537 r.in.level = 1;
6538 r.in.buffer = NULL;
6539 r.in.offered = 0;
6540 r.out.needed = &needed;
6542 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6544 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6545 "failed to call GetPrinterDriver");
6546 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6547 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6548 r.in.buffer = &blob;
6549 r.in.offered = needed;
6550 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6551 "failed to call GetPrinterDriver");
6554 torture_assert_werr_ok(tctx, r.out.result,
6555 "failed to call GetPrinterDriver");
6557 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6559 return true;
6562 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6563 struct dcerpc_binding_handle *b,
6564 struct policy_handle *handle,
6565 const char *driver_name,
6566 const char *architecture,
6567 uint32_t level,
6568 uint32_t client_major_version,
6569 uint32_t client_minor_version,
6570 union spoolss_DriverInfo *info_p,
6571 WERROR *result_p)
6574 struct spoolss_GetPrinterDriver2 r;
6575 uint32_t needed;
6576 uint32_t server_major_version;
6577 uint32_t server_minor_version;
6579 r.in.handle = handle;
6580 r.in.architecture = architecture;
6581 r.in.client_major_version = client_major_version;
6582 r.in.client_minor_version = client_minor_version;
6583 r.in.buffer = NULL;
6584 r.in.offered = 0;
6585 r.in.level = level;
6586 r.out.needed = &needed;
6587 r.out.server_major_version = &server_major_version;
6588 r.out.server_minor_version = &server_minor_version;
6590 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6591 driver_name, r.in.level);
6593 torture_assert_ntstatus_ok(tctx,
6594 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6595 "failed to call GetPrinterDriver2");
6596 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6597 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6598 r.in.buffer = &blob;
6599 r.in.offered = needed;
6600 torture_assert_ntstatus_ok(tctx,
6601 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6602 "failed to call GetPrinterDriver2");
6605 if (result_p) {
6606 *result_p = r.out.result;
6609 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6610 switch (r.in.level) {
6611 case 101:
6612 case 8:
6613 torture_comment(tctx,
6614 "level %d not implemented, not considering as an error\n",
6615 r.in.level);
6616 return true;
6617 default:
6618 break;
6622 torture_assert_werr_ok(tctx, r.out.result,
6623 "failed to call GetPrinterDriver2");
6625 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6627 if (info_p) {
6628 *info_p = *r.out.info;
6631 return true;
6634 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6635 struct dcerpc_binding_handle *b,
6636 struct policy_handle *handle,
6637 const char *driver_name,
6638 const char *architecture)
6640 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6641 int i;
6644 for (i=0;i<ARRAY_SIZE(levels);i++) {
6646 torture_assert(tctx,
6647 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6648 "");
6651 return true;
6654 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6655 void *private_data)
6657 struct test_spoolss_context *ctx =
6658 talloc_get_type_abort(private_data, struct test_spoolss_context);
6659 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6660 int i;
6661 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6662 struct dcerpc_binding_handle *b = p->binding_handle;
6663 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6665 for (i=0;i<ARRAY_SIZE(levels);i++) {
6667 uint32_t count;
6668 union spoolss_DriverInfo *info;
6670 torture_assert(tctx,
6671 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6672 "failed to enumerate drivers");
6674 if (!info) {
6675 torture_comment(tctx, "No printer drivers returned\n");
6676 break;
6680 return true;
6683 static bool test_DeletePrinter(struct torture_context *tctx,
6684 struct dcerpc_binding_handle *b,
6685 struct policy_handle *handle)
6687 struct spoolss_DeletePrinter r;
6689 torture_comment(tctx, "Testing DeletePrinter\n");
6691 r.in.handle = handle;
6693 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6694 "failed to delete printer");
6695 torture_assert_werr_ok(tctx, r.out.result,
6696 "failed to delete printer");
6698 return true;
6701 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6702 struct dcerpc_binding_handle *b,
6703 uint32_t flags,
6704 uint32_t level,
6705 const char *name,
6706 bool *found)
6708 struct spoolss_EnumPrinters e;
6709 uint32_t count;
6710 union spoolss_PrinterInfo *info;
6711 uint32_t needed;
6712 int i;
6714 *found = false;
6716 e.in.flags = flags;
6717 e.in.server = NULL;
6718 e.in.level = level;
6719 e.in.buffer = NULL;
6720 e.in.offered = 0;
6721 e.out.count = &count;
6722 e.out.info = &info;
6723 e.out.needed = &needed;
6725 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6726 "failed to enum printers");
6728 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6729 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6730 e.in.buffer = &blob;
6731 e.in.offered = needed;
6733 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6734 "failed to enum printers");
6737 torture_assert_werr_ok(tctx, e.out.result,
6738 "failed to enum printers");
6740 for (i=0; i < count; i++) {
6742 const char *current = NULL;
6743 const char *q;
6745 switch (level) {
6746 case 1:
6747 current = info[i].info1.name;
6748 break;
6751 if (strequal(current, name)) {
6752 *found = true;
6753 break;
6756 q = strrchr(current, '\\');
6757 if (q) {
6758 if (!e.in.server) {
6759 torture_warning(tctx,
6760 "server returns printername %s incl. servername although we did not set servername", current);
6762 q++;
6763 if (strequal(q, name)) {
6764 *found = true;
6765 break;
6770 return true;
6773 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6774 struct dcerpc_pipe *p,
6775 const char *printername,
6776 bool ex)
6778 WERROR result;
6779 struct spoolss_AddPrinter r;
6780 struct spoolss_AddPrinterEx rex;
6781 struct spoolss_SetPrinterInfoCtr info_ctr;
6782 struct spoolss_SetPrinterInfo1 info1;
6783 struct spoolss_DevmodeContainer devmode_ctr;
6784 struct sec_desc_buf secdesc_ctr;
6785 struct spoolss_UserLevelCtr userlevel_ctr;
6786 struct policy_handle handle;
6787 bool found = false;
6788 struct dcerpc_binding_handle *b = p->binding_handle;
6790 ZERO_STRUCT(devmode_ctr);
6791 ZERO_STRUCT(secdesc_ctr);
6792 ZERO_STRUCT(userlevel_ctr);
6793 ZERO_STRUCT(info1);
6795 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6796 ex ? "Ex":"", printername);
6798 /* try to add printer to wellknown printer list (level 1) */
6800 userlevel_ctr.level = 1;
6802 info_ctr.info.info1 = &info1;
6803 info_ctr.level = 1;
6805 rex.in.server = NULL;
6806 rex.in.info_ctr = &info_ctr;
6807 rex.in.devmode_ctr = &devmode_ctr;
6808 rex.in.secdesc_ctr = &secdesc_ctr;
6809 rex.in.userlevel_ctr = &userlevel_ctr;
6810 rex.out.handle = &handle;
6812 r.in.server = NULL;
6813 r.in.info_ctr = &info_ctr;
6814 r.in.devmode_ctr = &devmode_ctr;
6815 r.in.secdesc_ctr = &secdesc_ctr;
6816 r.out.handle = &handle;
6818 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6819 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6820 "failed to add printer");
6821 result = ex ? rex.out.result : r.out.result;
6822 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6823 "unexpected result code");
6825 info1.name = printername;
6826 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6828 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6829 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6830 "failed to add printer");
6831 result = ex ? rex.out.result : r.out.result;
6832 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6833 "unexpected result code");
6835 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6836 better do a real check to see the printer is really there */
6838 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6839 PRINTER_ENUM_NETWORK, 1,
6840 printername,
6841 &found),
6842 "failed to enum printers");
6844 torture_assert(tctx, found, "failed to find newly added printer");
6846 info1.flags = 0;
6848 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6849 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6850 "failed to add printer");
6851 result = ex ? rex.out.result : r.out.result;
6852 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6853 "unexpected result code");
6855 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6856 better do a real check to see the printer has really been removed
6857 from the well known printer list */
6859 found = false;
6861 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6862 PRINTER_ENUM_NETWORK, 1,
6863 printername,
6864 &found),
6865 "failed to enum printers");
6866 #if 0
6867 torture_assert(tctx, !found, "printer still in well known printer list");
6868 #endif
6869 return true;
6872 static bool test_AddPrinter_normal(struct torture_context *tctx,
6873 struct dcerpc_pipe *p,
6874 struct policy_handle *handle_p,
6875 const char *printername,
6876 const char *drivername,
6877 const char *portname,
6878 struct spoolss_DeviceMode *devmode,
6879 bool ex)
6881 WERROR result;
6882 struct spoolss_AddPrinter r;
6883 struct spoolss_AddPrinterEx rex;
6884 struct spoolss_SetPrinterInfoCtr info_ctr;
6885 struct spoolss_SetPrinterInfo2 info2;
6886 struct spoolss_DevmodeContainer devmode_ctr;
6887 struct sec_desc_buf secdesc_ctr;
6888 struct spoolss_UserLevelCtr userlevel_ctr;
6889 struct policy_handle handle;
6890 bool found = false;
6891 bool existing_printer_deleted = false;
6892 struct dcerpc_binding_handle *b = p->binding_handle;
6894 ZERO_STRUCT(devmode_ctr);
6895 ZERO_STRUCT(secdesc_ctr);
6896 ZERO_STRUCT(userlevel_ctr);
6898 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6899 ex ? "Ex":"", printername);
6901 devmode_ctr.devmode = devmode;
6903 userlevel_ctr.level = 1;
6905 rex.in.server = NULL;
6906 rex.in.info_ctr = &info_ctr;
6907 rex.in.devmode_ctr = &devmode_ctr;
6908 rex.in.secdesc_ctr = &secdesc_ctr;
6909 rex.in.userlevel_ctr = &userlevel_ctr;
6910 rex.out.handle = &handle;
6912 r.in.server = NULL;
6913 r.in.info_ctr = &info_ctr;
6914 r.in.devmode_ctr = &devmode_ctr;
6915 r.in.secdesc_ctr = &secdesc_ctr;
6916 r.out.handle = &handle;
6918 again:
6920 /* try to add printer to printer list (level 2) */
6922 ZERO_STRUCT(info2);
6924 info_ctr.info.info2 = &info2;
6925 info_ctr.level = 2;
6927 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6928 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6929 "failed to add printer");
6930 result = ex ? rex.out.result : r.out.result;
6931 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6932 "unexpected result code");
6934 info2.printername = printername;
6936 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6937 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6938 "failed to add printer");
6939 result = ex ? rex.out.result : r.out.result;
6941 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6942 struct policy_handle printer_handle;
6944 if (existing_printer_deleted) {
6945 torture_fail(tctx, "already deleted printer still existing?");
6948 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6949 "failed to open printer handle");
6951 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6952 "failed to delete printer");
6954 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6955 "failed to close server handle");
6957 existing_printer_deleted = true;
6959 goto again;
6962 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6963 "unexpected result code");
6965 info2.portname = portname;
6967 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6968 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6969 "failed to add printer");
6970 result = ex ? rex.out.result : r.out.result;
6971 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6972 "unexpected result code");
6974 info2.drivername = drivername;
6976 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6977 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6978 "failed to add printer");
6979 result = ex ? rex.out.result : r.out.result;
6981 /* w2k8r2 allows to add printer w/o defining printprocessor */
6983 if (!W_ERROR_IS_OK(result)) {
6984 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6985 "unexpected result code");
6987 info2.printprocessor = "winprint";
6989 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6990 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6991 "failed to add printer");
6992 result = ex ? rex.out.result : r.out.result;
6993 torture_assert_werr_ok(tctx, result,
6994 "failed to add printer");
6997 *handle_p = handle;
6999 /* we are paranoid, really check if the printer is there now */
7001 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7002 PRINTER_ENUM_LOCAL, 1,
7003 printername,
7004 &found),
7005 "failed to enum printers");
7006 torture_assert(tctx, found, "failed to find newly added printer");
7008 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7009 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7010 "failed to add printer");
7011 result = ex ? rex.out.result : r.out.result;
7012 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7013 "unexpected result code");
7015 return true;
7018 static bool test_printer_info(struct torture_context *tctx,
7019 void *private_data)
7021 struct torture_printer_context *t =
7022 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7023 struct dcerpc_pipe *p = t->spoolss_pipe;
7024 struct dcerpc_binding_handle *b = p->binding_handle;
7026 bool ret = true;
7028 if (torture_setting_bool(tctx, "samba3", false)) {
7029 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7032 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7033 ret = false;
7036 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7037 ret = false;
7040 return ret;
7043 static bool test_EnumPrinterKey(struct torture_context *tctx,
7044 struct dcerpc_binding_handle *b,
7045 struct policy_handle *handle,
7046 const char *key_name,
7047 const char ***array)
7049 struct spoolss_EnumPrinterKey r;
7050 uint32_t needed = 0;
7051 union spoolss_KeyNames key_buffer;
7052 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7053 uint32_t _ndr_size;
7054 int i;
7056 r.in.handle = handle;
7057 r.in.key_name = key_name;
7058 r.out.key_buffer = &key_buffer;
7059 r.out.needed = &needed;
7060 r.out._ndr_size = &_ndr_size;
7062 for (i=0; i < ARRAY_SIZE(offered); i++) {
7064 if (offered[i] < 0 && needed) {
7065 if (needed <= 4) {
7066 continue;
7068 r.in.offered = needed + offered[i];
7069 } else {
7070 r.in.offered = offered[i];
7073 ZERO_STRUCT(key_buffer);
7075 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7077 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7078 "failed to call EnumPrinterKey");
7079 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7081 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7082 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7083 _ndr_size, r.in.offered/2));
7085 r.in.offered = needed;
7086 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7087 "failed to call EnumPrinterKey");
7090 if (offered[i] > 0) {
7091 torture_assert_werr_ok(tctx, r.out.result,
7092 "failed to call EnumPrinterKey");
7095 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7096 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7097 _ndr_size, r.in.offered/2));
7099 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7100 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7102 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7103 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7105 if (key_buffer.string_array) {
7106 uint32_t calc_needed = 0;
7107 int s;
7108 for (s=0; key_buffer.string_array[s]; s++) {
7109 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7111 if (!key_buffer.string_array[0]) {
7112 calc_needed += 2;
7114 calc_needed += 2;
7116 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7117 "EnumPrinterKey unexpected size");
7121 if (array) {
7122 *array = key_buffer.string_array;
7125 return true;
7128 bool test_printer_all_keys(struct torture_context *tctx,
7129 struct dcerpc_binding_handle *b,
7130 struct policy_handle *handle)
7132 const char **key_array = NULL;
7133 int i;
7135 torture_comment(tctx, "Testing Printer Keys\n");
7137 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7138 "failed to call test_EnumPrinterKey");
7140 for (i=0; key_array && key_array[i]; i++) {
7141 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7142 "failed to call test_EnumPrinterKey");
7144 for (i=0; key_array && key_array[i]; i++) {
7145 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7146 "failed to call test_EnumPrinterDataEx");
7149 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7151 return true;
7154 static bool test_openprinter_wrap(struct torture_context *tctx,
7155 void *private_data)
7157 struct torture_printer_context *t =
7158 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7159 struct dcerpc_pipe *p = t->spoolss_pipe;
7160 struct dcerpc_binding_handle *b = p->binding_handle;
7161 const char *printername = t->info2.printername;
7163 return test_openprinter(tctx, b, printername);
7166 static bool test_csetprinter(struct torture_context *tctx,
7167 void *private_data)
7169 struct torture_printer_context *t =
7170 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7171 struct dcerpc_pipe *p = t->spoolss_pipe;
7173 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7174 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7175 const char *portname = t->info2.portname;
7177 union spoolss_PrinterInfo info;
7178 struct policy_handle new_handle, new_handle2;
7179 struct dcerpc_binding_handle *b = p->binding_handle;
7181 torture_comment(tctx, "Testing c_setprinter\n");
7183 torture_assert(tctx,
7184 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7185 "failed to get level 0 printer info");
7186 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7187 info.info0.c_setprinter);
7189 /* check if c_setprinter on 1st handle increases after a printer has
7190 * been added */
7192 torture_assert(tctx,
7193 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7194 "failed to add new printer");
7195 torture_assert(tctx,
7196 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7197 "failed to get level 0 printer info");
7198 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7199 info.info0.c_setprinter);
7201 /* check if c_setprinter on new handle increases after a printer has
7202 * been added */
7204 torture_assert(tctx,
7205 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7206 "failed to get level 0 printer info");
7207 torture_comment(tctx, "csetprinter on created handle: %d\n",
7208 info.info0.c_setprinter);
7210 /* open the new printer and check if c_setprinter increases */
7212 torture_assert(tctx,
7213 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7214 "failed to open created printer");
7215 torture_assert(tctx,
7216 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7217 "failed to get level 0 printer info");
7218 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7219 info.info0.c_setprinter);
7221 /* cleanup */
7223 torture_assert(tctx,
7224 test_ClosePrinter(tctx, b, &new_handle2),
7225 "failed to close printer");
7226 torture_assert(tctx,
7227 test_DeletePrinter(tctx, b, &new_handle),
7228 "failed to delete new printer");
7230 return true;
7233 static bool compose_local_driver_directory(struct torture_context *tctx,
7234 const char *environment,
7235 const char *local_dir,
7236 const char **path)
7238 char *p;
7240 p = strrchr(local_dir, '/');
7241 if (!p) {
7242 return NULL;
7244 p++;
7246 if (strequal(environment, "Windows x64")) {
7247 if (!strequal(p, "x64")) {
7248 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7250 } else if (strequal(environment, "Windows NT x86")) {
7251 if (!strequal(p, "i386")) {
7252 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7254 } else {
7255 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7258 return true;
7261 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7262 const char *devicename)
7264 struct spoolss_DeviceMode *r;
7266 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7267 if (r == NULL) {
7268 return NULL;
7271 r->devicename = talloc_strdup(r, devicename);
7272 r->specversion = DMSPEC_NT4_AND_ABOVE;
7273 r->driverversion = 0x0600;
7274 r->size = 0x00dc;
7275 r->__driverextra_length = 0;
7276 r->fields = DEVMODE_FORMNAME |
7277 DEVMODE_TTOPTION |
7278 DEVMODE_PRINTQUALITY |
7279 DEVMODE_DEFAULTSOURCE |
7280 DEVMODE_COPIES |
7281 DEVMODE_SCALE |
7282 DEVMODE_PAPERSIZE |
7283 DEVMODE_ORIENTATION;
7284 r->orientation = DMORIENT_PORTRAIT;
7285 r->papersize = DMPAPER_LETTER;
7286 r->paperlength = 0;
7287 r->paperwidth = 0;
7288 r->scale = 100;
7289 r->copies = 55;
7290 r->defaultsource = DMBIN_FORMSOURCE;
7291 r->printquality = DMRES_HIGH;
7292 r->color = DMRES_MONOCHROME;
7293 r->duplex = DMDUP_SIMPLEX;
7294 r->yresolution = 0;
7295 r->ttoption = DMTT_SUBDEV;
7296 r->collate = DMCOLLATE_FALSE;
7297 r->formname = talloc_strdup(r, "Letter");
7299 return r;
7302 static bool test_architecture_buffer(struct torture_context *tctx,
7303 void *private_data)
7305 struct test_spoolss_context *ctx =
7306 talloc_get_type_abort(private_data, struct test_spoolss_context);
7308 struct spoolss_OpenPrinterEx r;
7309 struct spoolss_UserLevel1 u1;
7310 struct policy_handle handle;
7311 uint32_t architectures[] = {
7312 PROCESSOR_ARCHITECTURE_INTEL,
7313 PROCESSOR_ARCHITECTURE_IA64,
7314 PROCESSOR_ARCHITECTURE_AMD64
7316 uint32_t needed[3];
7317 int i;
7318 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7319 struct dcerpc_binding_handle *b = p->binding_handle;
7321 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7323 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7325 u1.size = 0;
7326 u1.client = NULL;
7327 u1.user = NULL;
7328 u1.build = 0;
7329 u1.major = 3;
7330 u1.minor = 0;
7331 u1.processor = architectures[i];
7333 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7334 r.in.datatype = NULL;
7335 r.in.devmode_ctr.devmode= NULL;
7336 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7337 r.in.userlevel_ctr.level = 1;
7338 r.in.userlevel_ctr.user_info.level1 = &u1;
7339 r.out.handle = &handle;
7341 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7342 torture_assert_werr_ok(tctx, r.out.result, "");
7345 struct spoolss_EnumPrinters e;
7346 uint32_t count;
7347 union spoolss_PrinterInfo *info;
7349 e.in.flags = PRINTER_ENUM_LOCAL;
7350 e.in.server = NULL;
7351 e.in.level = 2;
7352 e.in.buffer = NULL;
7353 e.in.offered = 0;
7354 e.out.count = &count;
7355 e.out.info = &info;
7356 e.out.needed = &needed[i];
7358 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7359 #if 0
7360 torture_comment(tctx, "needed was %d\n", needed[i]);
7361 #endif
7364 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7367 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7368 if (needed[i-1] != needed[i]) {
7369 torture_fail(tctx,
7370 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7371 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7375 return true;
7378 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7379 void *private_data)
7381 struct test_spoolss_context *ctx =
7382 talloc_get_type_abort(private_data, struct test_spoolss_context);
7383 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7384 struct dcerpc_binding_handle *b = p->binding_handle;
7386 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7389 static bool test_PrintServer_Forms(struct torture_context *tctx,
7390 void *private_data)
7392 struct test_spoolss_context *ctx =
7393 talloc_get_type_abort(private_data, struct test_spoolss_context);
7394 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7395 struct dcerpc_binding_handle *b = p->binding_handle;
7397 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7400 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7401 void *private_data)
7403 struct test_spoolss_context *ctx =
7404 talloc_get_type_abort(private_data, struct test_spoolss_context);
7405 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7406 struct dcerpc_binding_handle *b = p->binding_handle;
7408 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7411 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7413 NTSTATUS status;
7415 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7417 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7419 torture_assert(tctx,
7420 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7421 "failed to open printserver");
7422 torture_assert(tctx,
7423 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7424 "failed to get environment");
7426 return true;
7429 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7431 struct test_spoolss_context *t;
7433 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7435 return torture_rpc_spoolss_setup_common(tctx, t);
7438 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7440 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7442 return true;
7445 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7447 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7448 bool ret;
7450 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7451 talloc_free(t);
7453 return ret;
7456 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7458 struct dcerpc_pipe *p;
7459 struct dcerpc_binding_handle *b;
7460 const char *server_name_slash;
7461 const char *driver_name;
7462 const char *printer_name;
7463 const char *port_name;
7465 torture_assert_ntstatus_ok(tctx,
7466 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7467 "Error connecting to server");
7469 p = t->spoolss_pipe;
7470 b = p->binding_handle;
7471 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7473 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7474 t->driver.info8.driver_name = TORTURE_DRIVER;
7475 t->driver.info8.driver_path = "pscript5.dll";
7476 t->driver.info8.data_file = "cups6.ppd";
7477 t->driver.info8.config_file = "ps5ui.dll";
7478 t->driver.info8.help_file = "pscript.hlp";
7479 t->driver.info8.default_datatype = "RAW";
7480 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7481 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7482 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7483 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7484 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7485 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7486 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7487 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7488 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7489 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7491 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7493 t->info2.drivername = "Microsoft XPS Document Writer";
7494 t->info2.portname = "LPT1:";
7496 printer_name = t->info2.printername;
7497 port_name = t->info2.portname;
7499 torture_assert(tctx,
7500 fillup_printserver_info(tctx, p, &t->driver),
7501 "failed to fillup printserver info");
7503 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7505 torture_assert(tctx,
7506 compose_local_driver_directory(tctx, t->driver.remote.environment,
7507 t->driver.local.driver_directory,
7508 &t->driver.local.driver_directory),
7509 "failed to compose local driver directory");
7511 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7512 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7513 t->info2.drivername, t->driver.remote.environment);
7514 t->have_driver = true;
7515 goto try_add;
7518 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7519 t->info2.drivername, t->driver.remote.environment);
7520 torture_comment(tctx, "trying to upload own driver\n");
7522 if (!directory_exist(t->driver.local.driver_directory)) {
7523 torture_warning(tctx, "no local driver is available!");
7524 t->have_driver = false;
7525 goto try_add;
7528 torture_assert(tctx,
7529 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7530 "failed to upload printer driver");
7532 torture_assert(tctx,
7533 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7534 "failed to add driver");
7536 t->added_driver = true;
7537 t->have_driver = true;
7539 try_add:
7540 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7542 if (t->wellknown) {
7543 torture_assert(tctx,
7544 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7545 "failed to add wellknown printer");
7546 } else {
7547 torture_assert(tctx,
7548 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7549 "failed to add printer");
7552 return true;
7555 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7557 struct torture_printer_context *t;
7559 *data = t = talloc_zero(tctx, struct torture_printer_context);
7561 t->ex = false;
7562 t->wellknown = false;
7563 t->info2.printername = TORTURE_PRINTER;
7564 t->devmode = NULL;
7566 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7569 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7571 struct torture_printer_context *t;
7573 *data = t = talloc_zero(tctx, struct torture_printer_context);
7575 t->ex = true;
7576 t->wellknown = false;
7577 t->info2.printername = TORTURE_PRINTER_EX;
7578 t->devmode = NULL;
7580 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7583 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7585 struct torture_printer_context *t;
7587 *data = t = talloc_zero(tctx, struct torture_printer_context);
7589 t->ex = false;
7590 t->wellknown = true;
7591 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7592 t->devmode = NULL;
7594 /* FIXME */
7595 if (t->wellknown) {
7596 torture_skip(tctx, "skipping AddPrinter level 1");
7599 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7602 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7604 struct torture_printer_context *t;
7606 *data = t = talloc_zero(tctx, struct torture_printer_context);
7608 t->ex = true;
7609 t->wellknown = true;
7610 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7611 t->devmode = NULL;
7613 /* FIXME */
7614 if (t->wellknown) {
7615 torture_skip(tctx, "skipping AddPrinterEx level 1");
7618 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7621 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7623 struct torture_printer_context *t;
7625 *data = t = talloc_zero(tctx, struct torture_printer_context);
7627 t->ex = true;
7628 t->wellknown = false;
7629 t->info2.printername = TORTURE_PRINTER_EX;
7630 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7632 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7635 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7637 bool found = false;
7638 struct dcerpc_pipe *p = t->spoolss_pipe;
7639 struct dcerpc_binding_handle *b;
7640 const char *printer_name = t->info2.printername;
7642 if (t->added_driver) {
7643 torture_assert(tctx,
7644 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7645 "failed to remove printer driver");
7648 if (p && !t->wellknown) {
7649 b = p->binding_handle;
7651 torture_assert(tctx,
7652 test_DeletePrinter(tctx, b, &t->handle),
7653 "failed to delete printer");
7655 torture_assert(tctx,
7656 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7657 printer_name, &found),
7658 "failed to enumerate printers");
7660 torture_assert(tctx, !found, "deleted printer still there");
7663 return true;
7666 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7668 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7669 bool ret;
7671 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7672 talloc_free(t);
7674 return ret;
7677 static bool test_print_test(struct torture_context *tctx,
7678 void *private_data)
7680 struct torture_printer_context *t =
7681 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7682 struct dcerpc_pipe *p = t->spoolss_pipe;
7683 struct dcerpc_binding_handle *b = p->binding_handle;
7685 torture_assert(tctx,
7686 test_PausePrinter(tctx, b, &t->handle),
7687 "failed to pause printer");
7689 torture_assert(tctx,
7690 test_DoPrintTest(tctx, b, &t->handle),
7691 "failed to do print test");
7693 torture_assert(tctx,
7694 test_ResumePrinter(tctx, b, &t->handle),
7695 "failed to resume printer");
7697 return true;
7700 static bool test_print_test_extended(struct torture_context *tctx,
7701 void *private_data)
7703 struct torture_printer_context *t =
7704 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7705 struct dcerpc_pipe *p = t->spoolss_pipe;
7706 struct dcerpc_binding_handle *b = p->binding_handle;
7707 bool ret = true;
7709 torture_assert(tctx,
7710 test_PausePrinter(tctx, b, &t->handle),
7711 "failed to pause printer");
7713 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7714 if (ret == false) {
7715 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7716 if (torture_setting_bool(tctx, "samba3", false)) {
7717 torture_comment(tctx, "non-critical for samba3\n");
7718 ret = true;
7719 tctx->last_result = TORTURE_SKIP;
7723 torture_assert(tctx,
7724 test_ResumePrinter(tctx, b, &t->handle),
7725 "failed to resume printer");
7727 return ret;
7730 /* use smbd file IO to spool a print job */
7731 static bool test_print_test_smbd(struct torture_context *tctx,
7732 void *private_data)
7734 struct torture_printer_context *t =
7735 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7736 struct dcerpc_pipe *p = t->spoolss_pipe;
7737 struct dcerpc_binding_handle *b = p->binding_handle;
7738 NTSTATUS status;
7739 uint32_t count;
7740 union spoolss_JobInfo *info = NULL;
7741 int i;
7743 struct smb2_tree *tree;
7744 struct smb2_handle job_h;
7745 struct cli_credentials *credentials = cmdline_credentials;
7746 struct smbcli_options options;
7747 TALLOC_CTX *mem_ctx = talloc_new(tctx);
7749 * Do not test against the dynamically added printers, printing via
7750 * smbd means that a different spoolss process may handle the
7751 * OpenPrinter request to the one that handled the AddPrinter request.
7752 * This currently leads to an ugly race condition where one process
7753 * sees the new printer and one doesn't.
7755 const char *share = TORTURE_PRINTER_STATIC1;
7757 torture_comment(tctx, "Testing smbd job spooling\n");
7758 lpcfg_smbcli_options(tctx->lp_ctx, &options);
7760 status = smb2_connect_ext(mem_ctx,
7761 torture_setting_string(tctx, "host", NULL),
7762 lpcfg_smb_ports(tctx->lp_ctx),
7763 share,
7764 lpcfg_resolve_context(tctx->lp_ctx),
7765 credentials,
7767 &tree,
7768 tctx->ev,
7769 &options,
7770 lpcfg_socket_options(tctx->lp_ctx),
7771 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
7772 if (!NT_STATUS_IS_OK(status)) {
7773 printf("Failed to connect to SMB2 printer %s - %s\n",
7774 share, nt_errstr(status));
7775 return false;
7778 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
7779 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
7781 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
7782 sizeof("exciting print job data"));
7783 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
7785 /* check back end spoolss job was created */
7786 torture_assert(tctx,
7787 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
7788 "EnumJobs level 1 failed");
7790 for (i = 0; i < count; i++) {
7791 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
7792 break;
7795 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
7797 status = smb2_util_close(tree, job_h);
7798 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
7800 /* disconnect from printer share */
7801 talloc_free(mem_ctx);
7803 return true;
7806 static bool test_printer_sd(struct torture_context *tctx,
7807 void *private_data)
7809 struct torture_printer_context *t =
7810 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7811 struct dcerpc_pipe *p = t->spoolss_pipe;
7812 struct dcerpc_binding_handle *b = p->binding_handle;
7814 torture_assert(tctx,
7815 test_PrinterInfo_SD(tctx, b, &t->handle),
7816 "failed to test security descriptors");
7818 return true;
7821 static bool test_printer_dm(struct torture_context *tctx,
7822 void *private_data)
7824 struct torture_printer_context *t =
7825 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7826 struct dcerpc_pipe *p = t->spoolss_pipe;
7828 torture_assert(tctx,
7829 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7830 "failed to test devicemodes");
7832 return true;
7835 static bool test_printer_info_winreg(struct torture_context *tctx,
7836 void *private_data)
7838 struct torture_printer_context *t =
7839 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7840 struct dcerpc_pipe *p = t->spoolss_pipe;
7842 torture_assert(tctx,
7843 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7844 "failed to test printer info winreg");
7846 return true;
7849 static bool test_printer_change_id(struct torture_context *tctx,
7850 void *private_data)
7852 struct torture_printer_context *t =
7853 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7854 struct dcerpc_pipe *p = t->spoolss_pipe;
7856 torture_assert(tctx,
7857 test_ChangeID(tctx, p, &t->handle),
7858 "failed to test change id");
7860 return true;
7863 static bool test_printer_keys(struct torture_context *tctx,
7864 void *private_data)
7866 struct torture_printer_context *t =
7867 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7868 struct dcerpc_pipe *p = t->spoolss_pipe;
7869 struct dcerpc_binding_handle *b = p->binding_handle;
7871 torture_assert(tctx,
7872 test_printer_all_keys(tctx, b, &t->handle),
7873 "failed to test printer keys");
7875 return true;
7878 static bool test_printer_data_consistency(struct torture_context *tctx,
7879 void *private_data)
7881 struct torture_printer_context *t =
7882 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7883 struct dcerpc_pipe *p = t->spoolss_pipe;
7885 torture_assert(tctx,
7886 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7887 "failed to test printer data consistency");
7889 return true;
7892 static bool test_printer_data_keys(struct torture_context *tctx,
7893 void *private_data)
7895 struct torture_printer_context *t =
7896 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7897 struct dcerpc_pipe *p = t->spoolss_pipe;
7899 torture_assert(tctx,
7900 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7901 "failed to test printer data keys");
7903 return true;
7906 static bool test_printer_data_values(struct torture_context *tctx,
7907 void *private_data)
7909 struct torture_printer_context *t =
7910 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7911 struct dcerpc_pipe *p = t->spoolss_pipe;
7913 torture_assert(tctx,
7914 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7915 "failed to test printer data values");
7917 return true;
7920 static bool test_printer_data_set(struct torture_context *tctx,
7921 void *private_data)
7923 struct torture_printer_context *t =
7924 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7925 struct dcerpc_pipe *p = t->spoolss_pipe;
7927 torture_assert(tctx,
7928 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7929 "failed to test printer data set");
7931 return true;
7934 static bool test_printer_data_winreg(struct torture_context *tctx,
7935 void *private_data)
7937 struct torture_printer_context *t =
7938 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7939 struct dcerpc_pipe *p = t->spoolss_pipe;
7941 torture_assert(tctx,
7942 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7943 "failed to test printer data winreg");
7945 return true;
7948 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7949 void *private_data)
7951 struct torture_printer_context *t =
7952 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7953 struct dcerpc_pipe *p = t->spoolss_pipe;
7955 torture_assert(tctx,
7956 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7957 "failed to test printer data winreg dsspooler");
7959 return true;
7962 static bool test_driver_info_winreg(struct torture_context *tctx,
7963 void *private_data)
7965 struct torture_printer_context *t =
7966 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7967 struct dcerpc_pipe *p = t->spoolss_pipe;
7968 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7970 if (!t->have_driver) {
7971 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7974 torture_assert(tctx,
7975 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7976 "failed to test driver info winreg");
7978 return true;
7981 void torture_tcase_printer(struct torture_tcase *tcase)
7983 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7984 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7985 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7986 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7987 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
7988 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7989 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7990 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7991 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7992 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7993 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7994 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7995 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7996 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7997 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7998 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7999 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8000 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8001 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8004 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8006 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8007 struct torture_tcase *tcase;
8009 tcase = torture_suite_add_tcase(suite, "addprinter");
8011 torture_tcase_set_fixture(tcase,
8012 torture_rpc_spoolss_printer_setup,
8013 torture_rpc_spoolss_printer_teardown);
8015 torture_tcase_printer(tcase);
8017 tcase = torture_suite_add_tcase(suite, "addprinterex");
8019 torture_tcase_set_fixture(tcase,
8020 torture_rpc_spoolss_printerex_setup,
8021 torture_rpc_spoolss_printer_teardown);
8023 torture_tcase_printer(tcase);
8025 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8027 torture_tcase_set_fixture(tcase,
8028 torture_rpc_spoolss_printerwkn_setup,
8029 torture_rpc_spoolss_printer_teardown);
8031 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8033 torture_tcase_set_fixture(tcase,
8034 torture_rpc_spoolss_printerexwkn_setup,
8035 torture_rpc_spoolss_printer_teardown);
8037 #if 0
8038 /* test is not correct */
8039 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8041 torture_tcase_set_fixture(tcase,
8042 torture_rpc_spoolss_printerdm_setup,
8043 torture_rpc_spoolss_printer_teardown);
8045 torture_tcase_printer(tcase);
8046 #endif
8047 return suite;
8050 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8052 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8053 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8055 torture_tcase_set_fixture(tcase,
8056 torture_rpc_spoolss_setup,
8057 torture_rpc_spoolss_teardown);
8059 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8060 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8061 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8062 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8063 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8064 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8065 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8066 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8067 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8068 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8069 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8070 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8071 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8072 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8073 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8074 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8075 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8076 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8077 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8078 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8080 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8082 return suite;
8085 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8086 struct dcerpc_binding_handle *b,
8087 const char *server,
8088 const char *environment,
8089 const char **dir_p)
8091 struct spoolss_GetPrinterDriverDirectory r;
8092 uint32_t needed;
8094 r.in.server = server;
8095 r.in.environment = environment;
8096 r.in.level = 1;
8097 r.in.buffer = NULL;
8098 r.in.offered = 0;
8099 r.out.needed = &needed;
8101 torture_assert_ntstatus_ok(tctx,
8102 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8103 "failed to query driver directory");
8105 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8106 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8107 r.in.buffer = &blob;
8108 r.in.offered = needed;
8110 torture_assert_ntstatus_ok(tctx,
8111 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8112 "failed to query driver directory");
8115 torture_assert_werr_ok(tctx, r.out.result,
8116 "failed to query driver directory");
8118 if (dir_p) {
8119 *dir_p = r.out.info->info1.directory_name;
8122 return true;
8125 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8127 if (info_ctr == NULL) {
8128 return NULL;
8131 switch (info_ctr->level) {
8132 case 1:
8133 return info_ctr->info.info1->driver_name;
8134 case 2:
8135 return info_ctr->info.info2->driver_name;
8136 case 3:
8137 return info_ctr->info.info3->driver_name;
8138 case 4:
8139 return info_ctr->info.info4->driver_name;
8140 case 6:
8141 return info_ctr->info.info6->driver_name;
8142 case 8:
8143 return info_ctr->info.info8->driver_name;
8144 default:
8145 return NULL;
8149 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8151 if (info_ctr == NULL) {
8152 return NULL;
8155 switch (info_ctr->level) {
8156 case 2:
8157 return info_ctr->info.info2->architecture;
8158 case 3:
8159 return info_ctr->info.info3->architecture;
8160 case 4:
8161 return info_ctr->info.info4->architecture;
8162 case 6:
8163 return info_ctr->info.info6->architecture;
8164 case 8:
8165 return info_ctr->info.info8->architecture;
8166 default:
8167 return NULL;
8172 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8173 struct dcerpc_binding_handle *b,
8174 const char *servername,
8175 struct spoolss_AddDriverInfoCtr *info_ctr,
8176 WERROR expected_result)
8178 struct spoolss_AddPrinterDriver r;
8179 const char *drivername = get_driver_from_info(info_ctr);
8180 const char *environment = get_environment_from_info(info_ctr);
8182 r.in.servername = servername;
8183 r.in.info_ctr = info_ctr;
8185 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8186 drivername, info_ctr->level, environment);
8188 torture_assert_ntstatus_ok(tctx,
8189 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8190 "spoolss_AddPrinterDriver failed");
8191 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8192 "spoolss_AddPrinterDriver failed with unexpected result");
8194 return true;
8198 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8199 struct dcerpc_binding_handle *b,
8200 const char *servername,
8201 struct spoolss_AddDriverInfoCtr *info_ctr,
8202 uint32_t flags,
8203 WERROR expected_result)
8205 struct spoolss_AddPrinterDriverEx r;
8206 const char *drivername = get_driver_from_info(info_ctr);
8207 const char *environment = get_environment_from_info(info_ctr);
8209 r.in.servername = servername;
8210 r.in.info_ctr = info_ctr;
8211 r.in.flags = flags;
8213 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8214 drivername, info_ctr->level, environment);
8216 torture_assert_ntstatus_ok(tctx,
8217 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8218 "AddPrinterDriverEx failed");
8219 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8220 "AddPrinterDriverEx failed with unexpected result");
8222 return true;
8225 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8226 if (path && strlen(path)) {\
8227 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8230 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8231 struct dcerpc_binding_handle *b,
8232 const char *server_name,
8233 struct spoolss_AddDriverInfo8 *r,
8234 uint32_t flags,
8235 bool ex,
8236 const char *remote_driver_dir)
8238 struct spoolss_AddDriverInfoCtr info_ctr;
8239 struct spoolss_AddDriverInfo1 info1;
8241 ZERO_STRUCT(info1);
8243 info_ctr.level = 1;
8244 info_ctr.info.info1 = &info1;
8246 if (ex) {
8247 torture_assert(tctx,
8248 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8249 "failed to test AddPrinterDriverEx level 1");
8250 } else {
8251 torture_assert(tctx,
8252 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8253 "failed to test AddPrinterDriver level 1");
8256 info1.driver_name = r->driver_name;
8258 if (ex) {
8259 torture_assert(tctx,
8260 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8261 "failed to test AddPrinterDriverEx level 1");
8262 } else {
8263 torture_assert(tctx,
8264 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8265 "failed to test AddPrinterDriver level 1");
8268 return true;
8271 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8272 struct dcerpc_binding_handle *b,
8273 const char *server_name,
8274 struct spoolss_AddDriverInfo8 *r,
8275 uint32_t flags,
8276 bool ex,
8277 const char *remote_driver_dir)
8279 struct spoolss_AddDriverInfoCtr info_ctr;
8280 struct spoolss_AddDriverInfo2 info2;
8281 union spoolss_DriverInfo info;
8283 ZERO_STRUCT(info2);
8285 info_ctr.level = 2;
8286 info_ctr.info.info2 = &info2;
8288 if (ex) {
8289 torture_assert(tctx,
8290 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8291 "failed to test AddPrinterDriverEx level 2");
8292 } else {
8293 torture_assert(tctx,
8294 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8295 "failed to test AddPrinterDriver level 2");
8298 info2.driver_name = r->driver_name;
8300 if (ex) {
8301 torture_assert(tctx,
8302 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8303 "failed to test AddPrinterDriverEx level 2");
8304 } else {
8305 torture_assert(tctx,
8306 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8307 "failed to test AddPrinterDriver level 2");
8310 info2.version = r->version;
8312 if (ex) {
8313 torture_assert(tctx,
8314 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8315 "failed to test AddPrinterDriverEx level 2");
8316 } else {
8317 torture_assert(tctx,
8318 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8319 "failed to test AddPrinterDriver level 2");
8322 info2.architecture = r->architecture;
8324 if (ex) {
8325 torture_assert(tctx,
8326 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8327 "failed to test AddPrinterDriverEx level 2");
8328 } else {
8329 torture_assert(tctx,
8330 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8331 "failed to test AddPrinterDriver level 2");
8334 info2.driver_path = r->driver_path;
8336 if (ex) {
8337 torture_assert(tctx,
8338 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8339 "failed to test AddPrinterDriverEx level 2");
8340 } else {
8341 torture_assert(tctx,
8342 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8343 "failed to test AddPrinterDriver level 2");
8346 info2.data_file = r->data_file;
8348 if (ex) {
8349 torture_assert(tctx,
8350 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8351 "failed to test AddPrinterDriverEx level 2");
8352 } else {
8353 torture_assert(tctx,
8354 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8355 "failed to test AddPrinterDriver level 2");
8358 info2.config_file = r->config_file;
8360 if (ex) {
8361 torture_assert(tctx,
8362 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8363 "failed to test AddPrinterDriverEx");
8366 if (ex) {
8367 torture_assert(tctx,
8368 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8369 "failed to test AddPrinterDriverEx level 2");
8370 } else {
8371 torture_assert(tctx,
8372 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8373 "failed to test AddPrinterDriver level 2");
8376 torture_assert(tctx,
8377 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8378 "failed to find added printer driver");
8380 if (remote_driver_dir) {
8381 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8382 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8383 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8386 return true;
8389 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8390 struct dcerpc_binding_handle *b,
8391 const char *server_name,
8392 struct spoolss_AddDriverInfo8 *r,
8393 uint32_t flags,
8394 bool ex,
8395 const char *remote_driver_dir)
8397 struct spoolss_AddDriverInfoCtr info_ctr;
8398 struct spoolss_AddDriverInfo3 info3;
8399 union spoolss_DriverInfo info;
8401 info3.driver_name = r->driver_name;
8402 info3.version = r->version;
8403 info3.architecture = r->architecture;
8404 info3.driver_path = r->driver_path;
8405 info3.data_file = r->data_file;
8406 info3.config_file = r->config_file;
8407 info3.help_file = r->help_file;
8408 info3.monitor_name = r->monitor_name;
8409 info3.default_datatype = r->default_datatype;
8410 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8411 info3.dependent_files = r->dependent_files;
8413 info_ctr.level = 3;
8414 info_ctr.info.info3 = &info3;
8416 if (ex) {
8417 torture_assert(tctx,
8418 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8419 "failed to test AddPrinterDriverEx level 3");
8420 } else {
8421 torture_assert(tctx,
8422 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8423 "failed to test AddPrinterDriver level 3");
8426 torture_assert(tctx,
8427 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8428 "failed to find added printer driver");
8430 if (remote_driver_dir) {
8431 int i;
8432 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8433 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8434 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8435 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8436 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8437 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8441 return true;
8444 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8445 struct dcerpc_binding_handle *b,
8446 const char *server_name,
8447 struct spoolss_AddDriverInfo8 *r,
8448 uint32_t flags,
8449 bool ex,
8450 const char *remote_driver_dir)
8452 struct spoolss_AddDriverInfoCtr info_ctr;
8453 struct spoolss_AddDriverInfo4 info4;
8454 union spoolss_DriverInfo info;
8456 info4.version = r->version;
8457 info4.driver_name = r->driver_name;
8458 info4.architecture = r->architecture;
8459 info4.driver_path = r->driver_path;
8460 info4.data_file = r->data_file;
8461 info4.config_file = r->config_file;
8462 info4.help_file = r->help_file;
8463 info4.monitor_name = r->monitor_name;
8464 info4.default_datatype = r->default_datatype;
8465 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8466 info4.dependent_files = r->dependent_files;
8467 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8468 info4.previous_names = r->previous_names;
8470 info_ctr.level = 4;
8471 info_ctr.info.info4 = &info4;
8473 if (ex) {
8474 torture_assert(tctx,
8475 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8476 "failed to test AddPrinterDriverEx level 4");
8477 } else {
8478 torture_assert(tctx,
8479 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8480 "failed to test AddPrinterDriver level 4");
8483 torture_assert(tctx,
8484 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8485 "failed to find added printer driver");
8487 if (remote_driver_dir) {
8488 int i;
8489 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8490 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8491 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8492 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8493 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8494 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8498 return true;
8501 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8502 struct dcerpc_binding_handle *b,
8503 const char *server_name,
8504 struct spoolss_AddDriverInfo8 *r,
8505 uint32_t flags,
8506 bool ex,
8507 const char *remote_driver_dir)
8509 struct spoolss_AddDriverInfoCtr info_ctr;
8510 struct spoolss_AddDriverInfo6 info6;
8511 union spoolss_DriverInfo info;
8513 info6.version = r->version;
8514 info6.driver_name = r->driver_name;
8515 info6.architecture = r->architecture;
8516 info6.driver_path = r->driver_path;
8517 info6.data_file = r->data_file;
8518 info6.config_file = r->config_file;
8519 info6.help_file = r->help_file;
8520 info6.monitor_name = r->monitor_name;
8521 info6.default_datatype = r->default_datatype;
8522 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8523 info6.dependent_files = r->dependent_files;
8524 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8525 info6.previous_names = r->previous_names;
8526 info6.driver_date = r->driver_date;
8527 info6.driver_version = r->driver_version;
8528 info6.manufacturer_name = r->manufacturer_name;
8529 info6.manufacturer_url = r->manufacturer_url;
8530 info6.hardware_id = r->hardware_id;
8531 info6.provider = r->provider;
8533 info_ctr.level = 6;
8534 info_ctr.info.info6 = &info6;
8536 if (ex) {
8537 torture_assert(tctx,
8538 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8539 "failed to test AddPrinterDriverEx level 6");
8540 } else {
8541 torture_assert(tctx,
8542 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8543 "failed to test AddPrinterDriver level 6");
8546 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8548 if (!ex) {
8549 return true;
8552 torture_assert(tctx,
8553 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8554 "failed to find added printer driver");
8556 if (remote_driver_dir) {
8557 int i;
8558 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8559 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8560 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8561 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8562 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8563 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8567 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8568 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8570 return true;
8573 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8574 struct dcerpc_binding_handle *b,
8575 const char *server_name,
8576 struct spoolss_AddDriverInfo8 *r,
8577 uint32_t flags,
8578 bool ex,
8579 const char *remote_driver_dir)
8581 struct spoolss_AddDriverInfoCtr info_ctr;
8582 union spoolss_DriverInfo info;
8584 info_ctr.level = 8;
8585 info_ctr.info.info8 = r;
8587 if (ex) {
8588 torture_assert(tctx,
8589 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8590 "failed to test AddPrinterDriverEx level 8");
8591 } else {
8592 torture_assert(tctx,
8593 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8594 "failed to test AddPrinterDriver level 8");
8597 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8599 if (!ex) {
8600 return true;
8603 torture_assert(tctx,
8604 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8605 "failed to find added printer driver");
8607 if (remote_driver_dir) {
8608 int i;
8609 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8610 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8611 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8612 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8613 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8614 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8618 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8619 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8621 return true;
8624 #undef ASSERT_DRIVER_PATH
8626 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8627 struct dcerpc_binding_handle *b,
8628 const char *server,
8629 const char *driver,
8630 const char *environment,
8631 WERROR expected_result)
8633 struct spoolss_DeletePrinterDriver r;
8635 r.in.server = server;
8636 r.in.architecture = environment;
8637 r.in.driver = driver;
8639 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8641 torture_assert_ntstatus_ok(tctx,
8642 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8643 "DeletePrinterDriver failed");
8644 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8645 "DeletePrinterDriver failed with unexpected result");
8647 return true;
8650 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8651 struct dcerpc_binding_handle *b,
8652 const char *server,
8653 const char *driver,
8654 const char *environment,
8655 uint32_t delete_flags,
8656 uint32_t version,
8657 WERROR expected_result)
8659 struct spoolss_DeletePrinterDriverEx r;
8661 r.in.server = server;
8662 r.in.architecture = environment;
8663 r.in.driver = driver;
8664 r.in.delete_flags = delete_flags;
8665 r.in.version = version;
8667 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8669 torture_assert_ntstatus_ok(tctx,
8670 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8671 "DeletePrinterDriverEx failed");
8672 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8673 "DeletePrinterDriverEx failed with unexpected result");
8675 return true;
8678 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8679 struct dcerpc_binding_handle *b,
8680 const char *server_name,
8681 const char *driver,
8682 const char *environment)
8684 torture_assert(tctx,
8685 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8686 "failed to delete driver");
8688 torture_assert(tctx,
8689 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8690 "failed to delete driver");
8692 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8693 torture_fail(tctx, "deleted driver still enumerated");
8696 torture_assert(tctx,
8697 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8698 "2nd delete failed");
8700 return true;
8703 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8704 struct dcerpc_binding_handle *b,
8705 const char *server_name,
8706 const char *driver,
8707 const char *environment,
8708 uint32_t delete_flags,
8709 uint32_t version)
8711 torture_assert(tctx,
8712 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8713 "failed to delete driver");
8715 torture_assert(tctx,
8716 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8717 "failed to delete driver");
8719 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8720 torture_fail(tctx, "deleted driver still enumerated");
8723 torture_assert(tctx,
8724 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8725 "2nd delete failed");
8727 return true;
8730 static bool test_PrinterDriver_args(struct torture_context *tctx,
8731 struct dcerpc_binding_handle *b,
8732 const char *server_name,
8733 uint32_t level,
8734 struct spoolss_AddDriverInfo8 *r,
8735 uint32_t add_flags,
8736 uint32_t delete_flags,
8737 uint32_t delete_version,
8738 bool ex,
8739 const char *remote_driver_dir)
8741 bool ret = true;
8743 switch (level) {
8744 case 1:
8745 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8746 break;
8747 case 2:
8748 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8749 break;
8750 case 3:
8751 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8752 break;
8753 case 4:
8754 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8755 break;
8756 case 6:
8757 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8758 break;
8759 case 8:
8760 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8761 break;
8762 default:
8763 return false;
8766 if (ret == false) {
8767 return ret;
8770 if (level == 1) {
8771 return ret;
8774 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8776 if (!ex && (level == 6 || level == 8)) {
8777 return ret;
8781 struct dcerpc_pipe *p2;
8782 struct policy_handle hive_handle;
8783 struct dcerpc_binding_handle *b2;
8785 torture_assert_ntstatus_ok(tctx,
8786 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8787 "could not open winreg pipe");
8788 b2 = p2->binding_handle;
8790 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8792 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8794 test_winreg_CloseKey(tctx, b2, &hive_handle);
8796 talloc_free(p2);
8799 if (ex) {
8800 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8801 } else {
8802 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8806 static bool fillup_printserver_info(struct torture_context *tctx,
8807 struct dcerpc_pipe *p,
8808 struct torture_driver_context *d)
8810 struct policy_handle server_handle;
8811 struct dcerpc_binding_handle *b = p->binding_handle;
8812 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8814 torture_assert(tctx,
8815 test_OpenPrinter_server(tctx, p, &server_handle),
8816 "failed to open printserver");
8817 torture_assert(tctx,
8818 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8819 "failed to get environment");
8820 torture_assert(tctx,
8821 test_ClosePrinter(tctx, b, &server_handle),
8822 "failed to close printserver");
8824 torture_assert(tctx,
8825 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8826 d->local.environment ? d->local.environment : d->remote.environment,
8827 &d->remote.driver_directory),
8828 "failed to get driver directory");
8830 return true;
8833 static const char *driver_directory_dir(const char *driver_directory)
8835 char *p;
8837 p = strrchr(driver_directory, '\\');
8838 if (p) {
8839 return p+1;
8842 return NULL;
8845 static const char *driver_directory_share(struct torture_context *tctx,
8846 const char *driver_directory)
8848 const char *p;
8849 char *tok;
8851 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8852 driver_directory += 2;
8855 p = talloc_strdup(tctx, driver_directory);
8857 torture_assert(tctx,
8858 next_token_talloc(tctx, &p, &tok, "\\"),
8859 "cannot explode uri");
8860 torture_assert(tctx,
8861 next_token_talloc(tctx, &p, &tok, "\\"),
8862 "cannot explode uri");
8864 return tok;
8867 static bool upload_printer_driver_file(struct torture_context *tctx,
8868 struct smbcli_state *cli,
8869 struct torture_driver_context *d,
8870 const char *file_name)
8872 XFILE *f;
8873 int fnum;
8874 uint8_t *buf;
8875 int maxwrite = 64512;
8876 off_t nread = 0;
8877 size_t start = 0;
8878 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8879 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8880 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8882 if (!file_name || strlen(file_name) == 0) {
8883 return true;
8886 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8888 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8889 if (fnum == -1) {
8890 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8893 f = x_fopen(local_name, O_RDONLY, 0);
8894 if (f == NULL) {
8895 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8898 buf = talloc_array(tctx, uint8_t, maxwrite);
8899 if (!buf) {
8900 return false;
8903 while (!x_feof(f)) {
8904 int n = maxwrite;
8905 int ret;
8907 if ((n = x_fread(buf, 1, n, f)) < 1) {
8908 if((n == 0) && x_feof(f))
8909 break; /* Empty local file. */
8911 torture_warning(tctx,
8912 "failed to read file: %s\n", strerror(errno));
8913 break;
8916 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8918 if (n != ret) {
8919 torture_warning(tctx,
8920 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8921 break;
8924 nread += n;
8927 x_fclose(f);
8929 torture_assert_ntstatus_ok(tctx,
8930 smbcli_close(cli->tree, fnum),
8931 "failed to close file");
8933 return true;
8936 static bool connect_printer_driver_share(struct torture_context *tctx,
8937 const char *server_name,
8938 const char *share_name,
8939 struct smbcli_state **cli)
8941 struct smbcli_options smb_options;
8942 struct smbcli_session_options smb_session_options;
8944 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8945 share_name, server_name);
8947 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8948 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8950 torture_assert_ntstatus_ok(tctx,
8951 smbcli_full_connection(tctx, cli, server_name,
8952 lpcfg_smb_ports(tctx->lp_ctx),
8953 share_name, NULL,
8954 lpcfg_socket_options(tctx->lp_ctx),
8955 cmdline_credentials,
8956 lpcfg_resolve_context(tctx->lp_ctx),
8957 tctx->ev,
8958 &smb_options,
8959 &smb_session_options,
8960 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8961 "failed to open driver share");
8963 return true;
8966 static bool upload_printer_driver(struct torture_context *tctx,
8967 const char *server_name,
8968 struct torture_driver_context *d)
8970 struct smbcli_state *cli;
8971 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8972 int i;
8974 torture_assert(tctx,
8975 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8976 "failed to connect to driver share");
8978 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8979 server_name, share_name);
8981 torture_assert(tctx,
8982 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8983 "failed to upload driver_path");
8984 torture_assert(tctx,
8985 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8986 "failed to upload data_file");
8987 torture_assert(tctx,
8988 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8989 "failed to upload config_file");
8990 torture_assert(tctx,
8991 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8992 "failed to upload help_file");
8993 if (d->info8.dependent_files) {
8994 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8995 torture_assert(tctx,
8996 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8997 "failed to upload dependent_files");
9001 talloc_free(cli);
9003 return true;
9006 static bool check_printer_driver_file(struct torture_context *tctx,
9007 struct smbcli_state *cli,
9008 struct torture_driver_context *d,
9009 const char *file_name)
9011 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9012 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9013 remote_arch_dir,
9014 d->info8.version,
9015 file_name);
9016 int fnum;
9018 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9020 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9022 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9023 if (fnum == -1) {
9024 return false;
9027 torture_assert_ntstatus_ok(tctx,
9028 smbcli_close(cli->tree, fnum),
9029 "failed to close driver file");
9031 return true;
9034 static bool check_printer_driver_files(struct torture_context *tctx,
9035 const char *server_name,
9036 struct torture_driver_context *d,
9037 bool expect_exist)
9039 struct smbcli_state *cli;
9040 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9041 int i;
9043 torture_assert(tctx,
9044 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9045 "failed to connect to driver share");
9047 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9048 (expect_exist ? "": "non-"),
9049 server_name, share_name);
9051 if (d->info8.driver_path && d->info8.driver_path[0]) {
9052 torture_assert(tctx,
9053 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9054 "failed driver_path check");
9056 if (d->info8.data_file && d->info8.data_file[0]) {
9057 torture_assert(tctx,
9058 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9059 "failed data_file check");
9061 if (d->info8.config_file && d->info8.config_file[0]) {
9062 torture_assert(tctx,
9063 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9064 "failed config_file check");
9066 if (d->info8.help_file && d->info8.help_file[0]) {
9067 torture_assert(tctx,
9068 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9069 "failed help_file check");
9071 if (d->info8.dependent_files) {
9072 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9073 torture_assert(tctx,
9074 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9075 "failed dependent_files check");
9079 talloc_free(cli);
9081 return true;
9084 static bool remove_printer_driver_file(struct torture_context *tctx,
9085 struct smbcli_state *cli,
9086 struct torture_driver_context *d,
9087 const char *file_name)
9089 const char *remote_name;
9090 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9092 if (!file_name || strlen(file_name) == 0) {
9093 return true;
9096 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9098 torture_comment(tctx, "Removing %s\n", remote_name);
9100 torture_assert_ntstatus_ok(tctx,
9101 smbcli_unlink(cli->tree, remote_name),
9102 "failed to unlink");
9104 return true;
9107 static bool remove_printer_driver(struct torture_context *tctx,
9108 const char *server_name,
9109 struct torture_driver_context *d)
9111 struct smbcli_state *cli;
9112 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9113 int i;
9115 torture_assert(tctx,
9116 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9117 "failed to connect to driver share");
9119 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9120 server_name, share_name);
9122 torture_assert(tctx,
9123 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9124 "failed to remove driver_path");
9125 torture_assert(tctx,
9126 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9127 "failed to remove data_file");
9128 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9129 torture_assert(tctx,
9130 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9131 "failed to remove config_file");
9133 torture_assert(tctx,
9134 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9135 "failed to remove help_file");
9136 if (d->info8.dependent_files) {
9137 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9138 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9139 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9140 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9141 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9142 continue;
9144 torture_assert(tctx,
9145 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9146 "failed to remove dependent_files");
9150 talloc_free(cli);
9152 return true;
9156 static bool test_add_driver_arg(struct torture_context *tctx,
9157 struct dcerpc_pipe *p,
9158 struct torture_driver_context *d)
9160 bool ret = true;
9161 struct dcerpc_binding_handle *b = p->binding_handle;
9162 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9163 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9164 int i;
9165 struct spoolss_AddDriverInfo8 info8;
9166 uint32_t add_flags = APD_COPY_NEW_FILES;
9167 uint32_t delete_flags = 0;
9169 ZERO_STRUCT(info8);
9171 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9172 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9174 torture_assert(tctx,
9175 fillup_printserver_info(tctx, p, d),
9176 "failed to fillup printserver info");
9178 if (!directory_exist(d->local.driver_directory)) {
9179 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9182 torture_assert(tctx,
9183 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9184 "failed to upload printer driver");
9186 info8 = d->info8;
9187 if (d->info8.dependent_files) {
9188 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9189 if (d->info8.dependent_files->string) {
9190 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9192 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9193 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9194 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9198 info8.architecture = d->local.environment;
9200 for (i=0; i < ARRAY_SIZE(levels); i++) {
9202 if (torture_setting_bool(tctx, "samba3", false)) {
9203 switch (levels[i]) {
9204 case 2:
9205 case 4:
9206 case 8:
9207 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9208 continue;
9209 default:
9210 break;
9213 if (torture_setting_bool(tctx, "w2k3", false)) {
9214 switch (levels[i]) {
9215 case 8:
9216 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9217 continue;
9218 default:
9219 break;
9223 torture_comment(tctx,
9224 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9225 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9227 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);
9230 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9231 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9232 if (d->info8.config_file) {
9233 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9235 if (d->info8.help_file) {
9236 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9238 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9239 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9240 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9244 for (i=0; i < ARRAY_SIZE(levels); i++) {
9246 if (torture_setting_bool(tctx, "samba3", false)) {
9247 switch (levels[i]) {
9248 case 2:
9249 case 4:
9250 case 8:
9251 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9252 continue;
9253 default:
9254 break;
9257 if (torture_setting_bool(tctx, "w2k3", false)) {
9258 switch (levels[i]) {
9259 case 8:
9260 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9261 continue;
9262 default:
9263 break;
9267 torture_comment(tctx,
9268 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9269 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9271 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);
9274 torture_assert(tctx,
9275 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9276 "failed to remove printer driver");
9278 torture_comment(tctx, "\n");
9280 return ret;
9283 static bool test_add_driver_ex_64(struct torture_context *tctx,
9284 struct dcerpc_pipe *p)
9286 struct torture_driver_context *d;
9288 d = talloc_zero(tctx, struct torture_driver_context);
9290 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9291 d->info8.driver_name = TORTURE_DRIVER_EX;
9292 d->info8.architecture = NULL;
9293 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9294 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9295 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9296 d->local.environment = talloc_strdup(d, "Windows x64");
9297 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9298 d->ex = true;
9300 return test_add_driver_arg(tctx, p, d);
9303 static bool test_add_driver_ex_32(struct torture_context *tctx,
9304 struct dcerpc_pipe *p)
9306 struct torture_driver_context *d;
9308 d = talloc_zero(tctx, struct torture_driver_context);
9310 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9311 d->info8.driver_name = TORTURE_DRIVER_EX;
9312 d->info8.architecture = NULL;
9313 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9314 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9315 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9316 d->local.environment = talloc_strdup(d, "Windows NT x86");
9317 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9318 d->ex = true;
9320 return test_add_driver_arg(tctx, p, d);
9323 static bool test_add_driver_64(struct torture_context *tctx,
9324 struct dcerpc_pipe *p)
9326 struct torture_driver_context *d;
9328 d = talloc_zero(tctx, struct torture_driver_context);
9330 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9331 d->info8.driver_name = TORTURE_DRIVER;
9332 d->info8.architecture = NULL;
9333 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9334 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9335 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9336 d->local.environment = talloc_strdup(d, "Windows x64");
9337 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9338 d->ex = false;
9340 return test_add_driver_arg(tctx, p, d);
9343 static bool test_add_driver_32(struct torture_context *tctx,
9344 struct dcerpc_pipe *p)
9346 struct torture_driver_context *d;
9348 d = talloc_zero(tctx, struct torture_driver_context);
9350 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9351 d->info8.driver_name = TORTURE_DRIVER;
9352 d->info8.architecture = NULL;
9353 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9354 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9355 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9356 d->local.environment = talloc_strdup(d, "Windows NT x86");
9357 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9358 d->ex = false;
9360 return test_add_driver_arg(tctx, p, d);
9363 static bool test_add_driver_adobe(struct torture_context *tctx,
9364 struct dcerpc_pipe *p)
9366 struct torture_driver_context *d;
9368 if (!torture_setting_bool(tctx, "samba3", false)) {
9369 torture_skip(tctx, "skipping adobe test which only works against samba3");
9372 d = talloc_zero(tctx, struct torture_driver_context);
9374 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9375 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9376 d->info8.architecture = NULL;
9377 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9378 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9379 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9380 #if 0
9381 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9382 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9383 #endif
9384 d->local.environment = talloc_strdup(d, "Windows 4.0");
9385 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9386 d->ex = false;
9388 return test_add_driver_arg(tctx, p, d);
9391 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9392 struct dcerpc_pipe *p)
9394 struct torture_driver_context *d;
9395 struct spoolss_StringArray *a;
9397 if (!torture_setting_bool(tctx, "samba3", false)) {
9398 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9401 d = talloc_zero(tctx, struct torture_driver_context);
9403 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9404 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9405 d->info8.architecture = NULL;
9406 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9407 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9408 d->info8.config_file = NULL;
9409 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9410 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9411 d->info8.default_datatype = talloc_strdup(d, "RAW");
9413 a = talloc_zero(d, struct spoolss_StringArray);
9414 a->string = talloc_zero_array(a, const char *, 7);
9415 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9416 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9417 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9418 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9419 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9420 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9422 d->info8.dependent_files = a;
9423 d->local.environment = talloc_strdup(d, "Windows 4.0");
9424 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9425 d->ex = false;
9427 return test_add_driver_arg(tctx, p, d);
9430 static bool test_add_driver_timestamps(struct torture_context *tctx,
9431 struct dcerpc_pipe *p)
9433 struct torture_driver_context *d;
9434 struct timeval t = timeval_current();
9436 d = talloc_zero(tctx, struct torture_driver_context);
9438 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9439 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9440 d->info8.architecture = NULL;
9441 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9442 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9443 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9444 d->info8.driver_date = timeval_to_nttime(&t);
9445 d->local.environment = talloc_strdup(d, "Windows NT x86");
9446 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9447 d->ex = true;
9449 torture_assert(tctx,
9450 test_add_driver_arg(tctx, p, d),
9451 "");
9453 unix_to_nt_time(&d->info8.driver_date, 1);
9455 torture_assert(tctx,
9456 test_add_driver_arg(tctx, p, d),
9457 "");
9459 return true;
9462 static bool test_multiple_drivers(struct torture_context *tctx,
9463 struct dcerpc_pipe *p)
9465 struct torture_driver_context *d;
9466 struct dcerpc_binding_handle *b = p->binding_handle;
9467 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9468 int i;
9469 struct spoolss_AddDriverInfo8 info8;
9470 uint32_t add_flags = APD_COPY_NEW_FILES;
9471 uint32_t delete_flags = 0;
9473 d = talloc_zero(tctx, struct torture_driver_context);
9475 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9476 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9477 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9478 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9479 d->local.environment = talloc_strdup(d, "Windows NT x86");
9480 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9481 d->ex = true;
9483 torture_assert(tctx,
9484 fillup_printserver_info(tctx, p, d),
9485 "failed to fillup printserver info");
9487 if (!directory_exist(d->local.driver_directory)) {
9488 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9491 torture_assert(tctx,
9492 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9493 "failed to upload printer driver");
9495 info8 = d->info8;
9496 info8.architecture = d->local.environment;
9498 for (i=0; i < 3; i++) {
9499 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9501 torture_assert(tctx,
9502 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9503 "failed to add driver");
9506 torture_assert(tctx,
9507 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9508 "failed to delete driver");
9510 torture_assert(tctx,
9511 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9512 "torture_test_driver_1 no longer on the server");
9514 torture_assert(tctx,
9515 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9516 "torture_test_driver_2 no longer on the server");
9518 torture_assert(tctx,
9519 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9520 "failed to delete driver");
9522 torture_assert(tctx,
9523 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9524 "torture_test_driver_2 no longer on the server");
9526 torture_assert(tctx,
9527 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9528 "failed to delete driver");
9530 torture_assert(tctx,
9531 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9532 "failed to remove printer driver");
9534 return true;
9537 static bool test_del_driver_all_files(struct torture_context *tctx,
9538 struct dcerpc_pipe *p)
9540 struct torture_driver_context *d;
9541 struct spoolss_StringArray *a;
9542 uint32_t add_flags = APD_COPY_NEW_FILES;
9543 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9544 struct dcerpc_binding_handle *b = p->binding_handle;
9545 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9547 d = talloc_zero(tctx, struct torture_driver_context);
9549 d->ex = true;
9550 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9551 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9552 d->info8.architecture = NULL;
9553 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9554 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9555 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9556 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9557 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9558 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9560 a = talloc_zero(d, struct spoolss_StringArray);
9561 a->string = talloc_zero_array(a, const char *, 3);
9562 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9563 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9565 d->info8.dependent_files = a;
9566 d->info8.architecture = d->local.environment;
9568 torture_assert(tctx,
9569 fillup_printserver_info(tctx, p, d),
9570 "failed to fillup printserver info");
9572 if (!directory_exist(d->local.driver_directory)) {
9573 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9576 torture_assert(tctx,
9577 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9578 "failed to upload printer driver");
9580 torture_assert(tctx,
9581 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9582 "failed to add driver");
9584 torture_assert(tctx,
9585 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9586 d->info8.driver_name,
9587 d->local.environment,
9588 delete_flags,
9589 d->info8.version),
9590 "failed to delete driver");
9592 torture_assert(tctx,
9593 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9594 "printer driver file check failed");
9596 talloc_free(d);
9597 return true;
9600 static bool test_del_driver_unused_files(struct torture_context *tctx,
9601 struct dcerpc_pipe *p)
9603 struct torture_driver_context *d1;
9604 struct torture_driver_context *d2;
9605 uint32_t add_flags = APD_COPY_NEW_FILES;
9606 struct dcerpc_binding_handle *b = p->binding_handle;
9607 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9609 d1 = talloc_zero(tctx, struct torture_driver_context);
9610 d1->ex = true;
9611 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9612 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9613 d1->info8.architecture = NULL;
9614 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9615 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9616 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9617 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9618 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9619 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9620 d1->info8.architecture = d1->local.environment;
9622 d2 = talloc_zero(tctx, struct torture_driver_context);
9623 d2->ex = true;
9624 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9625 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9626 d2->info8.architecture = NULL;
9627 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9628 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9629 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9630 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9631 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9632 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9633 d2->info8.architecture = d2->local.environment;
9635 torture_assert(tctx,
9636 fillup_printserver_info(tctx, p, d1),
9637 "failed to fillup printserver info");
9638 torture_assert(tctx,
9639 fillup_printserver_info(tctx, p, d2),
9640 "failed to fillup printserver info");
9642 if (!directory_exist(d1->local.driver_directory)) {
9643 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9646 torture_assert(tctx,
9647 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9648 "failed to upload printer driver");
9649 torture_assert(tctx,
9650 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9651 "failed to add driver");
9653 torture_assert(tctx,
9654 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9655 "failed to upload printer driver");
9656 torture_assert(tctx,
9657 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9658 "failed to add driver");
9660 /* some files are in use by a separate driver, should fail */
9661 torture_assert(tctx,
9662 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9663 d1->info8.driver_name,
9664 d1->local.environment,
9665 DPD_DELETE_ALL_FILES,
9666 d1->info8.version,
9667 WERR_PRINTER_DRIVER_IN_USE),
9668 "invalid delete driver response");
9670 /* should only delete files not in use by other driver */
9671 torture_assert(tctx,
9672 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9673 d1->info8.driver_name,
9674 d1->local.environment,
9675 DPD_DELETE_UNUSED_FILES,
9676 d1->info8.version,
9677 WERR_OK),
9678 "failed to delete driver (unused files)");
9680 /* check non-overlapping were deleted */
9681 d1->info8.driver_path = NULL;
9682 d1->info8.help_file = NULL;
9683 torture_assert(tctx,
9684 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9685 "printer driver file check failed");
9686 /* d2 files should be uneffected */
9687 torture_assert(tctx,
9688 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9689 "printer driver file check failed");
9691 torture_assert(tctx,
9692 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9693 d2->info8.driver_name,
9694 d2->local.environment,
9695 DPD_DELETE_ALL_FILES,
9696 d2->info8.version,
9697 WERR_OK),
9698 "failed to delete driver");
9700 torture_assert(tctx,
9701 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9702 "printer driver file check failed");
9704 talloc_free(d1);
9705 talloc_free(d2);
9706 return true;
9709 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9711 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9713 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9714 "driver", &ndr_table_spoolss);
9715 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9716 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9718 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9719 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9721 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9723 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9725 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9727 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9729 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9731 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9733 return suite;