torture: confirm printer driver file removal
[Samba/vl.git] / source4 / torture / rpc / spoolss.c
blob1fb7d353e95b1d9230694c2e392847cf62723498
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 "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
42 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
43 #define TORTURE_PRINTER "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX "torture_printer_ex"
46 #define TORTURE_DRIVER "torture_driver"
47 #define TORTURE_DRIVER_EX "torture_driver_ex"
48 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
49 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
50 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
51 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
52 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
54 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
55 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
56 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
57 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
58 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
59 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
61 struct test_spoolss_context {
62 struct dcerpc_pipe *spoolss_pipe;
64 /* server environment */
65 const char *environment;
67 /* print server handle */
68 struct policy_handle server_handle;
70 /* for EnumPorts */
71 uint32_t port_count[3];
72 union spoolss_PortInfo *ports[3];
74 /* for EnumPrinterDrivers */
75 uint32_t driver_count[8];
76 union spoolss_DriverInfo *drivers[8];
78 /* for EnumMonitors */
79 uint32_t monitor_count[3];
80 union spoolss_MonitorInfo *monitors[3];
82 /* for EnumPrintProcessors */
83 uint32_t print_processor_count[2];
84 union spoolss_PrintProcessorInfo *print_processors[2];
86 /* for EnumPrinters */
87 uint32_t printer_count[6];
88 union spoolss_PrinterInfo *printers[6];
91 struct torture_driver_context {
92 struct {
93 const char *driver_directory;
94 const char *environment;
95 } local;
96 struct {
97 const char *driver_directory;
98 const char *environment;
99 } remote;
100 struct spoolss_AddDriverInfo8 info8;
101 bool ex;
104 struct torture_printer_context {
105 struct dcerpc_pipe *spoolss_pipe;
106 struct spoolss_SetPrinterInfo2 info2;
107 struct torture_driver_context driver;
108 bool ex;
109 bool wellknown;
110 bool added_driver;
111 bool have_driver;
112 struct spoolss_DeviceMode *devmode;
113 struct policy_handle handle;
116 static bool upload_printer_driver(struct torture_context *tctx,
117 const char *server_name,
118 struct torture_driver_context *d);
119 static bool remove_printer_driver(struct torture_context *tctx,
120 const char *server_name,
121 struct torture_driver_context *d);
122 static bool fillup_printserver_info(struct torture_context *tctx,
123 struct dcerpc_pipe *p,
124 struct torture_driver_context *d);
125 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
126 struct dcerpc_binding_handle *b,
127 const char *server_name,
128 struct spoolss_AddDriverInfo8 *r,
129 uint32_t flags,
130 bool ex,
131 const char *remote_driver_dir);
133 #define COMPARE_STRING(tctx, c,r,e) \
134 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
136 /* not every compiler supports __typeof__() */
137 #if (__GNUC__ >= 3)
138 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
139 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
140 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
142 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
143 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
145 } while(0)
146 #else
147 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
148 #endif
150 #define COMPARE_UINT32(tctx, c, r, e) do {\
151 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
152 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
153 } while(0)
155 #define COMPARE_UINT64(tctx, c, r, e) do {\
156 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
157 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
158 } while(0)
161 #define COMPARE_NTTIME(tctx, c, r, e) do {\
162 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
163 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
164 } while(0)
166 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
167 int __i; \
168 if (!c.e && !r.e) { \
169 break; \
171 if (c.e && !r.e) { \
172 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
174 if (!c.e && r.e) { \
175 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
177 for (__i=0;c.e[__i] != NULL; __i++) { \
178 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
180 } while(0)
182 #define CHECK_ALIGN(size, n) do {\
183 if (size % n) {\
184 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
185 size, n, size + n - (size % n));\
187 } while(0)
189 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
191 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
192 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
193 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
194 uint32_t round_size = DO_ROUND(size, align);\
195 if (round_size != needed) {\
196 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
197 CHECK_ALIGN(size, align);\
200 } while(0)
202 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
203 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
204 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
205 uint32_t round_size = DO_ROUND(size, align);\
206 if (round_size != needed) {\
207 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
208 CHECK_ALIGN(size, align);\
211 } while(0)
213 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
214 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
215 uint32_t size = ndr_size_##fn(info, level, 0);\
216 uint32_t round_size = DO_ROUND(size, align);\
217 if (round_size != needed) {\
218 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
219 CHECK_ALIGN(size, align);\
222 } while(0)
224 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
225 const union spoolss_PrinterInfo *i,
226 uint32_t level,
227 union spoolss_SetPrinterInfo *s)
229 switch (level) {
230 case 0:
231 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
232 break;
233 case 2:
234 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
235 s->info2->servername = i->info2.servername;
236 s->info2->printername = i->info2.printername;
237 s->info2->sharename = i->info2.sharename;
238 s->info2->portname = i->info2.portname;
239 s->info2->drivername = i->info2.drivername;
240 s->info2->comment = i->info2.comment;
241 s->info2->location = i->info2.location;
242 s->info2->devmode_ptr = 0;
243 s->info2->sepfile = i->info2.sepfile;
244 s->info2->printprocessor = i->info2.printprocessor;
245 s->info2->datatype = i->info2.datatype;
246 s->info2->parameters = i->info2.parameters;
247 s->info2->secdesc_ptr = 0;
248 s->info2->attributes = i->info2.attributes;
249 s->info2->priority = i->info2.priority;
250 s->info2->defaultpriority = i->info2.defaultpriority;
251 s->info2->starttime = i->info2.starttime;
252 s->info2->untiltime = i->info2.untiltime;
253 s->info2->status = i->info2.status;
254 s->info2->cjobs = i->info2.cjobs;
255 s->info2->averageppm = i->info2.averageppm;
256 break;
257 case 3:
258 case 4:
259 case 5:
260 case 6:
261 case 7:
262 case 8:
263 case 9:
264 default:
265 return false;
268 return true;
271 static bool test_OpenPrinter_server(struct torture_context *tctx,
272 struct dcerpc_pipe *p,
273 struct policy_handle *server_handle)
275 NTSTATUS status;
276 struct spoolss_OpenPrinter op;
277 struct dcerpc_binding_handle *b = p->binding_handle;
279 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
280 op.in.datatype = NULL;
281 op.in.devmode_ctr.devmode= NULL;
282 op.in.access_mask = 0;
283 op.out.handle = server_handle;
285 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
287 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
288 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
289 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
291 return true;
294 static bool test_EnumPorts(struct torture_context *tctx,
295 void *private_data)
297 struct test_spoolss_context *ctx =
298 talloc_get_type_abort(private_data, struct test_spoolss_context);
299 struct dcerpc_pipe *p = ctx->spoolss_pipe;
300 struct dcerpc_binding_handle *b = p->binding_handle;
301 NTSTATUS status;
302 struct spoolss_EnumPorts r;
303 uint16_t levels[] = { 1, 2 };
304 int i, j;
306 for (i=0;i<ARRAY_SIZE(levels);i++) {
307 int level = levels[i];
308 DATA_BLOB blob;
309 uint32_t needed;
310 uint32_t count;
311 union spoolss_PortInfo *info;
313 r.in.servername = "";
314 r.in.level = level;
315 r.in.buffer = NULL;
316 r.in.offered = 0;
317 r.out.needed = &needed;
318 r.out.count = &count;
319 r.out.info = &info;
321 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
323 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
324 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
325 if (W_ERROR_IS_OK(r.out.result)) {
326 /* TODO: do some more checks here */
327 continue;
329 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
330 "EnumPorts unexpected return code");
332 blob = data_blob_talloc_zero(ctx, needed);
333 r.in.buffer = &blob;
334 r.in.offered = needed;
336 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
337 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
339 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
341 torture_assert(tctx, info, "EnumPorts returned no info");
343 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
345 ctx->port_count[level] = count;
346 ctx->ports[level] = info;
349 for (i=1;i<ARRAY_SIZE(levels);i++) {
350 int level = levels[i];
351 int old_level = levels[i-1];
352 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
353 "EnumPorts invalid value");
355 /* if the array sizes are not the same we would maybe segfault in the following code */
357 for (i=0;i<ARRAY_SIZE(levels);i++) {
358 int level = levels[i];
359 for (j=0;j<ctx->port_count[level];j++) {
360 union spoolss_PortInfo *cur = &ctx->ports[level][j];
361 union spoolss_PortInfo *ref = &ctx->ports[2][j];
362 switch (level) {
363 case 1:
364 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
365 break;
366 case 2:
367 /* level 2 is our reference, and it makes no sense to compare it to itself */
368 break;
373 return true;
376 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
377 void *private_data)
379 struct test_spoolss_context *ctx =
380 talloc_get_type_abort(private_data, struct test_spoolss_context);
382 NTSTATUS status;
383 struct dcerpc_pipe *p = ctx->spoolss_pipe;
384 struct dcerpc_binding_handle *b = p->binding_handle;
385 struct spoolss_GetPrintProcessorDirectory r;
386 struct {
387 uint16_t level;
388 const char *server;
389 } levels[] = {{
390 .level = 1,
391 .server = NULL
393 .level = 1,
394 .server = ""
396 .level = 78,
397 .server = ""
399 .level = 1,
400 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
402 .level = 1024,
403 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
406 int i;
407 uint32_t needed;
409 for (i=0;i<ARRAY_SIZE(levels);i++) {
410 int level = levels[i].level;
411 DATA_BLOB blob;
413 r.in.server = levels[i].server;
414 r.in.environment = ctx->environment;
415 r.in.level = level;
416 r.in.buffer = NULL;
417 r.in.offered = 0;
418 r.out.needed = &needed;
420 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
422 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
423 torture_assert_ntstatus_ok(tctx, status,
424 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
425 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
426 "GetPrintProcessorDirectory unexpected return code");
428 blob = data_blob_talloc_zero(tctx, needed);
429 r.in.buffer = &blob;
430 r.in.offered = needed;
432 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
433 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
435 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
437 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
440 return true;
444 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
445 void *private_data)
447 struct test_spoolss_context *ctx =
448 talloc_get_type_abort(private_data, struct test_spoolss_context);
450 NTSTATUS status;
451 struct dcerpc_pipe *p = ctx->spoolss_pipe;
452 struct dcerpc_binding_handle *b = p->binding_handle;
453 struct spoolss_GetPrinterDriverDirectory r;
454 struct {
455 uint16_t level;
456 const char *server;
457 } levels[] = {{
458 .level = 1,
459 .server = NULL
461 .level = 1,
462 .server = ""
464 .level = 78,
465 .server = ""
467 .level = 1,
468 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
470 .level = 1024,
471 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
474 int i;
475 uint32_t needed;
477 for (i=0;i<ARRAY_SIZE(levels);i++) {
478 int level = levels[i].level;
479 DATA_BLOB blob;
481 r.in.server = levels[i].server;
482 r.in.environment = ctx->environment;
483 r.in.level = level;
484 r.in.buffer = NULL;
485 r.in.offered = 0;
486 r.out.needed = &needed;
488 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
490 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
491 torture_assert_ntstatus_ok(tctx, status,
492 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
493 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
494 "GetPrinterDriverDirectory unexpected return code");
496 blob = data_blob_talloc_zero(tctx, needed);
497 r.in.buffer = &blob;
498 r.in.offered = needed;
500 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
501 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
503 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
505 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
508 return true;
511 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
512 struct dcerpc_binding_handle *b,
513 const char *server_name,
514 const char *environment,
515 uint32_t level,
516 uint32_t *count_p,
517 union spoolss_DriverInfo **info_p)
519 struct spoolss_EnumPrinterDrivers r;
520 uint32_t needed;
521 uint32_t count;
522 union spoolss_DriverInfo *info;
524 r.in.server = server_name;
525 r.in.environment = environment;
526 r.in.level = level;
527 r.in.buffer = NULL;
528 r.in.offered = 0;
529 r.out.needed = &needed;
530 r.out.count = &count;
531 r.out.info = &info;
533 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
534 r.in.environment, r.in.level);
536 torture_assert_ntstatus_ok(tctx,
537 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
538 "EnumPrinterDrivers failed");
539 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
540 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
541 r.in.buffer = &blob;
542 r.in.offered = needed;
544 torture_assert_ntstatus_ok(tctx,
545 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
546 "EnumPrinterDrivers failed");
549 torture_assert_werr_ok(tctx, r.out.result,
550 "EnumPrinterDrivers failed");
552 if (count_p) {
553 *count_p = count;
555 if (info_p) {
556 *info_p = info;
559 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
561 return true;
565 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
566 struct dcerpc_binding_handle *b,
567 const char *server_name,
568 const char *environment,
569 uint32_t level,
570 const char *driver_name,
571 union spoolss_DriverInfo *info_p)
573 uint32_t count;
574 union spoolss_DriverInfo *info;
575 int i;
576 const char *environment_ret = NULL;
578 torture_assert(tctx,
579 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
580 "failed to enumerate printer drivers");
582 for (i=0; i < count; i++) {
583 const char *driver_name_ret;
584 switch (level) {
585 case 1:
586 driver_name_ret = info[i].info1.driver_name;
587 break;
588 case 2:
589 driver_name_ret = info[i].info2.driver_name;
590 environment_ret = info[i].info2.architecture;
591 break;
592 case 3:
593 driver_name_ret = info[i].info3.driver_name;
594 environment_ret = info[i].info3.architecture;
595 break;
596 case 4:
597 driver_name_ret = info[i].info4.driver_name;
598 environment_ret = info[i].info4.architecture;
599 break;
600 case 5:
601 driver_name_ret = info[i].info5.driver_name;
602 environment_ret = info[i].info5.architecture;
603 break;
604 case 6:
605 driver_name_ret = info[i].info6.driver_name;
606 environment_ret = info[i].info6.architecture;
607 break;
608 case 7:
609 driver_name_ret = info[i].info7.driver_name;
610 break;
611 case 8:
612 driver_name_ret = info[i].info8.driver_name;
613 environment_ret = info[i].info8.architecture;
614 break;
615 default:
616 break;
618 if (environment_ret) {
619 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
621 if (strequal(driver_name, driver_name_ret)) {
622 if (info_p) {
623 *info_p = info[i];
625 return true;
629 return false;
632 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
633 void *private_data)
635 struct test_spoolss_context *ctx =
636 talloc_get_type_abort(private_data, struct test_spoolss_context);
637 struct dcerpc_pipe *p = ctx->spoolss_pipe;
638 struct dcerpc_binding_handle *b = p->binding_handle;
639 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
640 int i, j, a;
642 /* FIXME: gd, come back and fix "" as server, and handle
643 * priority of returned error codes in torture test and samba 3
644 * server */
645 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
646 const char *environments[2];
648 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
649 environments[1] = ctx->environment;
651 for (a=0;a<ARRAY_SIZE(environments);a++) {
653 for (i=0;i<ARRAY_SIZE(levels);i++) {
654 int level = levels[i];
655 uint32_t count;
656 union spoolss_DriverInfo *info;
658 torture_assert(tctx,
659 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
660 "failed to enumerate drivers");
662 ctx->driver_count[level] = count;
663 ctx->drivers[level] = info;
666 for (i=1;i<ARRAY_SIZE(levels);i++) {
667 int level = levels[i];
668 int old_level = levels[i-1];
670 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
671 "EnumPrinterDrivers invalid value");
674 for (i=0;i<ARRAY_SIZE(levels);i++) {
675 int level = levels[i];
677 for (j=0;j<ctx->driver_count[level];j++) {
678 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
679 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
681 switch (level) {
682 case 1:
683 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
684 break;
685 case 2:
686 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
687 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
688 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
689 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
690 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
691 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
692 break;
693 case 3:
694 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
695 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
696 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
697 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
698 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
699 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
701 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
704 break;
705 case 4:
706 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
707 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
708 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
709 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
710 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
711 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
713 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
716 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
717 break;
718 case 5:
719 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
720 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
721 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
722 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
723 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
724 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
725 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
726 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
727 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
728 break;
729 case 6:
730 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
731 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
732 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
733 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
734 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
735 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
737 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
740 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
741 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
742 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
745 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
746 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
747 break;
748 case 8:
749 /* level 8 is our reference, and it makes no sense to compare it to itself */
750 break;
756 return true;
759 static bool test_EnumMonitors(struct torture_context *tctx,
760 void *private_data)
762 struct test_spoolss_context *ctx =
763 talloc_get_type_abort(private_data, struct test_spoolss_context);
764 struct dcerpc_pipe *p = ctx->spoolss_pipe;
765 struct dcerpc_binding_handle *b = p->binding_handle;
766 NTSTATUS status;
767 struct spoolss_EnumMonitors r;
768 uint16_t levels[] = { 1, 2 };
769 int i, j;
771 for (i=0;i<ARRAY_SIZE(levels);i++) {
772 int level = levels[i];
773 DATA_BLOB blob;
774 uint32_t needed;
775 uint32_t count;
776 union spoolss_MonitorInfo *info;
778 r.in.servername = "";
779 r.in.level = level;
780 r.in.buffer = NULL;
781 r.in.offered = 0;
782 r.out.needed = &needed;
783 r.out.count = &count;
784 r.out.info = &info;
786 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
788 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
789 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
790 if (W_ERROR_IS_OK(r.out.result)) {
791 /* TODO: do some more checks here */
792 continue;
794 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
795 "EnumMonitors failed");
797 blob = data_blob_talloc_zero(ctx, needed);
798 r.in.buffer = &blob;
799 r.in.offered = needed;
801 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
802 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
804 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
806 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
808 ctx->monitor_count[level] = count;
809 ctx->monitors[level] = info;
812 for (i=1;i<ARRAY_SIZE(levels);i++) {
813 int level = levels[i];
814 int old_level = levels[i-1];
815 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
816 "EnumMonitors invalid value");
819 for (i=0;i<ARRAY_SIZE(levels);i++) {
820 int level = levels[i];
821 for (j=0;j<ctx->monitor_count[level];j++) {
822 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
823 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
824 switch (level) {
825 case 1:
826 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
827 break;
828 case 2:
829 /* level 2 is our reference, and it makes no sense to compare it to itself */
830 break;
835 return true;
838 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
839 struct dcerpc_binding_handle *b,
840 const char *environment,
841 uint32_t level,
842 uint32_t *count_p,
843 union spoolss_PrintProcessorInfo **info_p,
844 WERROR expected_result)
846 struct spoolss_EnumPrintProcessors r;
847 DATA_BLOB blob;
848 uint32_t needed;
849 uint32_t count;
850 union spoolss_PrintProcessorInfo *info;
852 r.in.servername = "";
853 r.in.environment = environment;
854 r.in.level = level;
855 r.in.buffer = NULL;
856 r.in.offered = 0;
857 r.out.needed = &needed;
858 r.out.count = &count;
859 r.out.info = &info;
861 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
862 r.in.environment, r.in.level);
864 torture_assert_ntstatus_ok(tctx,
865 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
866 "EnumPrintProcessors failed");
867 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
868 blob = data_blob_talloc_zero(tctx, needed);
869 r.in.buffer = &blob;
870 r.in.offered = needed;
871 torture_assert_ntstatus_ok(tctx,
872 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
873 "EnumPrintProcessors failed");
875 torture_assert_werr_equal(tctx, r.out.result, expected_result,
876 "EnumPrintProcessors failed");
878 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
880 if (count_p) {
881 *count_p = count;
883 if (info_p) {
884 *info_p = info;
887 return true;
890 static bool test_EnumPrintProcessors(struct torture_context *tctx,
891 void *private_data)
893 struct test_spoolss_context *ctx =
894 talloc_get_type_abort(private_data, struct test_spoolss_context);
896 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
897 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
898 int i;
899 struct dcerpc_pipe *p = ctx->spoolss_pipe;
900 struct dcerpc_binding_handle *b = p->binding_handle;
902 torture_assert(tctx,
903 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
904 "test_EnumPrintProcessors_level failed");
906 for (i=0;i<ARRAY_SIZE(levels);i++) {
907 union spoolss_PrintProcessorInfo *info;
908 uint32_t count;
909 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
911 torture_assert(tctx,
912 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
913 "test_EnumPrintProcessors_level failed");
916 return true;
919 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
920 struct dcerpc_binding_handle *b,
921 const char *print_processor_name,
922 uint32_t level,
923 uint32_t *count_p,
924 union spoolss_PrintProcDataTypesInfo **info_p,
925 WERROR expected_result)
927 struct spoolss_EnumPrintProcDataTypes r;
928 DATA_BLOB blob;
929 uint32_t needed;
930 uint32_t count;
931 union spoolss_PrintProcDataTypesInfo *info;
933 r.in.servername = "";
934 r.in.print_processor_name = print_processor_name;
935 r.in.level = level;
936 r.in.buffer = NULL;
937 r.in.offered = 0;
938 r.out.needed = &needed;
939 r.out.count = &count;
940 r.out.info = &info;
942 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
943 r.in.print_processor_name, r.in.level);
945 torture_assert_ntstatus_ok(tctx,
946 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
947 "EnumPrintProcDataTypes failed");
948 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
949 blob = data_blob_talloc_zero(tctx, needed);
950 r.in.buffer = &blob;
951 r.in.offered = needed;
952 torture_assert_ntstatus_ok(tctx,
953 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
954 "EnumPrintProcDataTypes failed");
956 torture_assert_werr_equal(tctx, r.out.result, expected_result,
957 "EnumPrintProcDataTypes failed");
959 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
961 if (count_p) {
962 *count_p = count;
964 if (info_p) {
965 *info_p = info;
968 return true;
971 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
972 void *private_data)
974 struct test_spoolss_context *ctx =
975 talloc_get_type_abort(private_data, struct test_spoolss_context);
977 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
978 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
979 int i;
980 struct dcerpc_pipe *p = ctx->spoolss_pipe;
981 struct dcerpc_binding_handle *b = p->binding_handle;
983 torture_assert(tctx,
984 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
985 "test_EnumPrintProcDataTypes_level failed");
987 torture_assert(tctx,
988 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
989 "test_EnumPrintProcDataTypes_level failed");
991 for (i=0;i<ARRAY_SIZE(levels);i++) {
992 int level = levels[i];
993 uint32_t count;
994 union spoolss_PrintProcDataTypesInfo *info;
995 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
997 torture_assert(tctx,
998 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
999 "test_EnumPrintProcDataTypes_level failed");
1003 union spoolss_PrintProcessorInfo *info;
1004 uint32_t count;
1006 torture_assert(tctx,
1007 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1008 "test_EnumPrintProcessors_level failed");
1010 for (i=0; i < count; i++) {
1011 torture_assert(tctx,
1012 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1013 "test_EnumPrintProcDataTypes_level failed");
1018 return true;
1021 static bool test_EnumPrinters(struct torture_context *tctx,
1022 void *private_data)
1024 struct test_spoolss_context *ctx =
1025 talloc_get_type_abort(private_data, struct test_spoolss_context);
1026 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1027 struct dcerpc_binding_handle *b = p->binding_handle;
1028 struct spoolss_EnumPrinters r;
1029 NTSTATUS status;
1030 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1031 int i, j;
1033 for (i=0;i<ARRAY_SIZE(levels);i++) {
1034 int level = levels[i];
1035 DATA_BLOB blob;
1036 uint32_t needed;
1037 uint32_t count;
1038 union spoolss_PrinterInfo *info;
1040 r.in.flags = PRINTER_ENUM_LOCAL;
1041 r.in.server = "";
1042 r.in.level = level;
1043 r.in.buffer = NULL;
1044 r.in.offered = 0;
1045 r.out.needed = &needed;
1046 r.out.count = &count;
1047 r.out.info = &info;
1049 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1051 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1052 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1053 if (W_ERROR_IS_OK(r.out.result)) {
1054 /* TODO: do some more checks here */
1055 continue;
1057 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1058 "EnumPrinters unexpected return code");
1060 blob = data_blob_talloc_zero(ctx, needed);
1061 r.in.buffer = &blob;
1062 r.in.offered = needed;
1064 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1065 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1067 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1069 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1071 ctx->printer_count[level] = count;
1072 ctx->printers[level] = info;
1075 for (i=1;i<ARRAY_SIZE(levels);i++) {
1076 int level = levels[i];
1077 int old_level = levels[i-1];
1078 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1079 "EnumPrinters invalid value");
1082 for (i=0;i<ARRAY_SIZE(levels);i++) {
1083 int level = levels[i];
1084 for (j=0;j<ctx->printer_count[level];j++) {
1085 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1086 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1087 switch (level) {
1088 case 0:
1089 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1090 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1091 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1092 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1093 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1094 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1095 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1097 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1099 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1111 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1112 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1113 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1114 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1116 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1117 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1118 break;
1119 case 1:
1120 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1121 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1122 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1123 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1124 break;
1125 case 2:
1126 /* level 2 is our reference, and it makes no sense to compare it to itself */
1127 break;
1128 case 4:
1129 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1130 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1131 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1132 break;
1133 case 5:
1134 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1135 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1136 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1137 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1138 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1139 break;
1144 /* TODO:
1145 * - verify that the port of a printer was in the list returned by EnumPorts
1148 return true;
1151 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1152 struct dcerpc_binding_handle *b,
1153 struct policy_handle *handle,
1154 const char *driver_name,
1155 const char *environment);
1157 bool test_GetPrinter_level(struct torture_context *tctx,
1158 struct dcerpc_binding_handle *b,
1159 struct policy_handle *handle,
1160 uint32_t level,
1161 union spoolss_PrinterInfo *info)
1163 struct spoolss_GetPrinter r;
1164 uint32_t needed;
1166 r.in.handle = handle;
1167 r.in.level = level;
1168 r.in.buffer = NULL;
1169 r.in.offered = 0;
1170 r.out.needed = &needed;
1172 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1174 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1175 "GetPrinter failed");
1177 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1178 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1179 r.in.buffer = &blob;
1180 r.in.offered = needed;
1182 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1183 "GetPrinter failed");
1186 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1188 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1190 if (info && r.out.info) {
1191 *info = *r.out.info;
1194 return true;
1198 static bool test_GetPrinter(struct torture_context *tctx,
1199 struct dcerpc_binding_handle *b,
1200 struct policy_handle *handle,
1201 const char *environment)
1203 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1204 int i;
1206 for (i=0;i<ARRAY_SIZE(levels);i++) {
1208 union spoolss_PrinterInfo info;
1210 ZERO_STRUCT(info);
1212 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1213 "failed to call GetPrinter");
1215 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1216 torture_assert(tctx,
1217 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1218 "failed to call test_GetPrinterDriver2");
1222 return true;
1225 static bool test_SetPrinter(struct torture_context *tctx,
1226 struct dcerpc_binding_handle *b,
1227 struct policy_handle *handle,
1228 struct spoolss_SetPrinterInfoCtr *info_ctr,
1229 struct spoolss_DevmodeContainer *devmode_ctr,
1230 struct sec_desc_buf *secdesc_ctr,
1231 enum spoolss_PrinterControl command)
1233 struct spoolss_SetPrinter r;
1235 r.in.handle = handle;
1236 r.in.info_ctr = info_ctr;
1237 r.in.devmode_ctr = devmode_ctr;
1238 r.in.secdesc_ctr = secdesc_ctr;
1239 r.in.command = command;
1241 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1243 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1244 "failed to call SetPrinter");
1245 torture_assert_werr_ok(tctx, r.out.result,
1246 "failed to call SetPrinter");
1248 return true;
1251 static bool test_SetPrinter_errors(struct torture_context *tctx,
1252 struct dcerpc_binding_handle *b,
1253 struct policy_handle *handle)
1255 struct spoolss_SetPrinter r;
1256 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1257 int i;
1259 struct spoolss_SetPrinterInfoCtr info_ctr;
1260 struct spoolss_DevmodeContainer devmode_ctr;
1261 struct sec_desc_buf secdesc_ctr;
1263 info_ctr.level = 0;
1264 info_ctr.info.info0 = NULL;
1266 ZERO_STRUCT(devmode_ctr);
1267 ZERO_STRUCT(secdesc_ctr);
1269 r.in.handle = handle;
1270 r.in.info_ctr = &info_ctr;
1271 r.in.devmode_ctr = &devmode_ctr;
1272 r.in.secdesc_ctr = &secdesc_ctr;
1273 r.in.command = 0;
1275 torture_comment(tctx, "Testing SetPrinter all zero\n");
1277 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1278 "failed to call SetPrinter");
1279 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1280 "failed to call SetPrinter");
1282 again:
1283 for (i=0; i < ARRAY_SIZE(levels); i++) {
1285 struct spoolss_SetPrinterInfo0 info0;
1286 struct spoolss_SetPrinterInfo1 info1;
1287 struct spoolss_SetPrinterInfo2 info2;
1288 struct spoolss_SetPrinterInfo3 info3;
1289 struct spoolss_SetPrinterInfo4 info4;
1290 struct spoolss_SetPrinterInfo5 info5;
1291 struct spoolss_SetPrinterInfo6 info6;
1292 struct spoolss_SetPrinterInfo7 info7;
1293 struct spoolss_SetPrinterInfo8 info8;
1294 struct spoolss_SetPrinterInfo9 info9;
1297 info_ctr.level = levels[i];
1298 switch (levels[i]) {
1299 case 0:
1300 ZERO_STRUCT(info0);
1301 info_ctr.info.info0 = &info0;
1302 break;
1303 case 1:
1304 ZERO_STRUCT(info1);
1305 info_ctr.info.info1 = &info1;
1306 break;
1307 case 2:
1308 ZERO_STRUCT(info2);
1309 info_ctr.info.info2 = &info2;
1310 break;
1311 case 3:
1312 ZERO_STRUCT(info3);
1313 info_ctr.info.info3 = &info3;
1314 break;
1315 case 4:
1316 ZERO_STRUCT(info4);
1317 info_ctr.info.info4 = &info4;
1318 break;
1319 case 5:
1320 ZERO_STRUCT(info5);
1321 info_ctr.info.info5 = &info5;
1322 break;
1323 case 6:
1324 ZERO_STRUCT(info6);
1325 info_ctr.info.info6 = &info6;
1326 break;
1327 case 7:
1328 ZERO_STRUCT(info7);
1329 info_ctr.info.info7 = &info7;
1330 break;
1331 case 8:
1332 ZERO_STRUCT(info8);
1333 info_ctr.info.info8 = &info8;
1334 break;
1335 case 9:
1336 ZERO_STRUCT(info9);
1337 info_ctr.info.info9 = &info9;
1338 break;
1341 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1342 info_ctr.level, r.in.command);
1344 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1345 "failed to call SetPrinter");
1347 switch (r.in.command) {
1348 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1349 /* is ignored for all levels other then 0 */
1350 if (info_ctr.level > 0) {
1351 /* ignored then */
1352 break;
1354 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1355 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1356 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1357 if (info_ctr.level > 0) {
1358 /* is invalid for all levels other then 0 */
1359 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1360 "unexpected error code returned");
1361 continue;
1362 } else {
1363 torture_assert_werr_ok(tctx, r.out.result,
1364 "failed to call SetPrinter with non 0 command");
1365 continue;
1367 break;
1369 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1370 /* FIXME: gd needs further investigation */
1371 default:
1372 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1373 "unexpected error code returned");
1374 continue;
1377 switch (info_ctr.level) {
1378 case 1:
1379 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1380 "unexpected error code returned");
1381 break;
1382 case 2:
1383 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1384 "unexpected error code returned");
1385 break;
1386 case 3:
1387 case 4:
1388 case 5:
1389 case 7:
1390 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1391 "unexpected error code returned");
1392 break;
1393 case 9:
1394 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1395 "unexpected error code returned");
1396 break;
1397 default:
1398 torture_assert_werr_ok(tctx, r.out.result,
1399 "failed to call SetPrinter");
1400 break;
1404 if (r.in.command < 5) {
1405 r.in.command++;
1406 goto again;
1409 return true;
1412 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1414 if ((r->level == 2) && (r->info.info2)) {
1415 r->info.info2->secdesc_ptr = 0;
1416 r->info.info2->devmode_ptr = 0;
1420 static bool test_PrinterInfo(struct torture_context *tctx,
1421 struct dcerpc_binding_handle *b,
1422 struct policy_handle *handle)
1424 NTSTATUS status;
1425 struct spoolss_SetPrinter s;
1426 struct spoolss_GetPrinter q;
1427 struct spoolss_GetPrinter q0;
1428 struct spoolss_SetPrinterInfoCtr info_ctr;
1429 union spoolss_PrinterInfo info;
1430 struct spoolss_DevmodeContainer devmode_ctr;
1431 struct sec_desc_buf secdesc_ctr;
1432 uint32_t needed;
1433 bool ret = true;
1434 int i;
1436 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1438 uint32_t status_list[] = {
1439 /* these do not stick
1440 PRINTER_STATUS_PAUSED,
1441 PRINTER_STATUS_ERROR,
1442 PRINTER_STATUS_PENDING_DELETION, */
1443 PRINTER_STATUS_PAPER_JAM,
1444 PRINTER_STATUS_PAPER_OUT,
1445 PRINTER_STATUS_MANUAL_FEED,
1446 PRINTER_STATUS_PAPER_PROBLEM,
1447 PRINTER_STATUS_OFFLINE,
1448 PRINTER_STATUS_IO_ACTIVE,
1449 PRINTER_STATUS_BUSY,
1450 PRINTER_STATUS_PRINTING,
1451 PRINTER_STATUS_OUTPUT_BIN_FULL,
1452 PRINTER_STATUS_NOT_AVAILABLE,
1453 PRINTER_STATUS_WAITING,
1454 PRINTER_STATUS_PROCESSING,
1455 PRINTER_STATUS_INITIALIZING,
1456 PRINTER_STATUS_WARMING_UP,
1457 PRINTER_STATUS_TONER_LOW,
1458 PRINTER_STATUS_NO_TONER,
1459 PRINTER_STATUS_PAGE_PUNT,
1460 PRINTER_STATUS_USER_INTERVENTION,
1461 PRINTER_STATUS_OUT_OF_MEMORY,
1462 PRINTER_STATUS_DOOR_OPEN,
1463 PRINTER_STATUS_SERVER_UNKNOWN,
1464 PRINTER_STATUS_POWER_SAVE,
1465 /* these do not stick
1466 0x02000000,
1467 0x04000000,
1468 0x08000000,
1469 0x10000000,
1470 0x20000000,
1471 0x40000000,
1472 0x80000000 */
1474 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1475 uint32_t attribute_list[] = {
1476 PRINTER_ATTRIBUTE_QUEUED,
1477 /* fails with WERR_INVALID_DATATYPE:
1478 PRINTER_ATTRIBUTE_DIRECT, */
1479 /* does not stick
1480 PRINTER_ATTRIBUTE_DEFAULT, */
1481 PRINTER_ATTRIBUTE_SHARED,
1482 /* does not stick
1483 PRINTER_ATTRIBUTE_NETWORK, */
1484 PRINTER_ATTRIBUTE_HIDDEN,
1485 PRINTER_ATTRIBUTE_LOCAL,
1486 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1487 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1488 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1489 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1490 /* does not stick
1491 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1492 /* fails with WERR_INVALID_DATATYPE:
1493 PRINTER_ATTRIBUTE_RAW_ONLY, */
1494 /* these do not stick
1495 PRINTER_ATTRIBUTE_PUBLISHED,
1496 PRINTER_ATTRIBUTE_FAX,
1497 PRINTER_ATTRIBUTE_TS,
1498 0x00010000,
1499 0x00020000,
1500 0x00040000,
1501 0x00080000,
1502 0x00100000,
1503 0x00200000,
1504 0x00400000,
1505 0x00800000,
1506 0x01000000,
1507 0x02000000,
1508 0x04000000,
1509 0x08000000,
1510 0x10000000,
1511 0x20000000,
1512 0x40000000,
1513 0x80000000 */
1516 ZERO_STRUCT(devmode_ctr);
1517 ZERO_STRUCT(secdesc_ctr);
1519 s.in.handle = handle;
1520 s.in.command = 0;
1521 s.in.info_ctr = &info_ctr;
1522 s.in.devmode_ctr = &devmode_ctr;
1523 s.in.secdesc_ctr = &secdesc_ctr;
1525 q.in.handle = handle;
1526 q.out.info = &info;
1527 q0 = q;
1529 #define TESTGETCALL(call, r) \
1530 r.in.buffer = NULL; \
1531 r.in.offered = 0;\
1532 r.out.needed = &needed; \
1533 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1534 if (!NT_STATUS_IS_OK(status)) { \
1535 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1536 r.in.level, nt_errstr(status), __location__); \
1537 ret = false; \
1538 break; \
1540 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1541 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1542 r.in.buffer = &blob; \
1543 r.in.offered = needed; \
1545 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1546 if (!NT_STATUS_IS_OK(status)) { \
1547 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1548 r.in.level, nt_errstr(status), __location__); \
1549 ret = false; \
1550 break; \
1552 if (!W_ERROR_IS_OK(r.out.result)) { \
1553 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1554 r.in.level, win_errstr(r.out.result), __location__); \
1555 ret = false; \
1556 break; \
1560 #define TESTSETCALL_EXP(call, r, err) \
1561 clear_info2(&info_ctr);\
1562 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1563 if (!NT_STATUS_IS_OK(status)) { \
1564 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1565 r.in.info_ctr->level, nt_errstr(status), __location__); \
1566 ret = false; \
1567 break; \
1569 if (!W_ERROR_IS_OK(err)) { \
1570 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1571 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1572 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1573 ret = false; \
1575 break; \
1577 if (!W_ERROR_IS_OK(r.out.result)) { \
1578 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1579 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1580 ret = false; \
1581 break; \
1584 #define TESTSETCALL(call, r) \
1585 TESTSETCALL_EXP(call, r, WERR_OK)
1587 #define STRING_EQUAL(s1, s2, field) \
1588 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1589 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1590 #field, s2, __location__); \
1591 ret = false; \
1592 break; \
1595 #define MEM_EQUAL(s1, s2, length, field) \
1596 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1597 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1598 #field, (const char *)s2, __location__); \
1599 ret = false; \
1600 break; \
1603 #define INT_EQUAL(i1, i2, field) \
1604 if (i1 != i2) { \
1605 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1606 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1607 ret = false; \
1608 break; \
1611 #define SD_EQUAL(sd1, sd2, field) \
1612 if (!security_descriptor_equal(sd1, sd2)) { \
1613 torture_comment(tctx, "Failed to set %s (%s)\n", \
1614 #field, __location__); \
1615 ret = false; \
1616 break; \
1619 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1620 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1621 q.in.level = lvl1; \
1622 TESTGETCALL(GetPrinter, q) \
1623 info_ctr.level = lvl1; \
1624 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1625 info_ctr.info.info ## lvl1->field1 = value;\
1626 TESTSETCALL_EXP(SetPrinter, s, err) \
1627 info_ctr.info.info ## lvl1->field1 = ""; \
1628 TESTGETCALL(GetPrinter, q) \
1629 info_ctr.info.info ## lvl1->field1 = value; \
1630 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1631 q.in.level = lvl2; \
1632 TESTGETCALL(GetPrinter, q) \
1633 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1634 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1635 } while (0)
1637 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1638 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1639 } while (0);
1641 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1642 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1643 q.in.level = lvl1; \
1644 TESTGETCALL(GetPrinter, q) \
1645 info_ctr.level = lvl1; \
1646 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1647 info_ctr.info.info ## lvl1->field1 = value; \
1648 TESTSETCALL(SetPrinter, s) \
1649 info_ctr.info.info ## lvl1->field1 = 0; \
1650 TESTGETCALL(GetPrinter, q) \
1651 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1652 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1653 q.in.level = lvl2; \
1654 TESTGETCALL(GetPrinter, q) \
1655 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1656 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1657 } while (0)
1659 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1660 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1661 } while (0)
1663 q0.in.level = 0;
1664 do { TESTGETCALL(GetPrinter, q0) } while (0);
1666 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1667 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1669 /* level 0 printername does not stick */
1670 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1671 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1672 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1673 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1674 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1675 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1676 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1677 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1678 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1679 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1680 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1681 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1682 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1683 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1684 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1686 /* servername can be set but does not stick
1687 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1688 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1689 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1692 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1693 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1694 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1695 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1696 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1698 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1699 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1700 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1701 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1702 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1703 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1704 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1705 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1706 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1707 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1709 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1710 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1711 attribute_list[i],
1712 (attribute_list[i] | default_attribute)
1713 ); */
1714 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1715 attribute_list[i],
1716 (attribute_list[i] | default_attribute)
1718 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1719 attribute_list[i],
1720 (attribute_list[i] | default_attribute)
1722 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1723 attribute_list[i],
1724 (attribute_list[i] | default_attribute)
1726 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1727 attribute_list[i],
1728 (attribute_list[i] | default_attribute)
1729 ); */
1730 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1731 attribute_list[i],
1732 (attribute_list[i] | default_attribute)
1734 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1735 attribute_list[i],
1736 (attribute_list[i] | default_attribute)
1738 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1739 attribute_list[i],
1740 (attribute_list[i] | default_attribute)
1742 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1743 attribute_list[i],
1744 (attribute_list[i] | default_attribute)
1745 ); */
1746 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1747 attribute_list[i],
1748 (attribute_list[i] | default_attribute)
1750 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1751 attribute_list[i],
1752 (attribute_list[i] | default_attribute)
1754 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1755 attribute_list[i],
1756 (attribute_list[i] | default_attribute)
1760 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1761 /* level 2 sets do not stick
1762 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1763 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1764 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1765 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1766 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1767 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1770 /* priorities need to be between 0 and 99
1771 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1772 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1773 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1774 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1775 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1776 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1777 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1778 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1779 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1781 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1782 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1784 /* does not stick
1785 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1786 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1788 /* does not stick
1789 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1790 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1792 /* FIXME: gd also test devmode and secdesc behavior */
1795 /* verify composition of level 1 description field */
1796 const char *description;
1797 const char *tmp;
1799 q0.in.level = 1;
1800 do { TESTGETCALL(GetPrinter, q0) } while (0);
1802 description = talloc_strdup(tctx, q0.out.info->info1.description);
1804 q0.in.level = 2;
1805 do { TESTGETCALL(GetPrinter, q0) } while (0);
1807 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1808 q0.out.info->info2.printername,
1809 q0.out.info->info2.drivername,
1810 q0.out.info->info2.location);
1812 do { STRING_EQUAL(description, tmp, "description")} while (0);
1815 return ret;
1818 static bool test_security_descriptor_equal(struct torture_context *tctx,
1819 const struct security_descriptor *sd1,
1820 const struct security_descriptor *sd2)
1822 if (sd1 == sd2) {
1823 return true;
1826 if (!sd1 || !sd2) {
1827 torture_comment(tctx, "%s\n", __location__);
1828 return false;
1831 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1832 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1834 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1835 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1837 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1838 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1839 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1840 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1841 return false;
1843 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1844 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1845 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1846 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1847 return false;
1850 return true;
1853 static bool test_sd_set_level(struct torture_context *tctx,
1854 struct dcerpc_binding_handle *b,
1855 struct policy_handle *handle,
1856 uint32_t level,
1857 struct security_descriptor *sd)
1859 struct spoolss_SetPrinterInfoCtr info_ctr;
1860 struct spoolss_DevmodeContainer devmode_ctr;
1861 struct sec_desc_buf secdesc_ctr;
1862 union spoolss_SetPrinterInfo sinfo;
1864 ZERO_STRUCT(devmode_ctr);
1865 ZERO_STRUCT(secdesc_ctr);
1867 switch (level) {
1868 case 2: {
1869 union spoolss_PrinterInfo info;
1870 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1871 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1873 info_ctr.level = 2;
1874 info_ctr.info = sinfo;
1876 break;
1878 case 3: {
1879 struct spoolss_SetPrinterInfo3 info3;
1881 info3.sec_desc_ptr = 0;
1883 info_ctr.level = 3;
1884 info_ctr.info.info3 = &info3;
1886 break;
1888 default:
1889 return false;
1892 secdesc_ctr.sd = sd;
1894 torture_assert(tctx,
1895 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1897 return true;
1900 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1901 struct dcerpc_binding_handle *b,
1902 struct policy_handle *handle)
1904 union spoolss_PrinterInfo info;
1905 struct security_descriptor *sd1, *sd2;
1906 int i;
1908 /* just compare level 2 and level 3 */
1910 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1912 sd1 = info.info2.secdesc;
1914 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1916 sd2 = info.info3.secdesc;
1918 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1919 "SD level 2 != SD level 3");
1922 /* query level 2, set level 2, query level 2 */
1924 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1926 sd1 = info.info2.secdesc;
1928 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1930 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1932 sd2 = info.info2.secdesc;
1933 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1934 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1935 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1938 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1939 "SD level 2 != SD level 2 after SD has been set via level 2");
1942 /* query level 2, set level 3, query level 2 */
1944 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1946 sd1 = info.info2.secdesc;
1948 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1950 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1952 sd2 = info.info2.secdesc;
1954 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1955 "SD level 2 != SD level 2 after SD has been set via level 3");
1957 /* set modified sd level 3, query level 2 */
1959 for (i=0; i < 93; i++) {
1960 struct security_ace a;
1961 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1962 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1963 a.flags = 0;
1964 a.size = 0; /* autogenerated */
1965 a.access_mask = 0;
1966 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1967 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1970 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1972 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1973 sd2 = info.info2.secdesc;
1975 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1976 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1977 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1980 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1981 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1984 return true;
1988 * wrapper call that saves original sd, runs tests, and restores sd
1991 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1992 struct dcerpc_binding_handle *b,
1993 struct policy_handle *handle)
1995 union spoolss_PrinterInfo info;
1996 struct security_descriptor *sd;
1997 bool ret = true;
1999 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2001 /* save original sd */
2003 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2004 "failed to get initial security descriptor");
2006 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2008 /* run tests */
2010 ret = test_PrinterInfo_SDs(tctx, b, handle);
2012 /* restore original sd */
2014 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2015 "failed to restore initial security descriptor");
2017 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2018 ret ? "succeeded" : "failed");
2021 return ret;
2024 static bool test_devmode_set_level(struct torture_context *tctx,
2025 struct dcerpc_binding_handle *b,
2026 struct policy_handle *handle,
2027 uint32_t level,
2028 struct spoolss_DeviceMode *devmode)
2030 struct spoolss_SetPrinterInfoCtr info_ctr;
2031 struct spoolss_DevmodeContainer devmode_ctr;
2032 struct sec_desc_buf secdesc_ctr;
2033 union spoolss_SetPrinterInfo sinfo;
2035 ZERO_STRUCT(devmode_ctr);
2036 ZERO_STRUCT(secdesc_ctr);
2038 switch (level) {
2039 case 2: {
2040 union spoolss_PrinterInfo info;
2041 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2042 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2044 info_ctr.level = 2;
2045 info_ctr.info = sinfo;
2047 break;
2049 case 8: {
2050 struct spoolss_SetPrinterInfo8 info8;
2052 info8.devmode_ptr = 0;
2054 info_ctr.level = 8;
2055 info_ctr.info.info8 = &info8;
2057 break;
2059 default:
2060 return false;
2063 devmode_ctr.devmode = devmode;
2065 torture_assert(tctx,
2066 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2068 return true;
2072 static bool test_devicemode_equal(struct torture_context *tctx,
2073 const struct spoolss_DeviceMode *d1,
2074 const struct spoolss_DeviceMode *d2)
2076 if (d1 == d2) {
2077 return true;
2080 if (!d1 || !d2) {
2081 torture_comment(tctx, "%s\n", __location__);
2082 return false;
2084 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2085 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2086 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2087 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2088 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2089 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2090 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2091 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2092 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2093 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2094 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2095 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2096 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2097 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2098 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2099 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2100 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2101 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2102 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2103 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2104 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2105 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2106 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2107 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2108 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2109 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2110 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2111 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2112 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2113 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2114 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2115 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2116 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2117 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2118 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2120 return true;
2123 static bool test_devicemode_full(struct torture_context *tctx,
2124 struct dcerpc_binding_handle *b,
2125 struct policy_handle *handle)
2127 struct spoolss_SetPrinter s;
2128 struct spoolss_GetPrinter q;
2129 struct spoolss_GetPrinter q0;
2130 struct spoolss_SetPrinterInfoCtr info_ctr;
2131 struct spoolss_SetPrinterInfo8 info8;
2132 union spoolss_PrinterInfo info;
2133 struct spoolss_DevmodeContainer devmode_ctr;
2134 struct sec_desc_buf secdesc_ctr;
2135 uint32_t needed;
2136 bool ret = true;
2137 NTSTATUS status;
2139 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2140 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2141 q.in.level = lvl1; \
2142 TESTGETCALL(GetPrinter, q) \
2143 info_ctr.level = lvl1; \
2144 if (lvl1 == 2) {\
2145 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2146 } else if (lvl1 == 8) {\
2147 info_ctr.info.info ## lvl1 = &info8; \
2149 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2150 devmode_ctr.devmode->field1 = value; \
2151 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2152 if (W_ERROR_IS_OK(expected_result)) { \
2153 TESTGETCALL(GetPrinter, q) \
2154 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2155 q.in.level = lvl2; \
2156 TESTGETCALL(GetPrinter, q) \
2157 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2159 } while (0)
2161 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2162 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2163 } while (0)
2165 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2166 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2167 } while (0)
2169 ZERO_STRUCT(devmode_ctr);
2170 ZERO_STRUCT(secdesc_ctr);
2171 ZERO_STRUCT(info8);
2173 s.in.handle = handle;
2174 s.in.command = 0;
2175 s.in.info_ctr = &info_ctr;
2176 s.in.devmode_ctr = &devmode_ctr;
2177 s.in.secdesc_ctr = &secdesc_ctr;
2179 q.in.handle = handle;
2180 q.out.info = &info;
2181 q0 = q;
2183 #if 0
2184 const char *devicename;/* [charset(UTF16)] */
2185 enum spoolss_DeviceModeSpecVersion specversion;
2186 uint16_t driverversion;
2187 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2188 uint32_t fields;
2189 #endif
2190 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2191 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2192 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2193 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);
2194 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2196 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2197 torture_assert(tctx,
2198 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2199 "failed to set devmode");
2201 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);
2202 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2204 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2205 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2206 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2207 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2208 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2209 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2210 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2211 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2212 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2213 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2214 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2215 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2216 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2217 #if 0
2218 const char *formname;/* [charset(UTF16)] */
2219 #endif
2220 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2221 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2222 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2223 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2224 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2225 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2226 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2227 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2228 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2229 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2230 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2231 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2232 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2233 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2235 return ret;
2238 static bool call_OpenPrinterEx(struct torture_context *tctx,
2239 struct dcerpc_pipe *p,
2240 const char *name,
2241 struct spoolss_DeviceMode *devmode,
2242 struct policy_handle *handle);
2244 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2245 struct dcerpc_pipe *p,
2246 struct policy_handle *handle,
2247 const char *name)
2249 union spoolss_PrinterInfo info;
2250 struct spoolss_DeviceMode *devmode;
2251 struct spoolss_DeviceMode *devmode2;
2252 struct policy_handle handle_devmode;
2253 struct dcerpc_binding_handle *b = p->binding_handle;
2255 /* simply compare level8 and level2 devmode */
2257 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2259 devmode = info.info8.devmode;
2261 if (devmode && devmode->size == 0) {
2262 torture_fail(tctx,
2263 "devmode of zero size!");
2266 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2268 devmode2 = info.info2.devmode;
2270 if (devmode2 && devmode2->size == 0) {
2271 torture_fail(tctx,
2272 "devmode of zero size!");
2275 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2276 "DM level 8 != DM level 2");
2279 /* set devicemode level 8 and see if it persists */
2281 devmode->copies = 93;
2282 devmode->formname = talloc_strdup(tctx, "Legal");
2284 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2286 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2288 devmode2 = info.info8.devmode;
2290 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2291 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2293 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2295 devmode2 = info.info2.devmode;
2297 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2298 "modified DM level 8 != DM level 2");
2301 /* set devicemode level 2 and see if it persists */
2303 devmode->copies = 39;
2304 devmode->formname = talloc_strdup(tctx, "Executive");
2306 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2308 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2310 devmode2 = info.info8.devmode;
2312 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2313 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2315 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2317 devmode2 = info.info2.devmode;
2319 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2320 "modified DM level 8 != DM level 2");
2323 /* check every single bit in public part of devicemode */
2325 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2326 "failed to set every single devicemode component");
2329 /* change formname upon open and see if it persists in getprinter calls */
2331 devmode->formname = talloc_strdup(tctx, "A4");
2332 devmode->copies = 42;
2334 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2335 "failed to open printer handle");
2337 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2339 devmode2 = info.info8.devmode;
2341 if (strequal(devmode->devicename, devmode2->devicename)) {
2342 torture_warning(tctx, "devicenames are the same\n");
2343 } else {
2344 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2345 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2348 if (strequal(devmode->formname, devmode2->formname)) {
2349 torture_warning(tctx, "formname are the same\n");
2350 } else {
2351 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2352 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2355 if (devmode->copies == devmode2->copies) {
2356 torture_warning(tctx, "copies are the same\n");
2357 } else {
2358 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2359 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2362 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2364 devmode2 = info.info2.devmode;
2366 if (strequal(devmode->devicename, devmode2->devicename)) {
2367 torture_warning(tctx, "devicenames are the same\n");
2368 } else {
2369 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2370 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2373 if (strequal(devmode->formname, devmode2->formname)) {
2374 torture_warning(tctx, "formname is the same\n");
2375 } else {
2376 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2377 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2380 if (devmode->copies == devmode2->copies) {
2381 torture_warning(tctx, "copies are the same\n");
2382 } else {
2383 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2384 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2387 test_ClosePrinter(tctx, b, &handle_devmode);
2389 return true;
2393 * wrapper call that saves original devmode, runs tests, and restores devmode
2396 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2397 struct dcerpc_pipe *p,
2398 struct policy_handle *handle,
2399 const char *name,
2400 struct spoolss_DeviceMode *addprinter_devmode)
2402 union spoolss_PrinterInfo info;
2403 struct spoolss_DeviceMode *devmode;
2404 bool ret = true;
2405 struct dcerpc_binding_handle *b = p->binding_handle;
2407 torture_comment(tctx, "Testing Printer Devicemodes\n");
2409 /* save original devmode */
2411 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2412 "failed to get initial global devicemode");
2414 devmode = info.info8.devmode;
2416 if (devmode && devmode->size == 0) {
2417 torture_fail(tctx,
2418 "devmode of zero size!");
2421 if (addprinter_devmode) {
2422 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2423 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2427 /* run tests */
2429 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2431 /* restore original devmode */
2433 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2434 "failed to restore initial global device mode");
2436 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2437 ret ? "succeeded" : "failed");
2440 return ret;
2443 bool test_ClosePrinter(struct torture_context *tctx,
2444 struct dcerpc_binding_handle *b,
2445 struct policy_handle *handle)
2447 NTSTATUS status;
2448 struct spoolss_ClosePrinter r;
2450 r.in.handle = handle;
2451 r.out.handle = handle;
2453 torture_comment(tctx, "Testing ClosePrinter\n");
2455 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2456 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2457 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2459 return true;
2462 static bool test_GetForm_args(struct torture_context *tctx,
2463 struct dcerpc_binding_handle *b,
2464 struct policy_handle *handle,
2465 const char *form_name,
2466 uint32_t level,
2467 union spoolss_FormInfo *info_p)
2469 NTSTATUS status;
2470 struct spoolss_GetForm r;
2471 uint32_t needed;
2473 r.in.handle = handle;
2474 r.in.form_name = form_name;
2475 r.in.level = level;
2476 r.in.buffer = NULL;
2477 r.in.offered = 0;
2478 r.out.needed = &needed;
2480 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2482 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2483 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2485 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2486 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2487 r.in.buffer = &blob;
2488 r.in.offered = needed;
2489 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2490 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2492 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2494 torture_assert(tctx, r.out.info, "No form info returned");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2501 if (info_p) {
2502 *info_p = *r.out.info;
2505 return true;
2508 static bool test_GetForm(struct torture_context *tctx,
2509 struct dcerpc_binding_handle *b,
2510 struct policy_handle *handle,
2511 const char *form_name,
2512 uint32_t level)
2514 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2517 static bool test_EnumForms(struct torture_context *tctx,
2518 struct dcerpc_binding_handle *b,
2519 struct policy_handle *handle,
2520 bool print_server,
2521 uint32_t level,
2522 uint32_t *count_p,
2523 union spoolss_FormInfo **info_p)
2525 struct spoolss_EnumForms r;
2526 uint32_t needed;
2527 uint32_t count;
2528 union spoolss_FormInfo *info;
2530 r.in.handle = handle;
2531 r.in.level = level;
2532 r.in.buffer = NULL;
2533 r.in.offered = 0;
2534 r.out.needed = &needed;
2535 r.out.count = &count;
2536 r.out.info = &info;
2538 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2540 torture_assert_ntstatus_ok(tctx,
2541 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2542 "EnumForms failed");
2544 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2545 torture_skip(tctx, "EnumForms level 2 not supported");
2548 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2549 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2552 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2553 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2554 r.in.buffer = &blob;
2555 r.in.offered = needed;
2557 torture_assert_ntstatus_ok(tctx,
2558 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2559 "EnumForms failed");
2561 torture_assert(tctx, info, "No forms returned");
2564 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2566 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2568 if (info_p) {
2569 *info_p = info;
2571 if (count_p) {
2572 *count_p = count;
2575 return true;
2578 static bool test_EnumForms_all(struct torture_context *tctx,
2579 struct dcerpc_binding_handle *b,
2580 struct policy_handle *handle,
2581 bool print_server)
2583 uint32_t levels[] = { 1, 2 };
2584 int i, j;
2586 for (i=0; i<ARRAY_SIZE(levels); i++) {
2588 uint32_t count = 0;
2589 union spoolss_FormInfo *info = NULL;
2591 torture_assert(tctx,
2592 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2593 "failed to enum forms");
2595 for (j = 0; j < count; j++) {
2596 if (!print_server) {
2597 torture_assert(tctx,
2598 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2599 "failed to get form");
2604 return true;
2607 static bool test_EnumForms_find_one(struct torture_context *tctx,
2608 struct dcerpc_binding_handle *b,
2609 struct policy_handle *handle,
2610 bool print_server,
2611 const char *form_name)
2613 union spoolss_FormInfo *info;
2614 uint32_t count;
2615 bool found = false;
2616 int i;
2618 torture_assert(tctx,
2619 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2620 "failed to enumerate forms");
2622 for (i=0; i<count; i++) {
2623 if (strequal(form_name, info[i].info1.form_name)) {
2624 found = true;
2625 break;
2629 return found;
2632 static bool test_DeleteForm(struct torture_context *tctx,
2633 struct dcerpc_binding_handle *b,
2634 struct policy_handle *handle,
2635 const char *form_name,
2636 WERROR expected_result)
2638 struct spoolss_DeleteForm r;
2640 r.in.handle = handle;
2641 r.in.form_name = form_name;
2643 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2645 torture_assert_ntstatus_ok(tctx,
2646 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2647 "DeleteForm failed");
2648 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2649 "DeleteForm gave unexpected result");
2650 if (W_ERROR_IS_OK(r.out.result)) {
2651 torture_assert_ntstatus_ok(tctx,
2652 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2653 "2nd DeleteForm failed");
2654 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2655 "2nd DeleteForm failed");
2658 return true;
2661 static bool test_AddForm(struct torture_context *tctx,
2662 struct dcerpc_binding_handle *b,
2663 struct policy_handle *handle,
2664 uint32_t level,
2665 union spoolss_AddFormInfo *info,
2666 WERROR expected_result)
2668 struct spoolss_AddForm r;
2670 if (level != 1) {
2671 torture_skip(tctx, "only level 1 supported");
2674 r.in.handle = handle;
2675 r.in.level = level;
2676 r.in.info = *info;
2678 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2679 r.in.info.info1->form_name, r.in.level,
2680 r.in.info.info1->flags);
2682 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2683 "AddForm failed");
2684 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2685 "AddForm gave unexpected result");
2687 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2688 "2nd AddForm failed");
2689 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2690 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2691 "2nd AddForm gave unexpected result");
2692 } else {
2693 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2694 "2nd AddForm gave unexpected result");
2697 return true;
2700 static bool test_SetForm(struct torture_context *tctx,
2701 struct dcerpc_binding_handle *b,
2702 struct policy_handle *handle,
2703 const char *form_name,
2704 uint32_t level,
2705 union spoolss_AddFormInfo *info)
2707 struct spoolss_SetForm r;
2709 r.in.handle = handle;
2710 r.in.form_name = form_name;
2711 r.in.level = level;
2712 r.in.info = *info;
2714 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2715 form_name, r.in.level);
2717 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2718 "SetForm failed");
2720 torture_assert_werr_ok(tctx, r.out.result,
2721 "SetForm failed");
2723 return true;
2726 static bool test_GetForm_winreg(struct torture_context *tctx,
2727 struct dcerpc_binding_handle *b,
2728 struct policy_handle *handle,
2729 const char *key_name,
2730 const char *form_name,
2731 enum winreg_Type *w_type,
2732 uint32_t *w_size,
2733 uint32_t *w_length,
2734 uint8_t **w_data);
2736 static bool test_Forms_args(struct torture_context *tctx,
2737 struct dcerpc_binding_handle *b,
2738 struct policy_handle *handle,
2739 bool print_server,
2740 const char *printer_name,
2741 struct dcerpc_binding_handle *winreg_handle,
2742 struct policy_handle *hive_handle,
2743 const char *form_name,
2744 struct spoolss_AddFormInfo1 *info1,
2745 WERROR expected_add_result,
2746 WERROR expected_delete_result)
2748 union spoolss_FormInfo info;
2749 union spoolss_AddFormInfo add_info;
2751 enum winreg_Type w_type;
2752 uint32_t w_size;
2753 uint32_t w_length;
2754 uint8_t *w_data;
2756 add_info.info1 = info1;
2758 torture_assert(tctx,
2759 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2760 "failed to add form");
2762 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2764 struct spoolss_FormInfo1 i1;
2766 torture_assert(tctx,
2767 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2768 "failed to get form via winreg");
2770 i1.size.width = IVAL(w_data, 0);
2771 i1.size.height = IVAL(w_data, 4);
2772 i1.area.left = IVAL(w_data, 8);
2773 i1.area.top = IVAL(w_data, 12);
2774 i1.area.right = IVAL(w_data, 16);
2775 i1.area.bottom = IVAL(w_data, 20);
2776 /* skip index here */
2777 i1.flags = IVAL(w_data, 28);
2779 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2780 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2781 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2782 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2783 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2784 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2785 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2786 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2787 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2788 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2791 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2792 torture_assert(tctx,
2793 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2794 "failed to get added form");
2796 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2797 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2798 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2799 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2800 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2801 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2802 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2804 if (winreg_handle && hive_handle) {
2806 struct spoolss_FormInfo1 i1;
2808 i1.size.width = IVAL(w_data, 0);
2809 i1.size.height = IVAL(w_data, 4);
2810 i1.area.left = IVAL(w_data, 8);
2811 i1.area.top = IVAL(w_data, 12);
2812 i1.area.right = IVAL(w_data, 16);
2813 i1.area.bottom = IVAL(w_data, 20);
2814 /* skip index here */
2815 i1.flags = IVAL(w_data, 28);
2817 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2818 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2819 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2820 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2821 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2822 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2823 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2826 add_info.info1->size.width = 1234;
2828 torture_assert(tctx,
2829 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2830 "failed to set form");
2831 torture_assert(tctx,
2832 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2833 "failed to get setted form");
2835 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2838 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2839 torture_assert(tctx,
2840 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2841 "Newly added form not found in enum call");
2844 torture_assert(tctx,
2845 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2846 "failed to delete form");
2848 return true;
2851 static bool test_Forms(struct torture_context *tctx,
2852 struct dcerpc_binding_handle *b,
2853 struct policy_handle *handle,
2854 bool print_server,
2855 const char *printer_name,
2856 struct dcerpc_binding_handle *winreg_handle,
2857 struct policy_handle *hive_handle)
2859 const struct spoolss_FormSize size = {
2860 .width = 50,
2861 .height = 25
2863 const struct spoolss_FormArea area = {
2864 .left = 5,
2865 .top = 10,
2866 .right = 45,
2867 .bottom = 15
2869 int i;
2871 struct {
2872 struct spoolss_AddFormInfo1 info1;
2873 WERROR expected_add_result;
2874 WERROR expected_delete_result;
2875 } forms[] = {
2877 .info1 = {
2878 .flags = SPOOLSS_FORM_USER,
2879 .form_name = "testform_user",
2880 .size = size,
2881 .area = area,
2883 .expected_add_result = WERR_OK,
2884 .expected_delete_result = WERR_OK
2887 weird, we can add a builtin form but we can never remove it
2888 again - gd
2891 .info1 = {
2892 .flags = SPOOLSS_FORM_BUILTIN,
2893 .form_name = "testform_builtin",
2894 .size = size,
2895 .area = area,
2897 .expected_add_result = WERR_OK,
2898 .expected_delete_result = WERR_INVALID_PARAM,
2902 .info1 = {
2903 .flags = SPOOLSS_FORM_PRINTER,
2904 .form_name = "testform_printer",
2905 .size = size,
2906 .area = area,
2908 .expected_add_result = WERR_OK,
2909 .expected_delete_result = WERR_OK
2912 .info1 = {
2913 .flags = SPOOLSS_FORM_USER,
2914 .form_name = "Letter",
2915 .size = size,
2916 .area = area,
2918 .expected_add_result = WERR_FILE_EXISTS,
2919 .expected_delete_result = WERR_INVALID_PARAM
2922 .info1 = {
2923 .flags = SPOOLSS_FORM_BUILTIN,
2924 .form_name = "Letter",
2925 .size = size,
2926 .area = area,
2928 .expected_add_result = WERR_FILE_EXISTS,
2929 .expected_delete_result = WERR_INVALID_PARAM
2932 .info1 = {
2933 .flags = SPOOLSS_FORM_PRINTER,
2934 .form_name = "Letter",
2935 .size = size,
2936 .area = area,
2938 .expected_add_result = WERR_FILE_EXISTS,
2939 .expected_delete_result = WERR_INVALID_PARAM
2942 .info1 = {
2943 .flags = 12345,
2944 .form_name = "invalid_flags",
2945 .size = size,
2946 .area = area,
2948 .expected_add_result = WERR_INVALID_PARAM,
2949 .expected_delete_result = WERR_INVALID_FORM_NAME
2954 for (i=0; i < ARRAY_SIZE(forms); i++) {
2955 torture_assert(tctx,
2956 test_Forms_args(tctx, b, handle, print_server, printer_name,
2957 winreg_handle, hive_handle,
2958 forms[i].info1.form_name,
2959 &forms[i].info1,
2960 forms[i].expected_add_result,
2961 forms[i].expected_delete_result),
2962 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2965 return true;
2968 static bool test_EnumPorts_old(struct torture_context *tctx,
2969 void *private_data)
2971 struct test_spoolss_context *ctx =
2972 talloc_get_type_abort(private_data, struct test_spoolss_context);
2974 NTSTATUS status;
2975 struct spoolss_EnumPorts r;
2976 uint32_t needed;
2977 uint32_t count;
2978 union spoolss_PortInfo *info;
2979 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2980 struct dcerpc_binding_handle *b = p->binding_handle;
2982 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2983 dcerpc_server_name(p));
2984 r.in.level = 2;
2985 r.in.buffer = NULL;
2986 r.in.offered = 0;
2987 r.out.needed = &needed;
2988 r.out.count = &count;
2989 r.out.info = &info;
2991 torture_comment(tctx, "Testing EnumPorts\n");
2993 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2995 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2997 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2998 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2999 r.in.buffer = &blob;
3000 r.in.offered = needed;
3002 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3003 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3004 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3006 torture_assert(tctx, info, "No ports returned");
3009 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3011 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3013 return true;
3016 static bool test_AddPort(struct torture_context *tctx,
3017 void *private_data)
3019 struct test_spoolss_context *ctx =
3020 talloc_get_type_abort(private_data, struct test_spoolss_context);
3022 NTSTATUS status;
3023 struct spoolss_AddPort r;
3024 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3025 struct dcerpc_binding_handle *b = p->binding_handle;
3027 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3028 dcerpc_server_name(p));
3029 r.in.unknown = 0;
3030 r.in.monitor_name = "foo";
3032 torture_comment(tctx, "Testing AddPort\n");
3034 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3036 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3038 /* win2k3 returns WERR_NOT_SUPPORTED */
3040 #if 0
3042 if (!W_ERROR_IS_OK(r.out.result)) {
3043 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3044 return false;
3047 #endif
3049 return true;
3052 static bool test_GetJob_args(struct torture_context *tctx,
3053 struct dcerpc_binding_handle *b,
3054 struct policy_handle *handle,
3055 uint32_t job_id,
3056 uint32_t level,
3057 union spoolss_JobInfo *info_p)
3059 NTSTATUS status;
3060 struct spoolss_GetJob r;
3061 union spoolss_JobInfo info;
3062 uint32_t needed;
3064 r.in.handle = handle;
3065 r.in.job_id = job_id;
3066 r.in.level = level;
3067 r.in.buffer = NULL;
3068 r.in.offered = 0;
3069 r.out.needed = &needed;
3070 r.out.info = &info;
3072 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3074 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3075 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3076 if (level == 0) {
3077 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3080 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3081 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3082 r.in.buffer = &blob;
3083 r.in.offered = needed;
3085 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3086 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3089 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3090 torture_assert(tctx, r.out.info, "No job info returned");
3092 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3094 if (info_p) {
3095 *info_p = *r.out.info;
3098 return true;
3101 static bool test_GetJob(struct torture_context *tctx,
3102 struct dcerpc_binding_handle *b,
3103 struct policy_handle *handle,
3104 uint32_t job_id)
3106 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3107 uint32_t i;
3109 for (i=0; i < ARRAY_SIZE(levels); i++) {
3110 torture_assert(tctx,
3111 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3112 "GetJob failed");
3115 return true;
3118 static bool test_SetJob(struct torture_context *tctx,
3119 struct dcerpc_binding_handle *b,
3120 struct policy_handle *handle,
3121 uint32_t job_id,
3122 struct spoolss_JobInfoContainer *ctr,
3123 enum spoolss_JobControl command)
3125 NTSTATUS status;
3126 struct spoolss_SetJob r;
3128 r.in.handle = handle;
3129 r.in.job_id = job_id;
3130 r.in.ctr = ctr;
3131 r.in.command = command;
3133 switch (command) {
3134 case SPOOLSS_JOB_CONTROL_PAUSE:
3135 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3136 break;
3137 case SPOOLSS_JOB_CONTROL_RESUME:
3138 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3139 break;
3140 case SPOOLSS_JOB_CONTROL_CANCEL:
3141 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3142 break;
3143 case SPOOLSS_JOB_CONTROL_RESTART:
3144 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3145 break;
3146 case SPOOLSS_JOB_CONTROL_DELETE:
3147 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3148 break;
3149 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3150 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3151 break;
3152 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3153 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3154 break;
3155 case SPOOLSS_JOB_CONTROL_RETAIN:
3156 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3157 break;
3158 case SPOOLSS_JOB_CONTROL_RELEASE:
3159 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3160 break;
3161 default:
3162 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3163 break;
3166 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3167 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3168 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3170 return true;
3173 static bool test_AddJob(struct torture_context *tctx,
3174 struct dcerpc_binding_handle *b,
3175 struct policy_handle *handle)
3177 NTSTATUS status;
3178 struct spoolss_AddJob r;
3179 uint32_t needed;
3181 r.in.level = 0;
3182 r.in.handle = handle;
3183 r.in.offered = 0;
3184 r.out.needed = &needed;
3185 r.in.buffer = r.out.buffer = NULL;
3187 torture_comment(tctx, "Testing AddJob\n");
3189 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3190 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3192 r.in.level = 1;
3194 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3195 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3197 return true;
3201 static bool test_EnumJobs_args(struct torture_context *tctx,
3202 struct dcerpc_binding_handle *b,
3203 struct policy_handle *handle,
3204 uint32_t level,
3205 uint32_t *count_p,
3206 union spoolss_JobInfo **info_p)
3208 NTSTATUS status;
3209 struct spoolss_EnumJobs r;
3210 uint32_t needed;
3211 uint32_t count;
3212 union spoolss_JobInfo *info;
3214 r.in.handle = handle;
3215 r.in.firstjob = 0;
3216 r.in.numjobs = 0xffffffff;
3217 r.in.level = level;
3218 r.in.buffer = NULL;
3219 r.in.offered = 0;
3220 r.out.needed = &needed;
3221 r.out.count = &count;
3222 r.out.info = &info;
3224 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3226 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3228 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3230 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3231 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3232 r.in.buffer = &blob;
3233 r.in.offered = needed;
3235 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3237 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3238 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3239 torture_assert(tctx, info, "No jobs returned");
3241 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3243 } else {
3244 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3247 if (count_p) {
3248 *count_p = count;
3250 if (info_p) {
3251 *info_p = info;
3254 return true;
3257 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3258 struct dcerpc_binding_handle *b,
3259 struct policy_handle *handle,
3260 const char *document_name,
3261 uint32_t *job_id)
3263 NTSTATUS status;
3264 struct spoolss_StartDocPrinter s;
3265 struct spoolss_DocumentInfo1 info1;
3266 struct spoolss_StartPagePrinter sp;
3267 struct spoolss_WritePrinter w;
3268 struct spoolss_EndPagePrinter ep;
3269 struct spoolss_EndDocPrinter e;
3270 int i;
3271 uint32_t num_written;
3273 torture_comment(tctx, "Testing StartDocPrinter\n");
3275 s.in.handle = handle;
3276 s.in.level = 1;
3277 s.in.info.info1 = &info1;
3278 s.out.job_id = job_id;
3279 info1.document_name = document_name;
3280 info1.output_file = NULL;
3281 info1.datatype = "RAW";
3283 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3284 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3285 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3287 for (i=1; i < 4; i++) {
3288 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3290 sp.in.handle = handle;
3292 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3293 torture_assert_ntstatus_ok(tctx, status,
3294 "dcerpc_spoolss_StartPagePrinter failed");
3295 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3297 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3299 w.in.handle = handle;
3300 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3301 w.out.num_written = &num_written;
3303 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3304 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3305 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3307 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3309 ep.in.handle = handle;
3311 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3312 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3313 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3316 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3318 e.in.handle = handle;
3320 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3321 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3322 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3324 return true;
3327 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3328 struct dcerpc_binding_handle *b,
3329 struct policy_handle *handle,
3330 uint32_t num_jobs,
3331 uint32_t *job_ids)
3333 uint32_t count;
3334 union spoolss_JobInfo *info = NULL;
3335 int i;
3337 torture_assert(tctx,
3338 test_AddJob(tctx, b, handle),
3339 "AddJob failed");
3341 torture_assert(tctx,
3342 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3343 "EnumJobs level 1 failed");
3345 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3347 for (i=0; i < num_jobs; i++) {
3348 union spoolss_JobInfo ginfo;
3349 const char *document_name;
3350 const char *new_document_name = "any_other_docname";
3351 struct spoolss_JobInfoContainer ctr;
3352 struct spoolss_SetJobInfo1 info1;
3354 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3356 torture_assert(tctx,
3357 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3358 "failed to call test_GetJob");
3360 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3362 document_name = ginfo.info1.document_name;
3364 info1.job_id = ginfo.info1.job_id;
3365 info1.printer_name = ginfo.info1.printer_name;
3366 info1.server_name = ginfo.info1.server_name;
3367 info1.user_name = ginfo.info1.user_name;
3368 info1.document_name = new_document_name;
3369 info1.data_type = ginfo.info1.data_type;
3370 info1.text_status = ginfo.info1.text_status;
3371 info1.status = ginfo.info1.status;
3372 info1.priority = ginfo.info1.priority;
3373 info1.position = ginfo.info1.position;
3374 info1.total_pages = ginfo.info1.total_pages;
3375 info1.pages_printed = ginfo.info1.pages_printed;
3376 info1.submitted = ginfo.info1.submitted;
3378 ctr.level = 1;
3379 ctr.info.info1 = &info1;
3381 torture_assert(tctx,
3382 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3383 "failed to call test_SetJob level 1");
3385 torture_assert(tctx,
3386 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3387 "failed to call test_GetJob");
3389 if (strequal(ginfo.info1.document_name, document_name)) {
3390 torture_warning(tctx,
3391 "document_name did *NOT* change from '%s' to '%s'\n",
3392 document_name, new_document_name);
3396 for (i=0; i < num_jobs; i++) {
3397 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3398 torture_warning(tctx, "failed to pause printjob\n");
3400 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3401 torture_warning(tctx, "failed to resume printjob\n");
3405 return true;
3408 static bool test_DoPrintTest(struct torture_context *tctx,
3409 struct dcerpc_binding_handle *b,
3410 struct policy_handle *handle)
3412 bool ret = true;
3413 uint32_t num_jobs = 8;
3414 uint32_t *job_ids;
3415 int i;
3417 torture_comment(tctx, "Testing real print operations\n");
3419 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3421 for (i=0; i < num_jobs; i++) {
3422 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3425 for (i=0; i < num_jobs; i++) {
3426 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3429 if (ret == true) {
3430 torture_comment(tctx, "real print operations test succeeded\n\n");
3433 return ret;
3436 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3437 struct dcerpc_binding_handle *b,
3438 struct policy_handle *handle)
3440 bool ret = true;
3441 uint32_t num_jobs = 8;
3442 uint32_t *job_ids;
3443 int i;
3444 torture_comment(tctx, "Testing real print operations (extended)\n");
3446 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3448 for (i=0; i < num_jobs; i++) {
3449 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3452 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3454 for (i=0; i < num_jobs; i++) {
3455 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3458 if (ret == true) {
3459 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3462 return ret;
3465 static bool test_PausePrinter(struct torture_context *tctx,
3466 struct dcerpc_binding_handle *b,
3467 struct policy_handle *handle)
3469 NTSTATUS status;
3470 struct spoolss_SetPrinter r;
3471 struct spoolss_SetPrinterInfoCtr info_ctr;
3472 struct spoolss_DevmodeContainer devmode_ctr;
3473 struct sec_desc_buf secdesc_ctr;
3475 info_ctr.level = 0;
3476 info_ctr.info.info0 = NULL;
3478 ZERO_STRUCT(devmode_ctr);
3479 ZERO_STRUCT(secdesc_ctr);
3481 r.in.handle = handle;
3482 r.in.info_ctr = &info_ctr;
3483 r.in.devmode_ctr = &devmode_ctr;
3484 r.in.secdesc_ctr = &secdesc_ctr;
3485 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3487 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3489 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3491 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3493 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3495 return true;
3498 static bool test_ResumePrinter(struct torture_context *tctx,
3499 struct dcerpc_binding_handle *b,
3500 struct policy_handle *handle)
3502 NTSTATUS status;
3503 struct spoolss_SetPrinter r;
3504 struct spoolss_SetPrinterInfoCtr info_ctr;
3505 struct spoolss_DevmodeContainer devmode_ctr;
3506 struct sec_desc_buf secdesc_ctr;
3508 info_ctr.level = 0;
3509 info_ctr.info.info0 = NULL;
3511 ZERO_STRUCT(devmode_ctr);
3512 ZERO_STRUCT(secdesc_ctr);
3514 r.in.handle = handle;
3515 r.in.info_ctr = &info_ctr;
3516 r.in.devmode_ctr = &devmode_ctr;
3517 r.in.secdesc_ctr = &secdesc_ctr;
3518 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3520 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3522 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3524 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3526 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3528 return true;
3531 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3532 struct dcerpc_binding_handle *b,
3533 struct policy_handle *handle,
3534 const char *value_name,
3535 enum winreg_Type *expected_type,
3536 enum winreg_Type *type_p,
3537 uint8_t **data_p,
3538 uint32_t *needed_p)
3540 NTSTATUS status;
3541 struct spoolss_GetPrinterData r;
3542 uint32_t needed;
3543 enum winreg_Type type;
3544 union spoolss_PrinterData data;
3546 r.in.handle = handle;
3547 r.in.value_name = value_name;
3548 r.in.offered = 0;
3549 r.out.needed = &needed;
3550 r.out.type = &type;
3551 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3553 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3555 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3556 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3558 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3559 if (expected_type) {
3560 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3562 r.in.offered = needed;
3563 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3564 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3565 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3568 torture_assert_werr_ok(tctx, r.out.result,
3569 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3571 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3573 if (type_p) {
3574 *type_p = type;
3577 if (data_p) {
3578 *data_p = r.out.data;
3581 if (needed_p) {
3582 *needed_p = needed;
3585 return true;
3588 static bool test_GetPrinterData(struct torture_context *tctx,
3589 struct dcerpc_binding_handle *b,
3590 struct policy_handle *handle,
3591 const char *value_name,
3592 enum winreg_Type *type_p,
3593 uint8_t **data_p,
3594 uint32_t *needed_p)
3596 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3597 NULL, type_p, data_p, needed_p);
3600 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3601 struct dcerpc_pipe *p,
3602 struct policy_handle *handle,
3603 const char *key_name,
3604 const char *value_name,
3605 enum winreg_Type *expected_type,
3606 enum winreg_Type *type_p,
3607 uint8_t **data_p,
3608 uint32_t *needed_p)
3610 NTSTATUS status;
3611 struct spoolss_GetPrinterDataEx r;
3612 enum winreg_Type type;
3613 uint32_t needed;
3614 union spoolss_PrinterData data;
3615 struct dcerpc_binding_handle *b = p->binding_handle;
3617 r.in.handle = handle;
3618 r.in.key_name = key_name;
3619 r.in.value_name = value_name;
3620 r.in.offered = 0;
3621 r.out.type = &type;
3622 r.out.needed = &needed;
3623 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3625 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3626 r.in.key_name, r.in.value_name);
3628 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3631 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3633 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3636 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3637 if (expected_type) {
3638 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3640 r.in.offered = needed;
3641 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3642 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3643 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3646 torture_assert_werr_ok(tctx, r.out.result,
3647 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3649 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3651 if (type_p) {
3652 *type_p = type;
3655 if (data_p) {
3656 *data_p = r.out.data;
3659 if (needed_p) {
3660 *needed_p = needed;
3663 return true;
3666 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3667 struct dcerpc_pipe *p,
3668 struct policy_handle *handle,
3669 const char *key_name,
3670 const char *value_name,
3671 enum winreg_Type *type_p,
3672 uint8_t **data_p,
3673 uint32_t *needed_p)
3675 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3676 NULL, type_p, data_p, needed_p);
3679 static bool test_get_environment(struct torture_context *tctx,
3680 struct dcerpc_binding_handle *b,
3681 struct policy_handle *handle,
3682 const char **architecture)
3684 DATA_BLOB blob;
3685 enum winreg_Type type;
3686 uint8_t *data;
3687 uint32_t needed;
3689 torture_assert(tctx,
3690 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3691 "failed to get Architecture");
3693 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3695 blob = data_blob_const(data, needed);
3696 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3698 return true;
3701 static bool test_GetPrinterData_list(struct torture_context *tctx,
3702 void *private_data)
3704 struct test_spoolss_context *ctx =
3705 talloc_get_type_abort(private_data, struct test_spoolss_context);
3706 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3707 struct dcerpc_binding_handle *b = p->binding_handle;
3708 const char *list[] = {
3709 "W3SvcInstalled",
3710 "BeepEnabled",
3711 "EventLog",
3712 /* "NetPopup", not on w2k8 */
3713 /* "NetPopupToComputer", not on w2k8 */
3714 "MajorVersion",
3715 "MinorVersion",
3716 "DefaultSpoolDirectory",
3717 "Architecture",
3718 "DsPresent",
3719 "OSVersion",
3720 /* "OSVersionEx", not on s3 */
3721 "DNSMachineName"
3723 int i;
3725 for (i=0; i < ARRAY_SIZE(list); i++) {
3726 enum winreg_Type type, type_ex;
3727 uint8_t *data, *data_ex;
3728 uint32_t needed, needed_ex;
3730 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3731 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3732 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3733 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3734 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3735 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3736 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3739 return true;
3742 static bool test_EnumPrinterData(struct torture_context *tctx,
3743 struct dcerpc_pipe *p,
3744 struct policy_handle *handle,
3745 uint32_t enum_index,
3746 uint32_t value_offered,
3747 uint32_t data_offered,
3748 enum winreg_Type *type_p,
3749 uint32_t *value_needed_p,
3750 uint32_t *data_needed_p,
3751 const char **value_name_p,
3752 uint8_t **data_p,
3753 WERROR *result_p)
3755 struct spoolss_EnumPrinterData r;
3756 uint32_t data_needed;
3757 uint32_t value_needed;
3758 enum winreg_Type type;
3759 struct dcerpc_binding_handle *b = p->binding_handle;
3761 r.in.handle = handle;
3762 r.in.enum_index = enum_index;
3763 r.in.value_offered = value_offered;
3764 r.in.data_offered = data_offered;
3765 r.out.data_needed = &data_needed;
3766 r.out.value_needed = &value_needed;
3767 r.out.type = &type;
3768 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3769 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3771 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3773 torture_assert_ntstatus_ok(tctx,
3774 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3775 "EnumPrinterData failed");
3777 if (type_p) {
3778 *type_p = type;
3780 if (value_needed_p) {
3781 *value_needed_p = value_needed;
3783 if (data_needed_p) {
3784 *data_needed_p = data_needed;
3786 if (value_name_p) {
3787 *value_name_p = r.out.value_name;
3789 if (data_p) {
3790 *data_p = r.out.data;
3792 if (result_p) {
3793 *result_p = r.out.result;
3796 return true;
3800 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3801 struct dcerpc_pipe *p,
3802 struct policy_handle *handle)
3804 uint32_t enum_index = 0;
3805 enum winreg_Type type;
3806 uint32_t value_needed;
3807 uint32_t data_needed;
3808 uint8_t *data;
3809 const char *value_name;
3810 WERROR result;
3812 torture_comment(tctx, "Testing EnumPrinterData\n");
3814 do {
3815 torture_assert(tctx,
3816 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3817 &type, &value_needed, &data_needed,
3818 &value_name, &data, &result),
3819 "EnumPrinterData failed");
3821 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3822 break;
3825 torture_assert(tctx,
3826 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3827 &type, &value_needed, &data_needed,
3828 &value_name, &data, &result),
3829 "EnumPrinterData failed");
3831 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3832 break;
3835 enum_index++;
3837 } while (W_ERROR_IS_OK(result));
3839 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3841 return true;
3844 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3845 struct dcerpc_binding_handle *b,
3846 struct policy_handle *handle,
3847 const char *key_name,
3848 uint32_t *count_p,
3849 struct spoolss_PrinterEnumValues **info_p)
3851 struct spoolss_EnumPrinterDataEx r;
3852 struct spoolss_PrinterEnumValues *info;
3853 uint32_t needed;
3854 uint32_t count;
3856 r.in.handle = handle;
3857 r.in.key_name = key_name;
3858 r.in.offered = 0;
3859 r.out.needed = &needed;
3860 r.out.count = &count;
3861 r.out.info = &info;
3863 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3865 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3866 "EnumPrinterDataEx failed");
3867 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3868 r.in.offered = needed;
3869 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3870 "EnumPrinterDataEx failed");
3873 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3875 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3877 if (count_p) {
3878 *count_p = count;
3880 if (info_p) {
3881 *info_p = info;
3884 return true;
3887 static bool test_SetPrinterData(struct torture_context *tctx,
3888 struct dcerpc_binding_handle *b,
3889 struct policy_handle *handle,
3890 const char *value_name,
3891 enum winreg_Type type,
3892 uint8_t *data,
3893 uint32_t offered);
3894 static bool test_DeletePrinterData(struct torture_context *tctx,
3895 struct dcerpc_binding_handle *b,
3896 struct policy_handle *handle,
3897 const char *value_name);
3899 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3900 struct dcerpc_pipe *p,
3901 struct policy_handle *handle)
3903 uint32_t count;
3904 struct spoolss_PrinterEnumValues *info;
3905 int i;
3906 uint32_t value_needed, data_needed;
3907 uint32_t value_offered, data_offered;
3908 WERROR result;
3909 struct dcerpc_binding_handle *b = p->binding_handle;
3911 enum winreg_Type type;
3912 DATA_BLOB blob;
3914 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3916 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3917 type = REG_SZ;
3919 torture_assert(tctx,
3920 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3921 "SetPrinterData failed");
3923 blob = data_blob_string_const("torture_data2");
3925 torture_assert(tctx,
3926 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3927 "SetPrinterData failed");
3929 blob = data_blob_talloc(tctx, NULL, 4);
3930 SIVAL(blob.data, 0, 0x11223344);
3932 torture_assert(tctx,
3933 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3934 "SetPrinterData failed");
3936 torture_assert(tctx,
3937 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3938 "failed to call EnumPrinterDataEx");
3940 /* get the max sizes for value and data */
3942 torture_assert(tctx,
3943 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3944 NULL, &value_needed, &data_needed,
3945 NULL, NULL, &result),
3946 "EnumPrinterData failed");
3947 torture_assert_werr_ok(tctx, result, "unexpected result");
3949 /* check if the reply from the EnumPrinterData really matches max values */
3951 for (i=0; i < count; i++) {
3952 if (info[i].value_name_len > value_needed) {
3953 torture_fail(tctx,
3954 talloc_asprintf(tctx,
3955 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3956 info[i].value_name_len, value_needed));
3958 if (info[i].data_length > data_needed) {
3959 torture_fail(tctx,
3960 talloc_asprintf(tctx,
3961 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3962 info[i].data_length, data_needed));
3966 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3967 * sort or not sort the replies by value name, we should be able to do
3968 * the following entry comparison */
3970 data_offered = data_needed;
3971 value_offered = value_needed;
3973 for (i=0; i < count; i++) {
3975 const char *value_name;
3976 uint8_t *data;
3978 torture_assert(tctx,
3979 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3980 &type, &value_needed, &data_needed,
3981 &value_name, &data, &result),
3982 "EnumPrinterData failed");
3984 if (i -1 == count) {
3985 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3986 "unexpected result");
3987 break;
3988 } else {
3989 torture_assert_werr_ok(tctx, result, "unexpected result");
3992 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3993 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3994 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3995 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3996 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3999 torture_assert(tctx,
4000 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4001 "DeletePrinterData failed");
4002 torture_assert(tctx,
4003 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4004 "DeletePrinterData failed");
4005 torture_assert(tctx,
4006 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4007 "DeletePrinterData failed");
4009 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4011 return true;
4014 static bool test_DeletePrinterData(struct torture_context *tctx,
4015 struct dcerpc_binding_handle *b,
4016 struct policy_handle *handle,
4017 const char *value_name)
4019 NTSTATUS status;
4020 struct spoolss_DeletePrinterData r;
4022 r.in.handle = handle;
4023 r.in.value_name = value_name;
4025 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4026 r.in.value_name);
4028 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4030 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4031 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4033 return true;
4036 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4037 struct dcerpc_binding_handle *b,
4038 struct policy_handle *handle,
4039 const char *key_name,
4040 const char *value_name)
4042 struct spoolss_DeletePrinterDataEx r;
4044 r.in.handle = handle;
4045 r.in.key_name = key_name;
4046 r.in.value_name = value_name;
4048 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4049 r.in.key_name, r.in.value_name);
4051 torture_assert_ntstatus_ok(tctx,
4052 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4053 "DeletePrinterDataEx failed");
4054 torture_assert_werr_ok(tctx, r.out.result,
4055 "DeletePrinterDataEx failed");
4057 return true;
4060 static bool test_DeletePrinterKey(struct torture_context *tctx,
4061 struct dcerpc_binding_handle *b,
4062 struct policy_handle *handle,
4063 const char *key_name)
4065 struct spoolss_DeletePrinterKey r;
4067 r.in.handle = handle;
4068 r.in.key_name = key_name;
4070 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4072 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4073 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4074 return true;
4077 torture_assert_ntstatus_ok(tctx,
4078 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4079 "DeletePrinterKey failed");
4080 torture_assert_werr_ok(tctx, r.out.result,
4081 "DeletePrinterKey failed");
4083 return true;
4086 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4087 struct dcerpc_binding_handle *b,
4088 struct policy_handle *handle)
4090 struct winreg_OpenHKLM r;
4092 r.in.system_name = NULL;
4093 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4094 r.out.handle = handle;
4096 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4098 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4099 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4101 return true;
4104 static void init_winreg_String(struct winreg_String *name, const char *s)
4106 name->name = s;
4107 if (s) {
4108 name->name_len = 2 * (strlen_m(s) + 1);
4109 name->name_size = name->name_len;
4110 } else {
4111 name->name_len = 0;
4112 name->name_size = 0;
4116 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4117 struct dcerpc_binding_handle *b,
4118 struct policy_handle *hive_handle,
4119 const char *keyname,
4120 uint32_t options,
4121 struct policy_handle *key_handle)
4123 struct winreg_OpenKey r;
4125 r.in.parent_handle = hive_handle;
4126 init_winreg_String(&r.in.keyname, keyname);
4127 r.in.options = options;
4128 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4129 r.out.handle = key_handle;
4131 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4133 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4134 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4136 return true;
4139 static bool test_winreg_OpenKey(struct torture_context *tctx,
4140 struct dcerpc_binding_handle *b,
4141 struct policy_handle *hive_handle,
4142 const char *keyname,
4143 struct policy_handle *key_handle)
4145 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4146 REG_OPTION_NON_VOLATILE, key_handle);
4149 static bool test_winreg_CloseKey(struct torture_context *tctx,
4150 struct dcerpc_binding_handle *b,
4151 struct policy_handle *handle)
4153 struct winreg_CloseKey r;
4155 r.in.handle = handle;
4156 r.out.handle = handle;
4158 torture_comment(tctx, "Testing winreg_CloseKey\n");
4160 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4161 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4163 return true;
4166 bool test_winreg_QueryValue(struct torture_context *tctx,
4167 struct dcerpc_binding_handle *b,
4168 struct policy_handle *handle,
4169 const char *value_name,
4170 enum winreg_Type *type_p,
4171 uint32_t *data_size_p,
4172 uint32_t *data_length_p,
4173 uint8_t **data_p)
4175 struct winreg_QueryValue r;
4176 enum winreg_Type type = REG_NONE;
4177 uint32_t data_size = 0;
4178 uint32_t data_length = 0;
4179 struct winreg_String valuename;
4180 uint8_t *data = NULL;
4182 init_winreg_String(&valuename, value_name);
4184 data = talloc_zero_array(tctx, uint8_t, 0);
4186 r.in.handle = handle;
4187 r.in.value_name = &valuename;
4188 r.in.type = &type;
4189 r.in.data_size = &data_size;
4190 r.in.data_length = &data_length;
4191 r.in.data = data;
4192 r.out.type = &type;
4193 r.out.data = data;
4194 r.out.data_size = &data_size;
4195 r.out.data_length = &data_length;
4197 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4199 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4200 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4201 *r.in.data_size = *r.out.data_size;
4202 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4203 r.in.data = data;
4204 r.out.data = data;
4205 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4207 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4209 if (type_p) {
4210 *type_p = *r.out.type;
4212 if (data_size_p) {
4213 *data_size_p = *r.out.data_size;
4215 if (data_length_p) {
4216 *data_length_p = *r.out.data_length;
4218 if (data_p) {
4219 *data_p = r.out.data;
4222 return true;
4225 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4226 struct dcerpc_binding_handle *b,
4227 struct policy_handle *handle,
4228 const char *printer_name,
4229 const char *key_name,
4230 const char *value_name,
4231 enum winreg_Type *w_type,
4232 uint32_t *w_size,
4233 uint32_t *w_length,
4234 uint8_t **w_data)
4236 const char *printer_key;
4237 struct policy_handle key_handle;
4239 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4240 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4242 torture_assert(tctx,
4243 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4245 torture_assert(tctx,
4246 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4248 torture_assert(tctx,
4249 test_winreg_CloseKey(tctx, b, &key_handle), "");
4251 return true;
4254 static bool test_GetForm_winreg(struct torture_context *tctx,
4255 struct dcerpc_binding_handle *b,
4256 struct policy_handle *handle,
4257 const char *key_name,
4258 const char *form_name,
4259 enum winreg_Type *w_type,
4260 uint32_t *w_size,
4261 uint32_t *w_length,
4262 uint8_t **w_data)
4264 struct policy_handle key_handle;
4266 torture_assert(tctx,
4267 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4269 torture_assert(tctx,
4270 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4272 torture_assert(tctx,
4273 test_winreg_CloseKey(tctx, b, &key_handle), "");
4275 return true;
4278 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4279 struct dcerpc_binding_handle *b,
4280 struct policy_handle *handle,
4281 const char *symlink_keyname,
4282 const char *symlink_destination)
4284 /* check if the first key is a symlink to the second key */
4286 enum winreg_Type w_type;
4287 uint32_t w_size;
4288 uint32_t w_length;
4289 uint8_t *w_data;
4290 struct policy_handle key_handle;
4291 DATA_BLOB blob;
4292 const char *str;
4294 if (torture_setting_bool(tctx, "samba3", false)) {
4295 torture_skip(tctx, "skip winreg symlink test against samba");
4298 torture_assert(tctx,
4299 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4300 "failed to open key link");
4302 torture_assert(tctx,
4303 test_winreg_QueryValue(tctx, b, &key_handle,
4304 "SymbolicLinkValue",
4305 &w_type, &w_size, &w_length, &w_data),
4306 "failed to query for 'SymbolicLinkValue' attribute");
4308 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4310 blob = data_blob(w_data, w_size);
4311 str = reg_val_data_string(tctx, REG_SZ, blob);
4313 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4315 torture_assert(tctx,
4316 test_winreg_CloseKey(tctx, b, &key_handle),
4317 "failed to close key link");
4319 return true;
4322 static const char *strip_unc(const char *unc)
4324 char *name;
4326 if (!unc) {
4327 return NULL;
4330 if (unc[0] == '\\' && unc[1] == '\\') {
4331 unc +=2;
4334 name = strchr(unc, '\\');
4335 if (name) {
4336 return name+1;
4339 return unc;
4342 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4343 struct dcerpc_binding_handle *b,
4344 struct policy_handle *handle,
4345 const char *printer_name,
4346 struct dcerpc_binding_handle *winreg_handle,
4347 struct policy_handle *hive_handle)
4349 union spoolss_PrinterInfo info;
4350 const char *keys[] = {
4351 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4352 TOP_LEVEL_PRINT_PRINTERS_KEY
4354 int i;
4355 const char *printername, *sharename;
4357 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4359 torture_assert(tctx,
4360 test_GetPrinter_level(tctx, b, handle, 2, &info),
4361 "failed to get printer info level 2");
4363 printername = strip_unc(info.info2.printername);
4364 sharename = strip_unc(info.info2.sharename);
4366 #define test_sz(wname, iname) \
4367 do {\
4368 DATA_BLOB blob;\
4369 const char *str;\
4370 enum winreg_Type w_type;\
4371 uint32_t w_size;\
4372 uint32_t w_length;\
4373 uint8_t *w_data;\
4374 torture_assert(tctx,\
4375 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4376 &w_type, &w_size, &w_length, &w_data),\
4377 "failed to query winreg");\
4378 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4379 blob = data_blob(w_data, w_size);\
4380 str = reg_val_data_string(tctx, REG_SZ, blob);\
4381 if (w_size == 2 && iname == NULL) {\
4382 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4383 } else {\
4384 torture_assert_str_equal(tctx, str, iname,\
4385 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4387 } while(0);
4389 #define test_dword(wname, iname) \
4390 do {\
4391 uint32_t value;\
4392 enum winreg_Type w_type;\
4393 uint32_t w_size;\
4394 uint32_t w_length;\
4395 uint8_t *w_data;\
4396 torture_assert(tctx,\
4397 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4398 &w_type, &w_size, &w_length, &w_data),\
4399 "failed to query winreg");\
4400 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4401 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4402 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4403 value = IVAL(w_data, 0);\
4404 torture_assert_int_equal(tctx, value, iname,\
4405 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4406 } while(0);
4408 #define test_binary(wname, iname) \
4409 do {\
4410 enum winreg_Type w_type;\
4411 uint32_t w_size;\
4412 uint32_t w_length;\
4413 uint8_t *w_data;\
4414 torture_assert(tctx,\
4415 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4416 &w_type, &w_size, &w_length, &w_data),\
4417 "failed to query winreg");\
4418 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4419 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4420 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4421 "binary unequal");\
4422 } while(0);
4425 #define test_dm(wname, iname) \
4426 do {\
4427 DATA_BLOB blob;\
4428 struct spoolss_DeviceMode dm;\
4429 enum ndr_err_code ndr_err;\
4430 enum winreg_Type w_type;\
4431 uint32_t w_size;\
4432 uint32_t w_length;\
4433 uint8_t *w_data;\
4434 torture_assert(tctx,\
4435 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4436 &w_type, &w_size, &w_length, &w_data),\
4437 "failed to query winreg");\
4438 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4439 blob = data_blob(w_data, w_size);\
4440 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4441 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4442 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4443 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4444 "dm unequal");\
4445 } while(0);
4447 #define test_sd(wname, iname) \
4448 do {\
4449 DATA_BLOB blob;\
4450 struct security_descriptor sd;\
4451 enum ndr_err_code ndr_err;\
4452 enum winreg_Type w_type;\
4453 uint32_t w_size;\
4454 uint32_t w_length;\
4455 uint8_t *w_data;\
4456 torture_assert(tctx,\
4457 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4458 &w_type, &w_size, &w_length, &w_data),\
4459 "failed to query winreg");\
4460 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4461 blob = data_blob(w_data, w_size);\
4462 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4463 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4464 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4465 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4466 "sd unequal");\
4467 } while(0);
4469 #define test_multi_sz(wname, iname) \
4470 do {\
4471 DATA_BLOB blob;\
4472 const char **array;\
4473 enum winreg_Type w_type;\
4474 uint32_t w_size;\
4475 uint32_t w_length;\
4476 uint8_t *w_data;\
4477 int i;\
4478 torture_assert(tctx,\
4479 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4480 &w_type, &w_size, &w_length, &w_data),\
4481 "failed to query winreg");\
4482 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4483 blob = data_blob(w_data, w_size);\
4484 torture_assert(tctx, \
4485 pull_reg_multi_sz(tctx, &blob, &array),\
4486 "failed to pull multi sz");\
4487 for (i=0; array[i] != NULL; i++) {\
4488 torture_assert_str_equal(tctx, array[i], iname[i],\
4489 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4491 } while(0);
4493 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4494 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4495 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4497 torture_warning(tctx, "failed to check for winreg symlink");
4500 for (i=0; i < ARRAY_SIZE(keys); i++) {
4502 const char *printer_key;
4503 struct policy_handle key_handle;
4505 printer_key = talloc_asprintf(tctx, "%s\\%s",
4506 keys[i], printer_name);
4508 torture_assert(tctx,
4509 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4511 test_sz("Name", printername);
4512 test_sz("Share Name", sharename);
4513 test_sz("Port", info.info2.portname);
4514 test_sz("Printer Driver", info.info2.drivername);
4515 test_sz("Description", info.info2.comment);
4516 test_sz("Location", info.info2.location);
4517 test_sz("Separator File", info.info2.sepfile);
4518 test_sz("Print Processor", info.info2.printprocessor);
4519 test_sz("Datatype", info.info2.datatype);
4520 test_sz("Parameters", info.info2.parameters);
4521 /* winreg: 0, spoolss not */
4522 /* test_dword("Attributes", info.info2.attributes); */
4523 test_dword("Priority", info.info2.priority);
4524 test_dword("Default Priority", info.info2.defaultpriority);
4525 /* winreg: 60, spoolss: 0 */
4526 /* test_dword("StartTime", info.info2.starttime); */
4527 /* test_dword("UntilTime", info.info2.untiltime); */
4528 /* winreg != spoolss */
4529 /* test_dword("Status", info.info2.status); */
4530 test_dm("Default DevMode", info.info2.devmode);
4531 test_sd("Security", info.info2.secdesc);
4533 torture_assert(tctx,
4534 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4537 #undef test_dm
4538 #undef test_sd
4540 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4542 return true;
4545 static bool test_PrintProcessors(struct torture_context *tctx,
4546 struct dcerpc_binding_handle *b,
4547 const char *environment,
4548 struct dcerpc_binding_handle *winreg_handle,
4549 struct policy_handle *hive_handle)
4551 union spoolss_PrintProcessorInfo *info;
4552 uint32_t count;
4553 int i;
4555 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4557 torture_assert(tctx,
4558 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4559 "failed to enum print processors level 1");
4561 for (i=0; i < count; i++) {
4563 const char *processor_key;
4564 struct policy_handle key_handle;
4566 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4567 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4568 environment,
4569 info[i].info1.print_processor_name);
4571 torture_assert(tctx,
4572 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4574 /* nothing to check in there so far */
4576 torture_assert(tctx,
4577 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4580 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4582 return true;
4585 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4586 struct dcerpc_binding_handle *b,
4587 struct policy_handle *handle,
4588 const char *driver_name,
4589 const char *architecture,
4590 uint32_t level,
4591 uint32_t client_major_version,
4592 uint32_t client_minor_version,
4593 union spoolss_DriverInfo *info_p,
4594 WERROR *result);
4596 static const char *strip_path(const char *path)
4598 char *p;
4600 if (path == NULL) {
4601 return NULL;
4604 p = strrchr(path, '\\');
4605 if (p) {
4606 return p+1;
4609 return path;
4612 static const char **strip_paths(const char **path_array)
4614 int i;
4616 if (path_array == NULL) {
4617 return NULL;
4620 for (i=0; path_array[i] != NULL; i++) {
4621 path_array[i] = strip_path(path_array[i]);
4624 return path_array;
4627 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4629 time_t t;
4630 struct tm *tm;
4632 if (nt == 0) {
4633 return talloc_strdup(mem_ctx, "01/01/1601");
4636 t = nt_time_to_unix(nt);
4637 tm = localtime(&t);
4639 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4640 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4643 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4645 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4646 (unsigned)((v >> 48) & 0xFFFF),
4647 (unsigned)((v >> 32) & 0xFFFF),
4648 (unsigned)((v >> 16) & 0xFFFF),
4649 (unsigned)(v & 0xFFFF));
4652 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4653 struct dcerpc_binding_handle *b,
4654 struct policy_handle *handle,
4655 const char *printer_name,
4656 const char *driver_name,
4657 const char *environment,
4658 enum spoolss_DriverOSVersion version,
4659 struct dcerpc_binding_handle *winreg_handle,
4660 struct policy_handle *hive_handle,
4661 const char *server_name_slash)
4663 WERROR result;
4664 union spoolss_DriverInfo info;
4665 const char *driver_key;
4666 struct policy_handle key_handle;
4668 const char *driver_path;
4669 const char *data_file;
4670 const char *config_file;
4671 const char *help_file;
4672 const char **dependent_files;
4674 const char *driver_date;
4675 const char *inbox_driver_date;
4677 const char *driver_version;
4678 const char *inbox_driver_version;
4680 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4682 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4683 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4684 environment,
4685 version,
4686 driver_name);
4688 torture_assert(tctx,
4689 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4690 "failed to open driver key");
4692 if (torture_setting_bool(tctx, "samba3", false) ||
4693 torture_setting_bool(tctx, "w2k3", false)) {
4694 goto try_level6;
4697 if (handle) {
4698 torture_assert(tctx,
4699 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4700 "failed to get driver info level 8");
4701 } else {
4702 torture_assert(tctx,
4703 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4704 "failed to get driver info level 8");
4707 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4708 goto try_level6;
4711 driver_path = strip_path(info.info8.driver_path);
4712 data_file = strip_path(info.info8.data_file);
4713 config_file = strip_path(info.info8.config_file);
4714 help_file = strip_path(info.info8.help_file);
4715 dependent_files = strip_paths(info.info8.dependent_files);
4717 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4718 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4720 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4721 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4723 test_sz("Configuration File", config_file);
4724 test_sz("Data File", data_file);
4725 test_sz("Datatype", info.info8.default_datatype);
4726 test_sz("Driver", driver_path);
4727 test_sz("DriverDate", driver_date);
4728 test_sz("DriverVersion", driver_version);
4729 test_sz("HardwareID", info.info8.hardware_id);
4730 test_sz("Help File", help_file);
4731 test_sz("InfPath", info.info8.inf_path);
4732 test_sz("Manufacturer", info.info8.manufacturer_name);
4733 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4734 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4735 test_sz("Monitor", info.info8.monitor_name);
4736 test_sz("OEM URL", info.info8.manufacturer_url);
4737 test_sz("Print Processor", info.info8.print_processor);
4738 test_sz("Provider", info.info8.provider);
4739 test_sz("VendorSetup", info.info8.vendor_setup);
4740 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4741 test_multi_sz("Dependent Files", dependent_files);
4742 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4743 test_multi_sz("Previous Names", info.info8.previous_names);
4744 /* test_dword("Attributes", ?); */
4745 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4746 test_dword("Version", info.info8.version);
4747 /* test_dword("TempDir", ?); */
4749 try_level6:
4751 if (handle) {
4752 torture_assert(tctx,
4753 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4754 "failed to get driver info level 6");
4755 } else {
4756 torture_assert(tctx,
4757 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4758 "failed to get driver info level 6");
4761 driver_path = strip_path(info.info6.driver_path);
4762 data_file = strip_path(info.info6.data_file);
4763 config_file = strip_path(info.info6.config_file);
4764 help_file = strip_path(info.info6.help_file);
4765 dependent_files = strip_paths(info.info6.dependent_files);
4767 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4769 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4771 test_sz("Configuration File", config_file);
4772 test_sz("Data File", data_file);
4773 test_sz("Datatype", info.info6.default_datatype);
4774 test_sz("Driver", driver_path);
4775 if (torture_setting_bool(tctx, "w2k3", false)) {
4776 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4777 push_nttime(blob.data, 0, info.info6.driver_date);
4778 test_binary("DriverDate", blob);
4779 SBVAL(blob.data, 0, info.info6.driver_version);
4780 test_binary("DriverVersion", blob);
4781 } else {
4782 test_sz("DriverDate", driver_date);
4783 test_sz("DriverVersion", driver_version);
4785 test_sz("HardwareID", info.info6.hardware_id);
4786 test_sz("Help File", help_file);
4787 test_sz("Manufacturer", info.info6.manufacturer_name);
4788 test_sz("Monitor", info.info6.monitor_name);
4789 test_sz("OEM URL", info.info6.manufacturer_url);
4790 test_sz("Provider", info.info6.provider);
4791 test_multi_sz("Dependent Files", dependent_files);
4792 test_multi_sz("Previous Names", info.info6.previous_names);
4793 /* test_dword("Attributes", ?); */
4794 test_dword("Version", info.info6.version);
4795 /* test_dword("TempDir", ?); */
4797 if (handle) {
4798 torture_assert(tctx,
4799 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4800 "failed to get driver info level 3");
4801 } else {
4802 torture_assert(tctx,
4803 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4804 "failed to get driver info level 3");
4807 driver_path = strip_path(info.info3.driver_path);
4808 data_file = strip_path(info.info3.data_file);
4809 config_file = strip_path(info.info3.config_file);
4810 help_file = strip_path(info.info3.help_file);
4811 dependent_files = strip_paths(info.info3.dependent_files);
4813 test_sz("Configuration File", config_file);
4814 test_sz("Data File", data_file);
4815 test_sz("Datatype", info.info3.default_datatype);
4816 test_sz("Driver", driver_path);
4817 test_sz("Help File", help_file);
4818 test_sz("Monitor", info.info3.monitor_name);
4819 test_multi_sz("Dependent Files", dependent_files);
4820 /* test_dword("Attributes", ?); */
4821 test_dword("Version", info.info3.version);
4822 /* test_dword("TempDir", ?); */
4825 torture_assert(tctx,
4826 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4828 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4830 return true;
4833 #undef test_sz
4834 #undef test_dword
4836 static bool test_SetPrinterData(struct torture_context *tctx,
4837 struct dcerpc_binding_handle *b,
4838 struct policy_handle *handle,
4839 const char *value_name,
4840 enum winreg_Type type,
4841 uint8_t *data,
4842 uint32_t offered)
4844 struct spoolss_SetPrinterData r;
4846 r.in.handle = handle;
4847 r.in.value_name = value_name;
4848 r.in.type = type;
4849 r.in.data = data;
4850 r.in.offered = offered;
4852 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4853 r.in.value_name);
4855 torture_assert_ntstatus_ok(tctx,
4856 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4857 "SetPrinterData failed");
4858 torture_assert_werr_ok(tctx, r.out.result,
4859 "SetPrinterData failed");
4861 return true;
4864 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4865 struct dcerpc_binding_handle *b,
4866 struct policy_handle *handle,
4867 const char *printer_name,
4868 struct dcerpc_binding_handle *winreg_handle,
4869 struct policy_handle *hive_handle)
4871 const char *values[] = {
4872 "spootyfoot",
4873 "spooty\\foot",
4874 #if 0
4875 /* FIXME: not working with s3 atm. */
4876 "spooty,foot",
4877 "spooty,fo,ot",
4878 #endif
4879 "spooty foot",
4880 #if 0
4881 /* FIXME: not working with s3 atm. */
4882 "spooty\\fo,ot",
4883 "spooty,fo\\ot"
4884 #endif
4886 int i;
4888 for (i=0; i < ARRAY_SIZE(values); i++) {
4890 enum winreg_Type type, expected_type = REG_SZ;
4891 DATA_BLOB blob;
4892 uint8_t *data;
4893 uint32_t needed;
4895 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4896 type = REG_SZ;
4898 torture_assert(tctx,
4899 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4900 "SetPrinterData failed");
4902 torture_assert(tctx,
4903 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4904 "GetPrinterData failed");
4906 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4907 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4908 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4910 if (winreg_handle && hive_handle) {
4912 enum winreg_Type w_type;
4913 uint32_t w_size;
4914 uint32_t w_length;
4915 uint8_t *w_data;
4917 torture_assert(tctx,
4918 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4919 printer_name, "PrinterDriverData", values[i],
4920 &w_type, &w_size, &w_length, &w_data), "");
4922 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4923 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4924 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4925 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4928 torture_assert(tctx,
4929 test_DeletePrinterData(tctx, b, handle, values[i]),
4930 "DeletePrinterData failed");
4933 return true;
4937 static bool test_EnumPrinterKey(struct torture_context *tctx,
4938 struct dcerpc_binding_handle *b,
4939 struct policy_handle *handle,
4940 const char *key_name,
4941 const char ***array);
4943 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4944 struct dcerpc_binding_handle *b,
4945 struct policy_handle *handle,
4946 const char *key_name,
4947 const char *value_name,
4948 enum winreg_Type type,
4949 uint8_t *data,
4950 uint32_t offered)
4952 NTSTATUS status;
4953 struct spoolss_SetPrinterDataEx r;
4955 r.in.handle = handle;
4956 r.in.key_name = key_name;
4957 r.in.value_name = value_name;
4958 r.in.type = type;
4959 r.in.data = data;
4960 r.in.offered = offered;
4962 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4963 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4965 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4967 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4968 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4970 return true;
4973 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4974 struct dcerpc_pipe *p,
4975 struct policy_handle *handle)
4977 struct dcerpc_binding_handle *b = p->binding_handle;
4978 const char *value_name = "dog";
4979 const char *keys[] = {
4980 "torturedataex",
4981 "torture data ex",
4982 "torturedataex_with_subkey\\subkey",
4983 "torturedataex_with_subkey\\subkey:0",
4984 "torturedataex_with_subkey\\subkey:1",
4985 "torturedataex_with_subkey\\subkey\\subsubkey",
4986 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4987 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4988 "torture,data",
4989 "torture,data,ex",
4990 "torture,data\\ex",
4991 "torture\\data,ex",
4992 "torture/data",
4993 "torture/data ex",
4994 "torture/data ex/sub",
4995 "torture//data",
4996 "torture//data ex",
4997 "torture//data ex/sub",
4998 "torture//data ex//sub",
5000 int i;
5002 for (i=0; i < ARRAY_SIZE(keys); i++) {
5004 char *c;
5005 const char *key;
5006 enum winreg_Type type;
5007 DATA_BLOB blob_in, blob_out;
5008 const char **subkeys;
5009 uint32_t ecount;
5010 struct spoolss_PrinterEnumValues *einfo;
5011 uint32_t needed;
5013 blob_in = data_blob_talloc(tctx, NULL, 42);
5015 generate_random_buffer(blob_in.data, blob_in.length);
5017 torture_assert(tctx,
5018 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5019 "failed to call SetPrinterDataEx");
5021 torture_assert(tctx,
5022 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5023 "failed to call GetPrinterDataEx");
5025 blob_out.length = needed;
5026 torture_assert(tctx,
5027 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5028 "failed to call EnumPrinterDataEx");
5030 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5031 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5032 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5034 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5035 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5036 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5037 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5038 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5039 if (einfo[0].data_length > 0) {
5040 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5043 key = talloc_strdup(tctx, keys[i]);
5045 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5046 return false;
5049 c = strchr(key, '\\');
5050 if (c) {
5051 int k;
5053 /* we have subkeys */
5055 *c = 0;
5057 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5058 return false;
5061 for (k=0; subkeys && subkeys[k]; k++) {
5063 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5065 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5066 return false;
5070 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5071 return false;
5074 } else {
5075 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5076 return false;
5081 return true;
5084 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5085 struct dcerpc_pipe *p,
5086 struct policy_handle *handle)
5088 struct dcerpc_binding_handle *b = p->binding_handle;
5089 const char *key = "torturedataex";
5090 const char *values[] = {
5091 "torture_value",
5092 "torture value",
5093 "torture,value",
5094 "torture/value",
5095 "torture\\value",
5096 "torture\\\\value"
5098 int i;
5100 for (i=0; i < ARRAY_SIZE(values); i++) {
5102 enum winreg_Type type;
5103 DATA_BLOB blob_in, blob_out;
5104 uint32_t ecount;
5105 struct spoolss_PrinterEnumValues *einfo;
5106 uint32_t needed;
5108 if (torture_setting_bool(tctx, "samba3", false)) {
5109 char *q;
5110 q = strrchr(values[i], ',');
5111 if (q) {
5112 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5113 values[i]);
5114 continue;
5118 blob_in = data_blob_talloc(tctx, NULL, 42);
5120 generate_random_buffer(blob_in.data, blob_in.length);
5122 torture_assert(tctx,
5123 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5124 "failed to call SetPrinterDataEx");
5126 torture_assert(tctx,
5127 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5128 "failed to call GetPrinterDataEx");
5130 blob_out.length = needed;
5131 torture_assert(tctx,
5132 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5133 "failed to call EnumPrinterDataEx");
5135 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5136 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5137 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5139 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5140 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5141 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5142 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5143 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5144 if (einfo[0].data_length > 0) {
5145 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5148 torture_assert(tctx,
5149 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5150 "failed to call DeletePrinterDataEx");
5153 return true;
5157 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5158 struct dcerpc_pipe *p,
5159 struct policy_handle *handle,
5160 const char *printername,
5161 struct dcerpc_binding_handle *winreg_handle,
5162 struct policy_handle *hive_handle)
5164 struct dcerpc_binding_handle *b = p->binding_handle;
5165 const char *value_name = "dog";
5166 const char *key_name = "torturedataex";
5167 enum winreg_Type types[] = {
5168 REG_SZ,
5169 REG_MULTI_SZ,
5170 REG_DWORD,
5171 REG_BINARY
5173 const char *str = "abcdefghi";
5174 int t, s;
5176 for (t=0; t < ARRAY_SIZE(types); t++) {
5177 for (s=0; s < strlen(str); s++) {
5179 enum winreg_Type type;
5180 const char *string = talloc_strndup(tctx, str, s);
5181 const char *array[2];
5182 DATA_BLOB blob = data_blob_string_const(string);
5183 DATA_BLOB data;
5184 uint8_t *data_out;
5185 uint32_t needed, offered = 0;
5186 uint32_t ecount;
5187 struct spoolss_PrinterEnumValues *einfo;
5189 array[0] = talloc_strdup(tctx, string);
5190 array[1] = NULL;
5192 if (types[t] == REG_DWORD) {
5193 s = 0xffff;
5196 switch (types[t]) {
5197 case REG_BINARY:
5198 data = blob;
5199 offered = blob.length;
5200 break;
5201 case REG_DWORD:
5202 data = data_blob_talloc(tctx, NULL, 4);
5203 SIVAL(data.data, 0, 0x12345678);
5204 offered = 4;
5205 break;
5206 case REG_SZ:
5207 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5208 type = REG_SZ;
5209 offered = data.length;
5210 /*strlen_m_term(data.string)*2;*/
5211 break;
5212 case REG_MULTI_SZ:
5213 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5214 type = REG_MULTI_SZ;
5215 offered = data.length;
5216 break;
5217 default:
5218 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5221 torture_assert(tctx,
5222 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5223 "failed to call SetPrinterDataEx");
5225 torture_assert(tctx,
5226 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5227 "failed to call GetPrinterDataEx");
5229 torture_assert(tctx,
5230 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5231 "failed to call EnumPrinterDataEx");
5233 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5234 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5235 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5237 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5238 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5239 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5240 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5241 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5242 if (einfo[0].data_length > 0) {
5243 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5246 if (winreg_handle && hive_handle) {
5247 enum winreg_Type w_type;
5248 uint32_t w_size;
5249 uint32_t w_length;
5250 uint8_t *w_data;
5252 torture_assert(tctx,
5253 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5254 printername, key_name, value_name,
5255 &w_type, &w_size, &w_length, &w_data), "");
5257 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5258 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5259 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5260 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5263 torture_assert(tctx,
5264 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5265 "failed to call DeletePrinterDataEx");
5269 return true;
5272 static bool test_PrinterData_winreg(struct torture_context *tctx,
5273 struct dcerpc_pipe *p,
5274 struct policy_handle *handle,
5275 const char *printer_name)
5277 struct dcerpc_binding_handle *b = p->binding_handle;
5278 struct dcerpc_pipe *p2;
5279 bool ret = true;
5280 struct policy_handle hive_handle;
5281 struct dcerpc_binding_handle *b2;
5283 torture_assert_ntstatus_ok(tctx,
5284 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5285 "could not open winreg pipe");
5286 b2 = p2->binding_handle;
5288 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5290 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5291 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5293 test_winreg_CloseKey(tctx, b2, &hive_handle);
5295 talloc_free(p2);
5297 return ret;
5300 static bool test_Forms_winreg(struct torture_context *tctx,
5301 struct dcerpc_binding_handle *b,
5302 struct policy_handle *handle,
5303 bool print_server,
5304 const char *printer_name)
5306 struct dcerpc_pipe *p2;
5307 bool ret = true;
5308 struct policy_handle hive_handle;
5309 struct dcerpc_binding_handle *b2;
5311 torture_assert_ntstatus_ok(tctx,
5312 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5313 "could not open winreg pipe");
5314 b2 = p2->binding_handle;
5316 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5318 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5320 test_winreg_CloseKey(tctx, b2, &hive_handle);
5322 talloc_free(p2);
5324 return ret;
5327 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5328 struct dcerpc_pipe *p,
5329 struct policy_handle *handle,
5330 const char *printer_name)
5332 struct dcerpc_binding_handle *b = p->binding_handle;
5333 struct dcerpc_pipe *p2;
5334 bool ret = true;
5335 struct policy_handle hive_handle;
5336 struct dcerpc_binding_handle *b2;
5338 torture_assert_ntstatus_ok(tctx,
5339 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5340 "could not open winreg pipe");
5341 b2 = p2->binding_handle;
5343 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5345 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5347 test_winreg_CloseKey(tctx, b2, &hive_handle);
5349 talloc_free(p2);
5351 return ret;
5354 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5355 struct dcerpc_pipe *p,
5356 struct policy_handle *handle,
5357 const char *printer_name,
5358 const char *driver_name,
5359 const char *environment,
5360 enum spoolss_DriverOSVersion version)
5362 struct dcerpc_binding_handle *b = p->binding_handle;
5363 struct dcerpc_pipe *p2;
5364 bool ret = true;
5365 struct policy_handle hive_handle;
5366 struct dcerpc_binding_handle *b2;
5368 torture_assert_ntstatus_ok(tctx,
5369 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5370 "could not open winreg pipe");
5371 b2 = p2->binding_handle;
5373 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5375 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5377 test_winreg_CloseKey(tctx, b2, &hive_handle);
5379 talloc_free(p2);
5381 return ret;
5384 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5385 struct dcerpc_binding_handle *b,
5386 const char *environment)
5388 struct dcerpc_pipe *p2;
5389 bool ret = true;
5390 struct policy_handle hive_handle;
5391 struct dcerpc_binding_handle *b2;
5393 torture_assert_ntstatus_ok(tctx,
5394 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5395 "could not open winreg pipe");
5396 b2 = p2->binding_handle;
5398 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5400 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5402 test_winreg_CloseKey(tctx, b2, &hive_handle);
5404 talloc_free(p2);
5406 return ret;
5409 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5410 struct dcerpc_pipe *p,
5411 struct policy_handle *handle,
5412 const char *printer_name)
5414 struct spoolss_SetPrinterInfoCtr info_ctr;
5415 struct spoolss_DevmodeContainer devmode_ctr;
5416 struct sec_desc_buf secdesc_ctr;
5417 union spoolss_SetPrinterInfo sinfo;
5418 union spoolss_PrinterInfo info;
5419 struct dcerpc_binding_handle *b = p->binding_handle;
5420 const char *pname;
5422 ZERO_STRUCT(info_ctr);
5423 ZERO_STRUCT(devmode_ctr);
5424 ZERO_STRUCT(secdesc_ctr);
5426 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5428 torture_assert(tctx,
5429 test_GetPrinter_level(tctx, b, handle, 2, &info),
5430 "failed to query Printer level 2");
5432 torture_assert(tctx,
5433 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5434 "failed to convert");
5436 info_ctr.level = 2;
5437 info_ctr.info = sinfo;
5439 #define TEST_SZ(wname, iname) \
5440 do {\
5441 enum winreg_Type type;\
5442 uint8_t *data;\
5443 uint32_t needed;\
5444 DATA_BLOB blob;\
5445 const char *str;\
5446 torture_assert(tctx,\
5447 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5448 "failed to query");\
5449 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5450 blob = data_blob_const(data, needed);\
5451 torture_assert(tctx,\
5452 pull_reg_sz(tctx, &blob, &str),\
5453 "failed to pull REG_SZ");\
5454 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5455 } while(0);
5458 #define TEST_SET_SZ(wname, iname, val) \
5459 do {\
5460 enum winreg_Type type;\
5461 uint8_t *data;\
5462 uint32_t needed;\
5463 DATA_BLOB blob;\
5464 const char *str;\
5465 sinfo.info2->iname = val;\
5466 torture_assert(tctx,\
5467 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5468 "failed to call SetPrinter");\
5469 torture_assert(tctx,\
5470 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5471 "failed to query");\
5472 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5473 blob = data_blob_const(data, needed);\
5474 torture_assert(tctx,\
5475 pull_reg_sz(tctx, &blob, &str),\
5476 "failed to pull REG_SZ");\
5477 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5478 } while(0);
5480 #define TEST_SET_DWORD(wname, iname, val) \
5481 do {\
5482 enum winreg_Type type;\
5483 uint8_t *data;\
5484 uint32_t needed;\
5485 uint32_t value;\
5486 sinfo.info2->iname = val;\
5487 torture_assert(tctx,\
5488 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5489 "failed to call SetPrinter");\
5490 torture_assert(tctx,\
5491 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5492 "failed to query");\
5493 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5494 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5495 value = IVAL(data, 0); \
5496 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5497 } while(0);
5499 TEST_SET_SZ("description", comment, "newval");
5500 TEST_SET_SZ("location", location, "newval");
5501 /* TEST_SET_DWORD("priority", priority, 25); */
5503 torture_assert(tctx,
5504 test_GetPrinter_level(tctx, b, handle, 2, &info),
5505 "failed to query Printer level 2");
5507 TEST_SZ("description", info.info2.comment);
5508 TEST_SZ("driverName", info.info2.drivername);
5509 TEST_SZ("location", info.info2.location);
5511 pname = strrchr(info.info2.printername, '\\');
5512 if (pname == NULL) {
5513 pname = info.info2.printername;
5514 } else {
5515 pname++;
5517 TEST_SZ("printerName", pname);
5518 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5519 /* TEST_SZ("printShareName", info.info2.sharename); */
5521 /* FIXME gd: complete the list */
5523 #undef TEST_SZ
5524 #undef TEST_SET_SZ
5525 #undef TEST_DWORD
5527 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5529 return true;
5532 static bool test_print_processors_winreg(struct torture_context *tctx,
5533 void *private_data)
5535 struct test_spoolss_context *ctx =
5536 talloc_get_type_abort(private_data, struct test_spoolss_context);
5537 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5538 struct dcerpc_binding_handle *b = p->binding_handle;
5540 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5543 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5544 struct dcerpc_binding_handle *b,
5545 struct policy_handle *handle,
5546 uint32_t *change_id)
5548 enum winreg_Type type;
5549 uint8_t *data;
5550 uint32_t needed;
5552 torture_assert(tctx,
5553 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5554 "failed to call GetPrinterData");
5556 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5557 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5559 *change_id = IVAL(data, 0);
5561 return true;
5564 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5565 struct dcerpc_pipe *p,
5566 struct policy_handle *handle,
5567 uint32_t *change_id)
5569 enum winreg_Type type;
5570 uint8_t *data;
5571 uint32_t needed;
5573 torture_assert(tctx,
5574 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5575 "failed to call GetPrinterData");
5577 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5578 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5580 *change_id = IVAL(data, 0);
5582 return true;
5585 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5586 struct dcerpc_binding_handle *b,
5587 struct policy_handle *handle,
5588 uint32_t *change_id)
5590 union spoolss_PrinterInfo info;
5592 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5593 "failed to query Printer level 0");
5595 *change_id = info.info0.change_id;
5597 return true;
5600 static bool test_ChangeID(struct torture_context *tctx,
5601 struct dcerpc_pipe *p,
5602 struct policy_handle *handle)
5604 uint32_t change_id, change_id_ex, change_id_info;
5605 uint32_t change_id2, change_id_ex2, change_id_info2;
5606 union spoolss_PrinterInfo info;
5607 const char *comment;
5608 struct dcerpc_binding_handle *b = p->binding_handle;
5610 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5612 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5613 "failed to query for ChangeID");
5614 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5615 "failed to query for ChangeID");
5616 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5617 "failed to query for ChangeID");
5619 torture_assert_int_equal(tctx, change_id, change_id_ex,
5620 "change_ids should all be equal");
5621 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5622 "change_ids should all be equal");
5625 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5627 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5628 "failed to query for ChangeID");
5629 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5630 "failed to query Printer level 2");
5631 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5632 "failed to query for ChangeID");
5633 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5634 "failed to query for ChangeID");
5635 torture_assert_int_equal(tctx, change_id, change_id_ex,
5636 "change_id should not have changed");
5637 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5638 "change_id should not have changed");
5641 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5643 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5644 "failed to query for ChangeID");
5645 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5646 "failed to query for ChangeID");
5647 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5648 "failed to query for ChangeID");
5649 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5650 "failed to query Printer level 2");
5651 comment = talloc_strdup(tctx, info.info2.comment);
5654 struct spoolss_SetPrinterInfoCtr info_ctr;
5655 struct spoolss_DevmodeContainer devmode_ctr;
5656 struct sec_desc_buf secdesc_ctr;
5657 union spoolss_SetPrinterInfo sinfo;
5659 ZERO_STRUCT(info_ctr);
5660 ZERO_STRUCT(devmode_ctr);
5661 ZERO_STRUCT(secdesc_ctr);
5664 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5665 sinfo.info2->comment = "torture_comment";
5667 info_ctr.level = 2;
5668 info_ctr.info = sinfo;
5670 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5671 "failed to call SetPrinter");
5673 sinfo.info2->comment = comment;
5675 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5676 "failed to call SetPrinter");
5680 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5681 "failed to query for ChangeID");
5682 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5683 "failed to query for ChangeID");
5684 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5685 "failed to query for ChangeID");
5687 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5688 "change_ids should all be equal");
5689 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5690 "change_ids should all be equal");
5692 torture_assert(tctx, (change_id < change_id2),
5693 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5694 change_id2, change_id));
5695 torture_assert(tctx, (change_id_ex < change_id_ex2),
5696 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5697 change_id_ex2, change_id_ex));
5698 torture_assert(tctx, (change_id_info < change_id_info2),
5699 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5700 change_id_info2, change_id_info));
5702 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5704 return true;
5707 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5708 struct dcerpc_pipe *p,
5709 struct policy_handle *handle)
5711 NTSTATUS status;
5712 struct dcerpc_binding *b;
5713 struct dcerpc_pipe *p2;
5714 struct spoolss_ClosePrinter cp;
5716 /* only makes sense on SMB */
5717 if (p->conn->transport.transport != NCACN_NP) {
5718 return true;
5721 torture_comment(tctx, "Testing close on secondary pipe\n");
5723 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5724 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5726 status = dcerpc_secondary_connection(p, &p2, b);
5727 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5729 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5730 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5732 cp.in.handle = handle;
5733 cp.out.handle = handle;
5735 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5736 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5737 "ERROR: Allowed close on secondary connection");
5739 talloc_free(p2);
5741 return true;
5744 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5745 struct dcerpc_binding_handle *b, const char *name)
5747 NTSTATUS status;
5748 struct spoolss_OpenPrinter op;
5749 struct spoolss_OpenPrinterEx opEx;
5750 struct policy_handle handle;
5751 bool ret = true;
5753 op.in.printername = name;
5754 op.in.datatype = NULL;
5755 op.in.devmode_ctr.devmode= NULL;
5756 op.in.access_mask = 0;
5757 op.out.handle = &handle;
5759 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5761 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5762 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5763 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5764 "unexpected result");
5766 if (W_ERROR_IS_OK(op.out.result)) {
5767 ret &=test_ClosePrinter(tctx, b, &handle);
5770 opEx.in.printername = name;
5771 opEx.in.datatype = NULL;
5772 opEx.in.devmode_ctr.devmode = NULL;
5773 opEx.in.access_mask = 0;
5774 opEx.in.level = 1;
5775 opEx.in.userlevel.level1 = NULL;
5776 opEx.out.handle = &handle;
5778 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5780 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5781 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5782 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5783 "unexpected result");
5785 if (W_ERROR_IS_OK(opEx.out.result)) {
5786 ret &=test_ClosePrinter(tctx, b, &handle);
5789 return ret;
5792 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5793 void *private_data)
5795 struct test_spoolss_context *ctx =
5796 talloc_get_type_abort(private_data, struct test_spoolss_context);
5798 const char *badnames[] = {
5799 "__INVALID_PRINTER__",
5800 "\\\\__INVALID_HOST__",
5802 "\\\\\\",
5803 "\\\\\\__INVALID_PRINTER__"
5805 const char *badname;
5806 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5807 const char *server_name = dcerpc_server_name(p);
5808 struct dcerpc_binding_handle *b = p->binding_handle;
5809 int i;
5811 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5812 torture_assert(tctx,
5813 test_OpenPrinter_badname(tctx, b, badnames[i]),
5814 "");
5817 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5818 torture_assert(tctx,
5819 test_OpenPrinter_badname(tctx, b, badname),
5820 "");
5822 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5823 torture_assert(tctx,
5824 test_OpenPrinter_badname(tctx, b, badname),
5825 "");
5827 return true;
5830 static bool test_OpenPrinter(struct torture_context *tctx,
5831 struct dcerpc_pipe *p,
5832 const char *name,
5833 const char *environment,
5834 bool open_only)
5836 NTSTATUS status;
5837 struct spoolss_OpenPrinter r;
5838 struct policy_handle handle;
5839 bool ret = true;
5840 struct dcerpc_binding_handle *b = p->binding_handle;
5842 r.in.printername = name;
5843 r.in.datatype = NULL;
5844 r.in.devmode_ctr.devmode= NULL;
5845 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5846 r.out.handle = &handle;
5848 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5850 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5852 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5854 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5856 if (open_only) {
5857 goto close_printer;
5860 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5861 ret = false;
5864 if (!torture_setting_bool(tctx, "samba3", false)) {
5865 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5866 ret = false;
5870 close_printer:
5871 if (!test_ClosePrinter(tctx, b, &handle)) {
5872 ret = false;
5875 return ret;
5878 static bool test_OpenPrinterEx(struct torture_context *tctx,
5879 struct dcerpc_binding_handle *b,
5880 const char *printername,
5881 const char *datatype,
5882 struct spoolss_DeviceMode *devmode,
5883 uint32_t access_mask,
5884 uint32_t level,
5885 union spoolss_UserLevel *userlevel,
5886 struct policy_handle *handle,
5887 WERROR expected_result)
5889 struct spoolss_OpenPrinterEx r;
5891 r.in.printername = printername;
5892 r.in.datatype = datatype;
5893 r.in.devmode_ctr.devmode= devmode;
5894 r.in.access_mask = access_mask;
5895 r.in.level = level;
5896 r.in.userlevel = *userlevel;
5897 r.out.handle = handle;
5899 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5901 torture_assert_ntstatus_ok(tctx,
5902 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5903 "OpenPrinterEx failed");
5905 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5906 "OpenPrinterEx failed");
5908 return true;
5911 static bool call_OpenPrinterEx(struct torture_context *tctx,
5912 struct dcerpc_pipe *p,
5913 const char *name,
5914 struct spoolss_DeviceMode *devmode,
5915 struct policy_handle *handle)
5917 union spoolss_UserLevel userlevel;
5918 struct spoolss_UserLevel1 userlevel1;
5919 struct dcerpc_binding_handle *b = p->binding_handle;
5921 userlevel1.size = 1234;
5922 userlevel1.client = "hello";
5923 userlevel1.user = "spottyfoot!";
5924 userlevel1.build = 1;
5925 userlevel1.major = 2;
5926 userlevel1.minor = 3;
5927 userlevel1.processor = 4;
5929 userlevel.level1 = &userlevel1;
5931 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5932 SEC_FLAG_MAXIMUM_ALLOWED,
5934 &userlevel,
5935 handle,
5936 WERR_OK);
5939 static bool test_printer_rename(struct torture_context *tctx,
5940 void *private_data)
5942 struct torture_printer_context *t =
5943 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5944 struct dcerpc_pipe *p = t->spoolss_pipe;
5946 bool ret = true;
5947 union spoolss_PrinterInfo info;
5948 union spoolss_SetPrinterInfo sinfo;
5949 struct spoolss_SetPrinterInfoCtr info_ctr;
5950 struct spoolss_DevmodeContainer devmode_ctr;
5951 struct sec_desc_buf secdesc_ctr;
5952 const char *printer_name;
5953 const char *printer_name_orig;
5954 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5955 struct policy_handle new_handle;
5956 const char *q;
5957 struct dcerpc_binding_handle *b = p->binding_handle;
5959 ZERO_STRUCT(devmode_ctr);
5960 ZERO_STRUCT(secdesc_ctr);
5962 torture_comment(tctx, "Testing Printer rename operations\n");
5964 torture_assert(tctx,
5965 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5966 "failed to call GetPrinter level 2");
5968 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5970 q = strrchr(info.info2.printername, '\\');
5971 if (q) {
5972 torture_warning(tctx,
5973 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5976 torture_assert(tctx,
5977 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5979 sinfo.info2->printername = printer_name_new;
5981 info_ctr.level = 2;
5982 info_ctr.info = sinfo;
5984 torture_assert(tctx,
5985 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5986 "failed to call SetPrinter level 2");
5988 torture_assert(tctx,
5989 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5990 "failed to call GetPrinter level 2");
5992 printer_name = talloc_strdup(tctx, info.info2.printername);
5994 q = strrchr(info.info2.printername, '\\');
5995 if (q) {
5996 torture_warning(tctx,
5997 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5998 q++;
5999 printer_name = q;
6002 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6003 "new printer name was not set");
6005 /* samba currently cannot fully rename printers */
6006 if (!torture_setting_bool(tctx, "samba3", false)) {
6007 torture_assert(tctx,
6008 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6009 "still can open printer with oldname after rename");
6010 } else {
6011 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6014 torture_assert(tctx,
6015 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6016 "failed to open printer with new name");
6018 torture_assert(tctx,
6019 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6020 "failed to call GetPrinter level 2");
6022 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6023 "new printer name was not set");
6025 torture_assert(tctx,
6026 test_ClosePrinter(tctx, b, &new_handle),
6027 "failed to close printer");
6029 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6031 return ret;
6034 static bool test_openprinter(struct torture_context *tctx,
6035 struct dcerpc_binding_handle *b,
6036 const char *real_printername)
6038 union spoolss_UserLevel userlevel;
6039 struct policy_handle handle;
6040 struct spoolss_UserLevel1 userlevel1;
6041 const char *printername = NULL;
6042 int i;
6044 struct {
6045 const char *suffix;
6046 WERROR expected_result;
6047 } tests[] = {
6049 .suffix = "rubbish",
6050 .expected_result = WERR_INVALID_PRINTER_NAME
6052 .suffix = ", LocalOnl",
6053 .expected_result = WERR_INVALID_PRINTER_NAME
6055 .suffix = ", localOnly",
6056 .expected_result = WERR_INVALID_PRINTER_NAME
6058 .suffix = ", localonl",
6059 .expected_result = WERR_INVALID_PRINTER_NAME
6061 .suffix = ",LocalOnl",
6062 .expected_result = WERR_INVALID_PRINTER_NAME
6064 .suffix = ",localOnl2",
6065 .expected_result = WERR_INVALID_PRINTER_NAME
6067 .suffix = ", DrvConver2t",
6068 .expected_result = WERR_INVALID_PRINTER_NAME
6070 .suffix = ", drvconvert",
6071 .expected_result = WERR_INVALID_PRINTER_NAME
6073 .suffix = ",drvconvert",
6074 .expected_result = WERR_INVALID_PRINTER_NAME
6076 .suffix = ", DrvConvert",
6077 .expected_result = WERR_OK
6079 .suffix = " , DrvConvert",
6080 .expected_result = WERR_INVALID_PRINTER_NAME
6082 .suffix = ",DrvConvert",
6083 .expected_result = WERR_OK
6085 .suffix = ", DrvConvertsadfasdf",
6086 .expected_result = WERR_OK
6088 .suffix = ",DrvConvertasdfasd",
6089 .expected_result = WERR_OK
6091 .suffix = ", LocalOnly",
6092 .expected_result = WERR_OK
6094 .suffix = " , LocalOnly",
6095 .expected_result = WERR_INVALID_PRINTER_NAME
6097 .suffix = ",LocalOnly",
6098 .expected_result = WERR_OK
6100 .suffix = ", LocalOnlysagi4gjfkd",
6101 .expected_result = WERR_OK
6103 .suffix = ",LocalOnlysagi4gjfkd",
6104 .expected_result = WERR_OK
6108 userlevel1.size = 1234;
6109 userlevel1.client = "hello";
6110 userlevel1.user = "spottyfoot!";
6111 userlevel1.build = 1;
6112 userlevel1.major = 2;
6113 userlevel1.minor = 3;
6114 userlevel1.processor = 4;
6116 userlevel.level1 = &userlevel1;
6118 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6120 torture_assert(tctx,
6121 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6122 &userlevel, &handle,
6123 WERR_OK),
6124 "OpenPrinterEx failed");
6125 test_ClosePrinter(tctx, b, &handle);
6127 for (i=0; i < ARRAY_SIZE(tests); i++) {
6129 printername = talloc_asprintf(tctx, "%s%s",
6130 real_printername,
6131 tests[i].suffix);
6133 torture_assert(tctx,
6134 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6135 &userlevel, &handle,
6136 tests[i].expected_result),
6137 "OpenPrinterEx failed");
6138 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6139 test_ClosePrinter(tctx, b, &handle);
6143 return true;
6147 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6148 struct dcerpc_pipe *p,
6149 const char *name,
6150 const char *environment)
6152 struct policy_handle handle;
6153 bool ret = true;
6154 struct dcerpc_binding_handle *b = p->binding_handle;
6156 if (!test_openprinter(tctx, b, name)) {
6157 return false;
6160 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6161 return false;
6164 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6165 ret = false;
6168 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6169 ret = false;
6172 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6173 ret = false;
6176 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6177 ret = false;
6180 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6181 ret = false;
6184 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6185 ret = false;
6188 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6189 ret = false;
6192 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6193 ret = false;
6196 if (!test_printer_all_keys(tctx, b, &handle)) {
6197 ret = false;
6200 if (!test_PausePrinter(tctx, b, &handle)) {
6201 ret = false;
6204 if (!test_DoPrintTest(tctx, b, &handle)) {
6205 ret = false;
6208 if (!test_ResumePrinter(tctx, b, &handle)) {
6209 ret = false;
6212 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6213 ret = false;
6216 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6217 ret = false;
6220 if (!torture_setting_bool(tctx, "samba3", false)) {
6221 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6222 ret = false;
6226 if (!test_ClosePrinter(tctx, b, &handle)) {
6227 ret = false;
6230 return ret;
6233 static bool test_EnumPrinters_old(struct torture_context *tctx,
6234 void *private_data)
6236 struct test_spoolss_context *ctx =
6237 talloc_get_type_abort(private_data, struct test_spoolss_context);
6238 struct spoolss_EnumPrinters r;
6239 NTSTATUS status;
6240 uint16_t levels[] = {1, 2, 4, 5};
6241 int i;
6242 bool ret = true;
6243 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6244 struct dcerpc_binding_handle *b = p->binding_handle;
6246 for (i=0;i<ARRAY_SIZE(levels);i++) {
6247 union spoolss_PrinterInfo *info;
6248 int j;
6249 uint32_t needed;
6250 uint32_t count;
6252 r.in.flags = PRINTER_ENUM_LOCAL;
6253 r.in.server = "";
6254 r.in.level = levels[i];
6255 r.in.buffer = NULL;
6256 r.in.offered = 0;
6257 r.out.needed = &needed;
6258 r.out.count = &count;
6259 r.out.info = &info;
6261 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6263 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6264 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6266 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6267 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6268 r.in.buffer = &blob;
6269 r.in.offered = needed;
6270 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6273 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6275 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6277 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6279 if (!info) {
6280 torture_comment(tctx, "No printers returned\n");
6281 return true;
6284 for (j=0;j<count;j++) {
6285 if (r.in.level == 1) {
6286 char *unc = talloc_strdup(tctx, info[j].info1.name);
6287 char *slash, *name, *full_name;
6288 name = unc;
6289 if (unc[0] == '\\' && unc[1] == '\\') {
6290 unc +=2;
6292 slash = strchr(unc, '\\');
6293 if (slash) {
6294 slash++;
6295 name = slash;
6297 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6298 dcerpc_server_name(p), name);
6299 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6300 ret = false;
6302 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6303 ret = false;
6305 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6306 ret = false;
6308 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6309 ret = false;
6315 return ret;
6318 static bool test_EnumPrinters_level(struct torture_context *tctx,
6319 struct dcerpc_binding_handle *b,
6320 uint32_t flags,
6321 const char *servername,
6322 uint32_t level,
6323 uint32_t *count_p,
6324 union spoolss_PrinterInfo **info_p)
6326 struct spoolss_EnumPrinters r;
6327 union spoolss_PrinterInfo *info;
6328 uint32_t needed;
6329 uint32_t count;
6331 r.in.flags = flags;
6332 r.in.server = servername;
6333 r.in.level = level;
6334 r.in.buffer = NULL;
6335 r.in.offered = 0;
6336 r.out.needed = &needed;
6337 r.out.count = &count;
6338 r.out.info = &info;
6340 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6341 r.in.server, r.in.level);
6343 torture_assert_ntstatus_ok(tctx,
6344 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6345 "EnumPrinters failed");
6346 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6347 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6348 r.in.buffer = &blob;
6349 r.in.offered = needed;
6350 torture_assert_ntstatus_ok(tctx,
6351 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6352 "EnumPrinters failed");
6355 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6357 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6359 if (count_p) {
6360 *count_p = count;
6362 if (info_p) {
6363 *info_p = info;
6366 return true;
6369 static const char *get_short_printername(struct torture_context *tctx,
6370 const char *name)
6372 const char *short_name;
6374 if (name[0] == '\\' && name[1] == '\\') {
6375 name += 2;
6376 short_name = strchr(name, '\\');
6377 if (short_name) {
6378 return talloc_strdup(tctx, short_name+1);
6382 return name;
6385 static const char *get_full_printername(struct torture_context *tctx,
6386 const char *name)
6388 const char *full_name = talloc_strdup(tctx, name);
6389 char *p;
6391 if (name && name[0] == '\\' && name[1] == '\\') {
6392 name += 2;
6393 p = strchr(name, '\\');
6394 if (p) {
6395 return full_name;
6399 return NULL;
6402 static bool test_OnePrinter_servername(struct torture_context *tctx,
6403 struct dcerpc_pipe *p,
6404 struct dcerpc_binding_handle *b,
6405 const char *servername,
6406 const char *printername)
6408 union spoolss_PrinterInfo info;
6409 const char *short_name = get_short_printername(tctx, printername);
6410 const char *full_name = get_full_printername(tctx, printername);
6412 if (short_name) {
6413 struct policy_handle handle;
6414 torture_assert(tctx,
6415 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6416 "failed to open printer");
6418 torture_assert(tctx,
6419 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6420 "failed to get printer info");
6422 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6423 "unexpected servername");
6424 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6425 "unexpected printername");
6427 if (info.info2.devmode) {
6428 const char *expected_devicename;
6429 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6430 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6431 "unexpected devicemode devicename");
6434 torture_assert(tctx,
6435 test_ClosePrinter(tctx, b, &handle),
6436 "failed to close printer");
6439 if (full_name) {
6440 struct policy_handle handle;
6442 torture_assert(tctx,
6443 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6444 "failed to open printer");
6446 torture_assert(tctx,
6447 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6448 "failed to get printer info");
6450 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6451 "unexpected servername");
6452 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6453 "unexpected printername");
6455 if (info.info2.devmode) {
6456 const char *expected_devicename;
6457 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6458 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6459 "unexpected devicemode devicename");
6462 torture_assert(tctx,
6463 test_ClosePrinter(tctx, b, &handle),
6464 "failed to close printer");
6467 return true;
6470 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6471 void *private_data)
6473 struct test_spoolss_context *ctx =
6474 talloc_get_type_abort(private_data, struct test_spoolss_context);
6475 int i;
6476 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6477 struct dcerpc_binding_handle *b = p->binding_handle;
6478 uint32_t count;
6479 union spoolss_PrinterInfo *info;
6480 const char *servername;
6481 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6483 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6485 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6487 torture_assert(tctx,
6488 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6489 "failed to enumerate printers");
6491 for (i=0; i < count; i++) {
6493 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6494 "unexpected servername");
6496 torture_assert(tctx,
6497 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6498 "failed to check printer");
6501 servername = "";
6503 torture_assert(tctx,
6504 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6505 "failed to enumerate printers");
6507 for (i=0; i < count; i++) {
6509 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6510 "unexpected servername");
6512 torture_assert(tctx,
6513 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6514 "failed to check printer");
6518 return true;
6522 static bool test_GetPrinterDriver(struct torture_context *tctx,
6523 struct dcerpc_binding_handle *b,
6524 struct policy_handle *handle,
6525 const char *driver_name)
6527 struct spoolss_GetPrinterDriver r;
6528 uint32_t needed;
6530 r.in.handle = handle;
6531 r.in.architecture = "W32X86";
6532 r.in.level = 1;
6533 r.in.buffer = NULL;
6534 r.in.offered = 0;
6535 r.out.needed = &needed;
6537 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6539 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6540 "failed to call GetPrinterDriver");
6541 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6542 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6543 r.in.buffer = &blob;
6544 r.in.offered = needed;
6545 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6546 "failed to call GetPrinterDriver");
6549 torture_assert_werr_ok(tctx, r.out.result,
6550 "failed to call GetPrinterDriver");
6552 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6554 return true;
6557 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6558 struct dcerpc_binding_handle *b,
6559 struct policy_handle *handle,
6560 const char *driver_name,
6561 const char *architecture,
6562 uint32_t level,
6563 uint32_t client_major_version,
6564 uint32_t client_minor_version,
6565 union spoolss_DriverInfo *info_p,
6566 WERROR *result_p)
6569 struct spoolss_GetPrinterDriver2 r;
6570 uint32_t needed;
6571 uint32_t server_major_version;
6572 uint32_t server_minor_version;
6574 r.in.handle = handle;
6575 r.in.architecture = architecture;
6576 r.in.client_major_version = client_major_version;
6577 r.in.client_minor_version = client_minor_version;
6578 r.in.buffer = NULL;
6579 r.in.offered = 0;
6580 r.in.level = level;
6581 r.out.needed = &needed;
6582 r.out.server_major_version = &server_major_version;
6583 r.out.server_minor_version = &server_minor_version;
6585 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6586 driver_name, r.in.level);
6588 torture_assert_ntstatus_ok(tctx,
6589 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6590 "failed to call GetPrinterDriver2");
6591 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6592 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6593 r.in.buffer = &blob;
6594 r.in.offered = needed;
6595 torture_assert_ntstatus_ok(tctx,
6596 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6597 "failed to call GetPrinterDriver2");
6600 if (result_p) {
6601 *result_p = r.out.result;
6604 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6605 switch (r.in.level) {
6606 case 101:
6607 case 8:
6608 torture_comment(tctx,
6609 "level %d not implemented, not considering as an error\n",
6610 r.in.level);
6611 return true;
6612 default:
6613 break;
6617 torture_assert_werr_ok(tctx, r.out.result,
6618 "failed to call GetPrinterDriver2");
6620 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6622 if (info_p) {
6623 *info_p = *r.out.info;
6626 return true;
6629 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6630 struct dcerpc_binding_handle *b,
6631 struct policy_handle *handle,
6632 const char *driver_name,
6633 const char *architecture)
6635 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6636 int i;
6639 for (i=0;i<ARRAY_SIZE(levels);i++) {
6641 torture_assert(tctx,
6642 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6643 "");
6646 return true;
6649 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6650 void *private_data)
6652 struct test_spoolss_context *ctx =
6653 talloc_get_type_abort(private_data, struct test_spoolss_context);
6654 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6655 int i;
6656 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6657 struct dcerpc_binding_handle *b = p->binding_handle;
6658 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6660 for (i=0;i<ARRAY_SIZE(levels);i++) {
6662 uint32_t count;
6663 union spoolss_DriverInfo *info;
6665 torture_assert(tctx,
6666 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6667 "failed to enumerate drivers");
6669 if (!info) {
6670 torture_comment(tctx, "No printer drivers returned\n");
6671 break;
6675 return true;
6678 static bool test_DeletePrinter(struct torture_context *tctx,
6679 struct dcerpc_binding_handle *b,
6680 struct policy_handle *handle)
6682 struct spoolss_DeletePrinter r;
6684 torture_comment(tctx, "Testing DeletePrinter\n");
6686 r.in.handle = handle;
6688 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6689 "failed to delete printer");
6690 torture_assert_werr_ok(tctx, r.out.result,
6691 "failed to delete printer");
6693 return true;
6696 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6697 struct dcerpc_binding_handle *b,
6698 uint32_t flags,
6699 uint32_t level,
6700 const char *name,
6701 bool *found)
6703 struct spoolss_EnumPrinters e;
6704 uint32_t count;
6705 union spoolss_PrinterInfo *info;
6706 uint32_t needed;
6707 int i;
6709 *found = false;
6711 e.in.flags = flags;
6712 e.in.server = NULL;
6713 e.in.level = level;
6714 e.in.buffer = NULL;
6715 e.in.offered = 0;
6716 e.out.count = &count;
6717 e.out.info = &info;
6718 e.out.needed = &needed;
6720 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6721 "failed to enum printers");
6723 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6724 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6725 e.in.buffer = &blob;
6726 e.in.offered = needed;
6728 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6729 "failed to enum printers");
6732 torture_assert_werr_ok(tctx, e.out.result,
6733 "failed to enum printers");
6735 for (i=0; i < count; i++) {
6737 const char *current = NULL;
6738 const char *q;
6740 switch (level) {
6741 case 1:
6742 current = info[i].info1.name;
6743 break;
6746 if (strequal(current, name)) {
6747 *found = true;
6748 break;
6751 q = strrchr(current, '\\');
6752 if (q) {
6753 if (!e.in.server) {
6754 torture_warning(tctx,
6755 "server returns printername %s incl. servername although we did not set servername", current);
6757 q++;
6758 if (strequal(q, name)) {
6759 *found = true;
6760 break;
6765 return true;
6768 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6769 struct dcerpc_pipe *p,
6770 const char *printername,
6771 bool ex)
6773 WERROR result;
6774 struct spoolss_AddPrinter r;
6775 struct spoolss_AddPrinterEx rex;
6776 struct spoolss_SetPrinterInfoCtr info_ctr;
6777 struct spoolss_SetPrinterInfo1 info1;
6778 struct spoolss_DevmodeContainer devmode_ctr;
6779 struct sec_desc_buf secdesc_ctr;
6780 struct spoolss_UserLevelCtr userlevel_ctr;
6781 struct policy_handle handle;
6782 bool found = false;
6783 struct dcerpc_binding_handle *b = p->binding_handle;
6785 ZERO_STRUCT(devmode_ctr);
6786 ZERO_STRUCT(secdesc_ctr);
6787 ZERO_STRUCT(userlevel_ctr);
6788 ZERO_STRUCT(info1);
6790 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6791 ex ? "Ex":"", printername);
6793 /* try to add printer to wellknown printer list (level 1) */
6795 userlevel_ctr.level = 1;
6797 info_ctr.info.info1 = &info1;
6798 info_ctr.level = 1;
6800 rex.in.server = NULL;
6801 rex.in.info_ctr = &info_ctr;
6802 rex.in.devmode_ctr = &devmode_ctr;
6803 rex.in.secdesc_ctr = &secdesc_ctr;
6804 rex.in.userlevel_ctr = &userlevel_ctr;
6805 rex.out.handle = &handle;
6807 r.in.server = NULL;
6808 r.in.info_ctr = &info_ctr;
6809 r.in.devmode_ctr = &devmode_ctr;
6810 r.in.secdesc_ctr = &secdesc_ctr;
6811 r.out.handle = &handle;
6813 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6814 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6815 "failed to add printer");
6816 result = ex ? rex.out.result : r.out.result;
6817 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6818 "unexpected result code");
6820 info1.name = printername;
6821 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6823 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6824 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6825 "failed to add printer");
6826 result = ex ? rex.out.result : r.out.result;
6827 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6828 "unexpected result code");
6830 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6831 better do a real check to see the printer is really there */
6833 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6834 PRINTER_ENUM_NETWORK, 1,
6835 printername,
6836 &found),
6837 "failed to enum printers");
6839 torture_assert(tctx, found, "failed to find newly added printer");
6841 info1.flags = 0;
6843 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6844 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6845 "failed to add printer");
6846 result = ex ? rex.out.result : r.out.result;
6847 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6848 "unexpected result code");
6850 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6851 better do a real check to see the printer has really been removed
6852 from the well known printer list */
6854 found = false;
6856 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6857 PRINTER_ENUM_NETWORK, 1,
6858 printername,
6859 &found),
6860 "failed to enum printers");
6861 #if 0
6862 torture_assert(tctx, !found, "printer still in well known printer list");
6863 #endif
6864 return true;
6867 static bool test_AddPrinter_normal(struct torture_context *tctx,
6868 struct dcerpc_pipe *p,
6869 struct policy_handle *handle_p,
6870 const char *printername,
6871 const char *drivername,
6872 const char *portname,
6873 struct spoolss_DeviceMode *devmode,
6874 bool ex)
6876 WERROR result;
6877 struct spoolss_AddPrinter r;
6878 struct spoolss_AddPrinterEx rex;
6879 struct spoolss_SetPrinterInfoCtr info_ctr;
6880 struct spoolss_SetPrinterInfo2 info2;
6881 struct spoolss_DevmodeContainer devmode_ctr;
6882 struct sec_desc_buf secdesc_ctr;
6883 struct spoolss_UserLevelCtr userlevel_ctr;
6884 struct policy_handle handle;
6885 bool found = false;
6886 bool existing_printer_deleted = false;
6887 struct dcerpc_binding_handle *b = p->binding_handle;
6889 ZERO_STRUCT(devmode_ctr);
6890 ZERO_STRUCT(secdesc_ctr);
6891 ZERO_STRUCT(userlevel_ctr);
6893 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6894 ex ? "Ex":"", printername);
6896 devmode_ctr.devmode = devmode;
6898 userlevel_ctr.level = 1;
6900 rex.in.server = NULL;
6901 rex.in.info_ctr = &info_ctr;
6902 rex.in.devmode_ctr = &devmode_ctr;
6903 rex.in.secdesc_ctr = &secdesc_ctr;
6904 rex.in.userlevel_ctr = &userlevel_ctr;
6905 rex.out.handle = &handle;
6907 r.in.server = NULL;
6908 r.in.info_ctr = &info_ctr;
6909 r.in.devmode_ctr = &devmode_ctr;
6910 r.in.secdesc_ctr = &secdesc_ctr;
6911 r.out.handle = &handle;
6913 again:
6915 /* try to add printer to printer list (level 2) */
6917 ZERO_STRUCT(info2);
6919 info_ctr.info.info2 = &info2;
6920 info_ctr.level = 2;
6922 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6923 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6924 "failed to add printer");
6925 result = ex ? rex.out.result : r.out.result;
6926 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6927 "unexpected result code");
6929 info2.printername = printername;
6931 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6932 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6933 "failed to add printer");
6934 result = ex ? rex.out.result : r.out.result;
6936 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6937 struct policy_handle printer_handle;
6939 if (existing_printer_deleted) {
6940 torture_fail(tctx, "already deleted printer still existing?");
6943 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6944 "failed to open printer handle");
6946 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6947 "failed to delete printer");
6949 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6950 "failed to close server handle");
6952 existing_printer_deleted = true;
6954 goto again;
6957 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6958 "unexpected result code");
6960 info2.portname = portname;
6962 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6963 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6964 "failed to add printer");
6965 result = ex ? rex.out.result : r.out.result;
6966 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6967 "unexpected result code");
6969 info2.drivername = drivername;
6971 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6972 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6973 "failed to add printer");
6974 result = ex ? rex.out.result : r.out.result;
6976 /* w2k8r2 allows to add printer w/o defining printprocessor */
6978 if (!W_ERROR_IS_OK(result)) {
6979 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6980 "unexpected result code");
6982 info2.printprocessor = "winprint";
6984 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6985 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6986 "failed to add printer");
6987 result = ex ? rex.out.result : r.out.result;
6988 torture_assert_werr_ok(tctx, result,
6989 "failed to add printer");
6992 *handle_p = handle;
6994 /* we are paranoid, really check if the printer is there now */
6996 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6997 PRINTER_ENUM_LOCAL, 1,
6998 printername,
6999 &found),
7000 "failed to enum printers");
7001 torture_assert(tctx, found, "failed to find newly added printer");
7003 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7004 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7005 "failed to add printer");
7006 result = ex ? rex.out.result : r.out.result;
7007 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7008 "unexpected result code");
7010 return true;
7013 static bool test_printer_info(struct torture_context *tctx,
7014 void *private_data)
7016 struct torture_printer_context *t =
7017 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7018 struct dcerpc_pipe *p = t->spoolss_pipe;
7019 struct dcerpc_binding_handle *b = p->binding_handle;
7021 bool ret = true;
7023 if (torture_setting_bool(tctx, "samba3", false)) {
7024 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7027 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7028 ret = false;
7031 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7032 ret = false;
7035 return ret;
7038 static bool test_EnumPrinterKey(struct torture_context *tctx,
7039 struct dcerpc_binding_handle *b,
7040 struct policy_handle *handle,
7041 const char *key_name,
7042 const char ***array)
7044 struct spoolss_EnumPrinterKey r;
7045 uint32_t needed = 0;
7046 union spoolss_KeyNames key_buffer;
7047 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7048 uint32_t _ndr_size;
7049 int i;
7051 r.in.handle = handle;
7052 r.in.key_name = key_name;
7053 r.out.key_buffer = &key_buffer;
7054 r.out.needed = &needed;
7055 r.out._ndr_size = &_ndr_size;
7057 for (i=0; i < ARRAY_SIZE(offered); i++) {
7059 if (offered[i] < 0 && needed) {
7060 if (needed <= 4) {
7061 continue;
7063 r.in.offered = needed + offered[i];
7064 } else {
7065 r.in.offered = offered[i];
7068 ZERO_STRUCT(key_buffer);
7070 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7072 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7073 "failed to call EnumPrinterKey");
7074 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7076 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7077 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7078 _ndr_size, r.in.offered/2));
7080 r.in.offered = needed;
7081 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7082 "failed to call EnumPrinterKey");
7085 if (offered[i] > 0) {
7086 torture_assert_werr_ok(tctx, r.out.result,
7087 "failed to call EnumPrinterKey");
7090 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7091 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7092 _ndr_size, r.in.offered/2));
7094 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7095 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7097 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7098 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7100 if (key_buffer.string_array) {
7101 uint32_t calc_needed = 0;
7102 int s;
7103 for (s=0; key_buffer.string_array[s]; s++) {
7104 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7106 if (!key_buffer.string_array[0]) {
7107 calc_needed += 2;
7109 calc_needed += 2;
7111 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7112 "EnumPrinterKey unexpected size");
7116 if (array) {
7117 *array = key_buffer.string_array;
7120 return true;
7123 bool test_printer_all_keys(struct torture_context *tctx,
7124 struct dcerpc_binding_handle *b,
7125 struct policy_handle *handle)
7127 const char **key_array = NULL;
7128 int i;
7130 torture_comment(tctx, "Testing Printer Keys\n");
7132 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7133 "failed to call test_EnumPrinterKey");
7135 for (i=0; key_array && key_array[i]; i++) {
7136 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7137 "failed to call test_EnumPrinterKey");
7139 for (i=0; key_array && key_array[i]; i++) {
7140 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7141 "failed to call test_EnumPrinterDataEx");
7144 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7146 return true;
7149 static bool test_openprinter_wrap(struct torture_context *tctx,
7150 void *private_data)
7152 struct torture_printer_context *t =
7153 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7154 struct dcerpc_pipe *p = t->spoolss_pipe;
7155 struct dcerpc_binding_handle *b = p->binding_handle;
7156 const char *printername = t->info2.printername;
7158 return test_openprinter(tctx, b, printername);
7161 static bool test_csetprinter(struct torture_context *tctx,
7162 void *private_data)
7164 struct torture_printer_context *t =
7165 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7166 struct dcerpc_pipe *p = t->spoolss_pipe;
7168 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7169 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7170 const char *portname = t->info2.portname;
7172 union spoolss_PrinterInfo info;
7173 struct policy_handle new_handle, new_handle2;
7174 struct dcerpc_binding_handle *b = p->binding_handle;
7176 torture_comment(tctx, "Testing c_setprinter\n");
7178 torture_assert(tctx,
7179 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7180 "failed to get level 0 printer info");
7181 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7182 info.info0.c_setprinter);
7184 /* check if c_setprinter on 1st handle increases after a printer has
7185 * been added */
7187 torture_assert(tctx,
7188 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7189 "failed to add new printer");
7190 torture_assert(tctx,
7191 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7192 "failed to get level 0 printer info");
7193 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7194 info.info0.c_setprinter);
7196 /* check if c_setprinter on new handle increases after a printer has
7197 * been added */
7199 torture_assert(tctx,
7200 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7201 "failed to get level 0 printer info");
7202 torture_comment(tctx, "csetprinter on created handle: %d\n",
7203 info.info0.c_setprinter);
7205 /* open the new printer and check if c_setprinter increases */
7207 torture_assert(tctx,
7208 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7209 "failed to open created printer");
7210 torture_assert(tctx,
7211 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7212 "failed to get level 0 printer info");
7213 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7214 info.info0.c_setprinter);
7216 /* cleanup */
7218 torture_assert(tctx,
7219 test_ClosePrinter(tctx, b, &new_handle2),
7220 "failed to close printer");
7221 torture_assert(tctx,
7222 test_DeletePrinter(tctx, b, &new_handle),
7223 "failed to delete new printer");
7225 return true;
7228 static bool compose_local_driver_directory(struct torture_context *tctx,
7229 const char *environment,
7230 const char *local_dir,
7231 const char **path)
7233 char *p;
7235 p = strrchr(local_dir, '/');
7236 if (!p) {
7237 return NULL;
7239 p++;
7241 if (strequal(environment, "Windows x64")) {
7242 if (!strequal(p, "x64")) {
7243 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7245 } else if (strequal(environment, "Windows NT x86")) {
7246 if (!strequal(p, "i386")) {
7247 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7249 } else {
7250 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7253 return true;
7256 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7257 const char *devicename)
7259 struct spoolss_DeviceMode *r;
7261 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7262 if (r == NULL) {
7263 return NULL;
7266 r->devicename = talloc_strdup(r, devicename);
7267 r->specversion = DMSPEC_NT4_AND_ABOVE;
7268 r->driverversion = 0x0600;
7269 r->size = 0x00dc;
7270 r->__driverextra_length = 0;
7271 r->fields = DEVMODE_FORMNAME |
7272 DEVMODE_TTOPTION |
7273 DEVMODE_PRINTQUALITY |
7274 DEVMODE_DEFAULTSOURCE |
7275 DEVMODE_COPIES |
7276 DEVMODE_SCALE |
7277 DEVMODE_PAPERSIZE |
7278 DEVMODE_ORIENTATION;
7279 r->orientation = DMORIENT_PORTRAIT;
7280 r->papersize = DMPAPER_LETTER;
7281 r->paperlength = 0;
7282 r->paperwidth = 0;
7283 r->scale = 100;
7284 r->copies = 55;
7285 r->defaultsource = DMBIN_FORMSOURCE;
7286 r->printquality = DMRES_HIGH;
7287 r->color = DMRES_MONOCHROME;
7288 r->duplex = DMDUP_SIMPLEX;
7289 r->yresolution = 0;
7290 r->ttoption = DMTT_SUBDEV;
7291 r->collate = DMCOLLATE_FALSE;
7292 r->formname = talloc_strdup(r, "Letter");
7294 return r;
7297 static bool test_architecture_buffer(struct torture_context *tctx,
7298 void *private_data)
7300 struct test_spoolss_context *ctx =
7301 talloc_get_type_abort(private_data, struct test_spoolss_context);
7303 struct spoolss_OpenPrinterEx r;
7304 struct spoolss_UserLevel1 u1;
7305 struct policy_handle handle;
7306 uint32_t architectures[] = {
7307 PROCESSOR_ARCHITECTURE_INTEL,
7308 PROCESSOR_ARCHITECTURE_IA64,
7309 PROCESSOR_ARCHITECTURE_AMD64
7311 uint32_t needed[3];
7312 int i;
7313 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7314 struct dcerpc_binding_handle *b = p->binding_handle;
7316 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7318 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7320 u1.size = 0;
7321 u1.client = NULL;
7322 u1.user = NULL;
7323 u1.build = 0;
7324 u1.major = 3;
7325 u1.minor = 0;
7326 u1.processor = architectures[i];
7328 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7329 r.in.datatype = NULL;
7330 r.in.devmode_ctr.devmode= NULL;
7331 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7332 r.in.level = 1;
7333 r.in.userlevel.level1 = &u1;
7334 r.out.handle = &handle;
7336 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7337 torture_assert_werr_ok(tctx, r.out.result, "");
7340 struct spoolss_EnumPrinters e;
7341 uint32_t count;
7342 union spoolss_PrinterInfo *info;
7344 e.in.flags = PRINTER_ENUM_LOCAL;
7345 e.in.server = NULL;
7346 e.in.level = 2;
7347 e.in.buffer = NULL;
7348 e.in.offered = 0;
7349 e.out.count = &count;
7350 e.out.info = &info;
7351 e.out.needed = &needed[i];
7353 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7354 #if 0
7355 torture_comment(tctx, "needed was %d\n", needed[i]);
7356 #endif
7359 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7362 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7363 if (needed[i-1] != needed[i]) {
7364 torture_fail(tctx,
7365 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7366 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7370 return true;
7373 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7374 void *private_data)
7376 struct test_spoolss_context *ctx =
7377 talloc_get_type_abort(private_data, struct test_spoolss_context);
7378 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7379 struct dcerpc_binding_handle *b = p->binding_handle;
7381 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7384 static bool test_PrintServer_Forms(struct torture_context *tctx,
7385 void *private_data)
7387 struct test_spoolss_context *ctx =
7388 talloc_get_type_abort(private_data, struct test_spoolss_context);
7389 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7390 struct dcerpc_binding_handle *b = p->binding_handle;
7392 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7395 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7396 void *private_data)
7398 struct test_spoolss_context *ctx =
7399 talloc_get_type_abort(private_data, struct test_spoolss_context);
7400 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7401 struct dcerpc_binding_handle *b = p->binding_handle;
7403 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7406 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7408 NTSTATUS status;
7410 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7412 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7414 torture_assert(tctx,
7415 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7416 "failed to open printserver");
7417 torture_assert(tctx,
7418 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7419 "failed to get environment");
7421 return true;
7424 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7426 struct test_spoolss_context *t;
7428 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7430 return torture_rpc_spoolss_setup_common(tctx, t);
7433 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7435 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7437 return true;
7440 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7442 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7443 bool ret;
7445 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7446 talloc_free(t);
7448 return ret;
7451 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7453 struct dcerpc_pipe *p;
7454 struct dcerpc_binding_handle *b;
7455 const char *server_name_slash;
7456 const char *driver_name;
7457 const char *printer_name;
7458 const char *port_name;
7460 torture_assert_ntstatus_ok(tctx,
7461 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7462 "Error connecting to server");
7464 p = t->spoolss_pipe;
7465 b = p->binding_handle;
7466 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7468 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7469 t->driver.info8.driver_name = TORTURE_DRIVER;
7470 t->driver.info8.driver_path = "pscript5.dll";
7471 t->driver.info8.data_file = "cups6.ppd";
7472 t->driver.info8.config_file = "ps5ui.dll";
7473 t->driver.info8.help_file = "pscript.hlp";
7474 t->driver.info8.default_datatype = "RAW";
7475 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7476 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7477 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7478 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7479 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7480 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7481 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7482 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7483 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7484 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7486 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7488 t->info2.drivername = "Microsoft XPS Document Writer";
7489 t->info2.portname = "LPT1:";
7491 printer_name = t->info2.printername;
7492 port_name = t->info2.portname;
7494 torture_assert(tctx,
7495 fillup_printserver_info(tctx, p, &t->driver),
7496 "failed to fillup printserver info");
7498 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7500 torture_assert(tctx,
7501 compose_local_driver_directory(tctx, t->driver.remote.environment,
7502 t->driver.local.driver_directory,
7503 &t->driver.local.driver_directory),
7504 "failed to compose local driver directory");
7506 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7507 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7508 t->info2.drivername, t->driver.remote.environment);
7509 t->have_driver = true;
7510 goto try_add;
7513 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7514 t->info2.drivername, t->driver.remote.environment);
7515 torture_comment(tctx, "trying to upload own driver\n");
7517 if (!directory_exist(t->driver.local.driver_directory)) {
7518 torture_warning(tctx, "no local driver is available!");
7519 t->have_driver = false;
7520 goto try_add;
7523 torture_assert(tctx,
7524 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7525 "failed to upload printer driver");
7527 torture_assert(tctx,
7528 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7529 "failed to add driver");
7531 t->added_driver = true;
7532 t->have_driver = true;
7534 try_add:
7535 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7537 if (t->wellknown) {
7538 torture_assert(tctx,
7539 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7540 "failed to add wellknown printer");
7541 } else {
7542 torture_assert(tctx,
7543 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7544 "failed to add printer");
7547 return true;
7550 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7552 struct torture_printer_context *t;
7554 *data = t = talloc_zero(tctx, struct torture_printer_context);
7556 t->ex = false;
7557 t->wellknown = false;
7558 t->info2.printername = TORTURE_PRINTER;
7559 t->devmode = NULL;
7561 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7564 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7566 struct torture_printer_context *t;
7568 *data = t = talloc_zero(tctx, struct torture_printer_context);
7570 t->ex = true;
7571 t->wellknown = false;
7572 t->info2.printername = TORTURE_PRINTER_EX;
7573 t->devmode = NULL;
7575 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7578 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7580 struct torture_printer_context *t;
7582 *data = t = talloc_zero(tctx, struct torture_printer_context);
7584 t->ex = false;
7585 t->wellknown = true;
7586 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7587 t->devmode = NULL;
7589 /* FIXME */
7590 if (t->wellknown) {
7591 torture_skip(tctx, "skipping AddPrinter level 1");
7594 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7597 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7599 struct torture_printer_context *t;
7601 *data = t = talloc_zero(tctx, struct torture_printer_context);
7603 t->ex = true;
7604 t->wellknown = true;
7605 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7606 t->devmode = NULL;
7608 /* FIXME */
7609 if (t->wellknown) {
7610 torture_skip(tctx, "skipping AddPrinterEx level 1");
7613 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7616 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7618 struct torture_printer_context *t;
7620 *data = t = talloc_zero(tctx, struct torture_printer_context);
7622 t->ex = true;
7623 t->wellknown = false;
7624 t->info2.printername = TORTURE_PRINTER_EX;
7625 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7627 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7630 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7632 bool found = false;
7633 struct dcerpc_pipe *p = t->spoolss_pipe;
7634 struct dcerpc_binding_handle *b;
7635 const char *printer_name = t->info2.printername;
7637 if (t->added_driver) {
7638 torture_assert(tctx,
7639 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7640 "failed to remove printer driver");
7643 if (p) {
7644 b = p->binding_handle;
7647 if (!t->wellknown) {
7648 torture_assert(tctx,
7649 test_DeletePrinter(tctx, b, &t->handle),
7650 "failed to delete printer");
7652 torture_assert(tctx,
7653 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7654 printer_name, &found),
7655 "failed to enumerate printers");
7657 torture_assert(tctx, !found, "deleted printer still there");
7660 return true;
7663 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7665 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7666 bool ret;
7668 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7669 talloc_free(t);
7671 return ret;
7674 static bool test_print_test(struct torture_context *tctx,
7675 void *private_data)
7677 struct torture_printer_context *t =
7678 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7679 struct dcerpc_pipe *p = t->spoolss_pipe;
7680 struct dcerpc_binding_handle *b = p->binding_handle;
7682 torture_assert(tctx,
7683 test_PausePrinter(tctx, b, &t->handle),
7684 "failed to pause printer");
7686 torture_assert(tctx,
7687 test_DoPrintTest(tctx, b, &t->handle),
7688 "failed to do print test");
7690 torture_assert(tctx,
7691 test_ResumePrinter(tctx, b, &t->handle),
7692 "failed to resume printer");
7694 return true;
7697 static bool test_print_test_extended(struct torture_context *tctx,
7698 void *private_data)
7700 struct torture_printer_context *t =
7701 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7702 struct dcerpc_pipe *p = t->spoolss_pipe;
7703 struct dcerpc_binding_handle *b = p->binding_handle;
7704 bool ret = true;
7706 torture_assert(tctx,
7707 test_PausePrinter(tctx, b, &t->handle),
7708 "failed to pause printer");
7710 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7711 if (ret == false) {
7712 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7713 if (torture_setting_bool(tctx, "samba3", false)) {
7714 torture_comment(tctx, "non-critical for samba3\n");
7715 ret = true;
7716 tctx->last_result = TORTURE_SKIP;
7720 torture_assert(tctx,
7721 test_ResumePrinter(tctx, b, &t->handle),
7722 "failed to resume printer");
7724 return ret;
7727 static bool test_printer_sd(struct torture_context *tctx,
7728 void *private_data)
7730 struct torture_printer_context *t =
7731 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7732 struct dcerpc_pipe *p = t->spoolss_pipe;
7733 struct dcerpc_binding_handle *b = p->binding_handle;
7735 torture_assert(tctx,
7736 test_PrinterInfo_SD(tctx, b, &t->handle),
7737 "failed to test security descriptors");
7739 return true;
7742 static bool test_printer_dm(struct torture_context *tctx,
7743 void *private_data)
7745 struct torture_printer_context *t =
7746 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7747 struct dcerpc_pipe *p = t->spoolss_pipe;
7749 torture_assert(tctx,
7750 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7751 "failed to test devicemodes");
7753 return true;
7756 static bool test_printer_info_winreg(struct torture_context *tctx,
7757 void *private_data)
7759 struct torture_printer_context *t =
7760 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7761 struct dcerpc_pipe *p = t->spoolss_pipe;
7763 torture_assert(tctx,
7764 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7765 "failed to test printer info winreg");
7767 return true;
7770 static bool test_printer_change_id(struct torture_context *tctx,
7771 void *private_data)
7773 struct torture_printer_context *t =
7774 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7775 struct dcerpc_pipe *p = t->spoolss_pipe;
7777 torture_assert(tctx,
7778 test_ChangeID(tctx, p, &t->handle),
7779 "failed to test change id");
7781 return true;
7784 static bool test_printer_keys(struct torture_context *tctx,
7785 void *private_data)
7787 struct torture_printer_context *t =
7788 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7789 struct dcerpc_pipe *p = t->spoolss_pipe;
7790 struct dcerpc_binding_handle *b = p->binding_handle;
7792 torture_assert(tctx,
7793 test_printer_all_keys(tctx, b, &t->handle),
7794 "failed to test printer keys");
7796 return true;
7799 static bool test_printer_data_consistency(struct torture_context *tctx,
7800 void *private_data)
7802 struct torture_printer_context *t =
7803 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7804 struct dcerpc_pipe *p = t->spoolss_pipe;
7806 torture_assert(tctx,
7807 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7808 "failed to test printer data consistency");
7810 return true;
7813 static bool test_printer_data_keys(struct torture_context *tctx,
7814 void *private_data)
7816 struct torture_printer_context *t =
7817 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7818 struct dcerpc_pipe *p = t->spoolss_pipe;
7820 torture_assert(tctx,
7821 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7822 "failed to test printer data keys");
7824 return true;
7827 static bool test_printer_data_values(struct torture_context *tctx,
7828 void *private_data)
7830 struct torture_printer_context *t =
7831 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7832 struct dcerpc_pipe *p = t->spoolss_pipe;
7834 torture_assert(tctx,
7835 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7836 "failed to test printer data values");
7838 return true;
7841 static bool test_printer_data_set(struct torture_context *tctx,
7842 void *private_data)
7844 struct torture_printer_context *t =
7845 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7846 struct dcerpc_pipe *p = t->spoolss_pipe;
7848 torture_assert(tctx,
7849 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7850 "failed to test printer data set");
7852 return true;
7855 static bool test_printer_data_winreg(struct torture_context *tctx,
7856 void *private_data)
7858 struct torture_printer_context *t =
7859 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7860 struct dcerpc_pipe *p = t->spoolss_pipe;
7862 torture_assert(tctx,
7863 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7864 "failed to test printer data winreg");
7866 return true;
7869 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7870 void *private_data)
7872 struct torture_printer_context *t =
7873 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7874 struct dcerpc_pipe *p = t->spoolss_pipe;
7876 torture_assert(tctx,
7877 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7878 "failed to test printer data winreg dsspooler");
7880 return true;
7883 static bool test_driver_info_winreg(struct torture_context *tctx,
7884 void *private_data)
7886 struct torture_printer_context *t =
7887 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7888 struct dcerpc_pipe *p = t->spoolss_pipe;
7889 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7891 if (!t->have_driver) {
7892 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7895 torture_assert(tctx,
7896 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7897 "failed to test driver info winreg");
7899 return true;
7902 void torture_tcase_printer(struct torture_tcase *tcase)
7904 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7905 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7906 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7907 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7908 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7909 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7910 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7911 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7912 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7913 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7914 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7915 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7916 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7917 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7918 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7919 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7920 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7921 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7924 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7926 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7927 struct torture_tcase *tcase;
7929 tcase = torture_suite_add_tcase(suite, "addprinter");
7931 torture_tcase_set_fixture(tcase,
7932 torture_rpc_spoolss_printer_setup,
7933 torture_rpc_spoolss_printer_teardown);
7935 torture_tcase_printer(tcase);
7937 tcase = torture_suite_add_tcase(suite, "addprinterex");
7939 torture_tcase_set_fixture(tcase,
7940 torture_rpc_spoolss_printerex_setup,
7941 torture_rpc_spoolss_printer_teardown);
7943 torture_tcase_printer(tcase);
7945 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7947 torture_tcase_set_fixture(tcase,
7948 torture_rpc_spoolss_printerwkn_setup,
7949 torture_rpc_spoolss_printer_teardown);
7951 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7953 torture_tcase_set_fixture(tcase,
7954 torture_rpc_spoolss_printerexwkn_setup,
7955 torture_rpc_spoolss_printer_teardown);
7957 #if 0
7958 /* test is not correct */
7959 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7961 torture_tcase_set_fixture(tcase,
7962 torture_rpc_spoolss_printerdm_setup,
7963 torture_rpc_spoolss_printer_teardown);
7965 torture_tcase_printer(tcase);
7966 #endif
7967 return suite;
7970 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7972 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7973 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7975 torture_tcase_set_fixture(tcase,
7976 torture_rpc_spoolss_setup,
7977 torture_rpc_spoolss_teardown);
7979 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7980 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7981 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7982 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7983 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7984 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7985 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7986 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7987 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7988 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7989 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7990 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7991 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7992 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7993 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7994 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7995 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7996 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7997 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7998 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8000 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8002 return suite;
8005 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8006 struct dcerpc_binding_handle *b,
8007 const char *server,
8008 const char *environment,
8009 const char **dir_p)
8011 struct spoolss_GetPrinterDriverDirectory r;
8012 uint32_t needed;
8014 r.in.server = server;
8015 r.in.environment = environment;
8016 r.in.level = 1;
8017 r.in.buffer = NULL;
8018 r.in.offered = 0;
8019 r.out.needed = &needed;
8021 torture_assert_ntstatus_ok(tctx,
8022 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8023 "failed to query driver directory");
8025 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8026 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8027 r.in.buffer = &blob;
8028 r.in.offered = needed;
8030 torture_assert_ntstatus_ok(tctx,
8031 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8032 "failed to query driver directory");
8035 torture_assert_werr_ok(tctx, r.out.result,
8036 "failed to query driver directory");
8038 if (dir_p) {
8039 *dir_p = r.out.info->info1.directory_name;
8042 return true;
8045 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8047 if (info_ctr == NULL) {
8048 return NULL;
8051 switch (info_ctr->level) {
8052 case 1:
8053 return info_ctr->info.info1->driver_name;
8054 case 2:
8055 return info_ctr->info.info2->driver_name;
8056 case 3:
8057 return info_ctr->info.info3->driver_name;
8058 case 4:
8059 return info_ctr->info.info4->driver_name;
8060 case 6:
8061 return info_ctr->info.info6->driver_name;
8062 case 8:
8063 return info_ctr->info.info8->driver_name;
8064 default:
8065 return NULL;
8069 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8071 if (info_ctr == NULL) {
8072 return NULL;
8075 switch (info_ctr->level) {
8076 case 2:
8077 return info_ctr->info.info2->architecture;
8078 case 3:
8079 return info_ctr->info.info3->architecture;
8080 case 4:
8081 return info_ctr->info.info4->architecture;
8082 case 6:
8083 return info_ctr->info.info6->architecture;
8084 case 8:
8085 return info_ctr->info.info8->architecture;
8086 default:
8087 return NULL;
8092 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8093 struct dcerpc_binding_handle *b,
8094 const char *servername,
8095 struct spoolss_AddDriverInfoCtr *info_ctr,
8096 WERROR expected_result)
8098 struct spoolss_AddPrinterDriver r;
8099 const char *drivername = get_driver_from_info(info_ctr);
8100 const char *environment = get_environment_from_info(info_ctr);
8102 r.in.servername = servername;
8103 r.in.info_ctr = info_ctr;
8105 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8106 drivername, info_ctr->level, environment);
8108 torture_assert_ntstatus_ok(tctx,
8109 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8110 "spoolss_AddPrinterDriver failed");
8111 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8112 "spoolss_AddPrinterDriver failed with unexpected result");
8114 return true;
8118 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8119 struct dcerpc_binding_handle *b,
8120 const char *servername,
8121 struct spoolss_AddDriverInfoCtr *info_ctr,
8122 uint32_t flags,
8123 WERROR expected_result)
8125 struct spoolss_AddPrinterDriverEx r;
8126 const char *drivername = get_driver_from_info(info_ctr);
8127 const char *environment = get_environment_from_info(info_ctr);
8129 r.in.servername = servername;
8130 r.in.info_ctr = info_ctr;
8131 r.in.flags = flags;
8133 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8134 drivername, info_ctr->level, environment);
8136 torture_assert_ntstatus_ok(tctx,
8137 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8138 "AddPrinterDriverEx failed");
8139 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8140 "AddPrinterDriverEx failed with unexpected result");
8142 return true;
8145 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8146 if (path && strlen(path)) {\
8147 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8150 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8151 struct dcerpc_binding_handle *b,
8152 const char *server_name,
8153 struct spoolss_AddDriverInfo8 *r,
8154 uint32_t flags,
8155 bool ex,
8156 const char *remote_driver_dir)
8158 struct spoolss_AddDriverInfoCtr info_ctr;
8159 struct spoolss_AddDriverInfo1 info1;
8161 ZERO_STRUCT(info1);
8163 info_ctr.level = 1;
8164 info_ctr.info.info1 = &info1;
8166 if (ex) {
8167 torture_assert(tctx,
8168 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8169 "failed to test AddPrinterDriverEx level 1");
8170 } else {
8171 torture_assert(tctx,
8172 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8173 "failed to test AddPrinterDriver level 1");
8176 info1.driver_name = r->driver_name;
8178 if (ex) {
8179 torture_assert(tctx,
8180 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8181 "failed to test AddPrinterDriverEx level 1");
8182 } else {
8183 torture_assert(tctx,
8184 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8185 "failed to test AddPrinterDriver level 1");
8188 return true;
8191 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8192 struct dcerpc_binding_handle *b,
8193 const char *server_name,
8194 struct spoolss_AddDriverInfo8 *r,
8195 uint32_t flags,
8196 bool ex,
8197 const char *remote_driver_dir)
8199 struct spoolss_AddDriverInfoCtr info_ctr;
8200 struct spoolss_AddDriverInfo2 info2;
8201 union spoolss_DriverInfo info;
8203 ZERO_STRUCT(info2);
8205 info_ctr.level = 2;
8206 info_ctr.info.info2 = &info2;
8208 if (ex) {
8209 torture_assert(tctx,
8210 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8211 "failed to test AddPrinterDriverEx level 2");
8212 } else {
8213 torture_assert(tctx,
8214 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8215 "failed to test AddPrinterDriver level 2");
8218 info2.driver_name = r->driver_name;
8220 if (ex) {
8221 torture_assert(tctx,
8222 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8223 "failed to test AddPrinterDriverEx level 2");
8224 } else {
8225 torture_assert(tctx,
8226 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8227 "failed to test AddPrinterDriver level 2");
8230 info2.version = r->version;
8232 if (ex) {
8233 torture_assert(tctx,
8234 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8235 "failed to test AddPrinterDriverEx level 2");
8236 } else {
8237 torture_assert(tctx,
8238 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8239 "failed to test AddPrinterDriver level 2");
8242 info2.architecture = r->architecture;
8244 if (ex) {
8245 torture_assert(tctx,
8246 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8247 "failed to test AddPrinterDriverEx level 2");
8248 } else {
8249 torture_assert(tctx,
8250 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8251 "failed to test AddPrinterDriver level 2");
8254 info2.driver_path = r->driver_path;
8256 if (ex) {
8257 torture_assert(tctx,
8258 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8259 "failed to test AddPrinterDriverEx level 2");
8260 } else {
8261 torture_assert(tctx,
8262 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8263 "failed to test AddPrinterDriver level 2");
8266 info2.data_file = r->data_file;
8268 if (ex) {
8269 torture_assert(tctx,
8270 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8271 "failed to test AddPrinterDriverEx level 2");
8272 } else {
8273 torture_assert(tctx,
8274 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8275 "failed to test AddPrinterDriver level 2");
8278 info2.config_file = r->config_file;
8280 if (ex) {
8281 torture_assert(tctx,
8282 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8283 "failed to test AddPrinterDriverEx");
8286 if (ex) {
8287 torture_assert(tctx,
8288 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8289 "failed to test AddPrinterDriverEx level 2");
8290 } else {
8291 torture_assert(tctx,
8292 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8293 "failed to test AddPrinterDriver level 2");
8296 torture_assert(tctx,
8297 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8298 "failed to find added printer driver");
8300 if (remote_driver_dir) {
8301 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8302 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8303 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8306 return true;
8309 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8310 struct dcerpc_binding_handle *b,
8311 const char *server_name,
8312 struct spoolss_AddDriverInfo8 *r,
8313 uint32_t flags,
8314 bool ex,
8315 const char *remote_driver_dir)
8317 struct spoolss_AddDriverInfoCtr info_ctr;
8318 struct spoolss_AddDriverInfo3 info3;
8319 union spoolss_DriverInfo info;
8321 info3.driver_name = r->driver_name;
8322 info3.version = r->version;
8323 info3.architecture = r->architecture;
8324 info3.driver_path = r->driver_path;
8325 info3.data_file = r->data_file;
8326 info3.config_file = r->config_file;
8327 info3.help_file = r->help_file;
8328 info3.monitor_name = r->monitor_name;
8329 info3.default_datatype = r->default_datatype;
8330 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8331 info3.dependent_files = r->dependent_files;
8333 info_ctr.level = 3;
8334 info_ctr.info.info3 = &info3;
8336 if (ex) {
8337 torture_assert(tctx,
8338 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8339 "failed to test AddPrinterDriverEx level 3");
8340 } else {
8341 torture_assert(tctx,
8342 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8343 "failed to test AddPrinterDriver level 3");
8346 torture_assert(tctx,
8347 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8348 "failed to find added printer driver");
8350 if (remote_driver_dir) {
8351 int i;
8352 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8353 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8354 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8355 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8356 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8357 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8361 return true;
8364 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8365 struct dcerpc_binding_handle *b,
8366 const char *server_name,
8367 struct spoolss_AddDriverInfo8 *r,
8368 uint32_t flags,
8369 bool ex,
8370 const char *remote_driver_dir)
8372 struct spoolss_AddDriverInfoCtr info_ctr;
8373 struct spoolss_AddDriverInfo4 info4;
8374 union spoolss_DriverInfo info;
8376 info4.version = r->version;
8377 info4.driver_name = r->driver_name;
8378 info4.architecture = r->architecture;
8379 info4.driver_path = r->driver_path;
8380 info4.data_file = r->data_file;
8381 info4.config_file = r->config_file;
8382 info4.help_file = r->help_file;
8383 info4.monitor_name = r->monitor_name;
8384 info4.default_datatype = r->default_datatype;
8385 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8386 info4.dependent_files = r->dependent_files;
8387 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8388 info4.previous_names = r->previous_names;
8390 info_ctr.level = 4;
8391 info_ctr.info.info4 = &info4;
8393 if (ex) {
8394 torture_assert(tctx,
8395 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8396 "failed to test AddPrinterDriverEx level 4");
8397 } else {
8398 torture_assert(tctx,
8399 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8400 "failed to test AddPrinterDriver level 4");
8403 torture_assert(tctx,
8404 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8405 "failed to find added printer driver");
8407 if (remote_driver_dir) {
8408 int i;
8409 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8410 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8411 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8412 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8413 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8414 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8418 return true;
8421 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8422 struct dcerpc_binding_handle *b,
8423 const char *server_name,
8424 struct spoolss_AddDriverInfo8 *r,
8425 uint32_t flags,
8426 bool ex,
8427 const char *remote_driver_dir)
8429 struct spoolss_AddDriverInfoCtr info_ctr;
8430 struct spoolss_AddDriverInfo6 info6;
8431 union spoolss_DriverInfo info;
8433 info6.version = r->version;
8434 info6.driver_name = r->driver_name;
8435 info6.architecture = r->architecture;
8436 info6.driver_path = r->driver_path;
8437 info6.data_file = r->data_file;
8438 info6.config_file = r->config_file;
8439 info6.help_file = r->help_file;
8440 info6.monitor_name = r->monitor_name;
8441 info6.default_datatype = r->default_datatype;
8442 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8443 info6.dependent_files = r->dependent_files;
8444 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8445 info6.previous_names = r->previous_names;
8446 info6.driver_date = r->driver_date;
8447 info6.driver_version = r->driver_version;
8448 info6.manufacturer_name = r->manufacturer_name;
8449 info6.manufacturer_url = r->manufacturer_url;
8450 info6.hardware_id = r->hardware_id;
8451 info6.provider = r->provider;
8453 info_ctr.level = 6;
8454 info_ctr.info.info6 = &info6;
8456 if (ex) {
8457 torture_assert(tctx,
8458 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8459 "failed to test AddPrinterDriverEx level 6");
8460 } else {
8461 torture_assert(tctx,
8462 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8463 "failed to test AddPrinterDriver level 6");
8466 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8468 if (!ex) {
8469 return true;
8472 torture_assert(tctx,
8473 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8474 "failed to find added printer driver");
8476 if (remote_driver_dir) {
8477 int i;
8478 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8479 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8480 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8481 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8482 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8483 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8487 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8488 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8490 return true;
8493 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8494 struct dcerpc_binding_handle *b,
8495 const char *server_name,
8496 struct spoolss_AddDriverInfo8 *r,
8497 uint32_t flags,
8498 bool ex,
8499 const char *remote_driver_dir)
8501 struct spoolss_AddDriverInfoCtr info_ctr;
8502 union spoolss_DriverInfo info;
8504 info_ctr.level = 8;
8505 info_ctr.info.info8 = r;
8507 if (ex) {
8508 torture_assert(tctx,
8509 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8510 "failed to test AddPrinterDriverEx level 8");
8511 } else {
8512 torture_assert(tctx,
8513 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8514 "failed to test AddPrinterDriver level 8");
8517 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8519 if (!ex) {
8520 return true;
8523 torture_assert(tctx,
8524 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8525 "failed to find added printer driver");
8527 if (remote_driver_dir) {
8528 int i;
8529 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8530 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8531 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8532 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8533 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8534 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8538 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8539 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8541 return true;
8544 #undef ASSERT_DRIVER_PATH
8546 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8547 struct dcerpc_binding_handle *b,
8548 const char *server,
8549 const char *driver,
8550 const char *environment,
8551 WERROR expected_result)
8553 struct spoolss_DeletePrinterDriver r;
8555 r.in.server = server;
8556 r.in.architecture = environment;
8557 r.in.driver = driver;
8559 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8561 torture_assert_ntstatus_ok(tctx,
8562 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8563 "DeletePrinterDriver failed");
8564 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8565 "DeletePrinterDriver failed with unexpected result");
8567 return true;
8570 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8571 struct dcerpc_binding_handle *b,
8572 const char *server,
8573 const char *driver,
8574 const char *environment,
8575 uint32_t delete_flags,
8576 uint32_t version,
8577 WERROR expected_result)
8579 struct spoolss_DeletePrinterDriverEx r;
8581 r.in.server = server;
8582 r.in.architecture = environment;
8583 r.in.driver = driver;
8584 r.in.delete_flags = delete_flags;
8585 r.in.version = version;
8587 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8589 torture_assert_ntstatus_ok(tctx,
8590 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8591 "DeletePrinterDriverEx failed");
8592 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8593 "DeletePrinterDriverEx failed with unexpected result");
8595 return true;
8598 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8599 struct dcerpc_binding_handle *b,
8600 const char *server_name,
8601 const char *driver,
8602 const char *environment)
8604 torture_assert(tctx,
8605 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8606 "failed to delete driver");
8608 torture_assert(tctx,
8609 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8610 "failed to delete driver");
8612 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8613 torture_fail(tctx, "deleted driver still enumerated");
8616 torture_assert(tctx,
8617 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8618 "2nd delete failed");
8620 return true;
8623 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8624 struct dcerpc_binding_handle *b,
8625 const char *server_name,
8626 const char *driver,
8627 const char *environment,
8628 uint32_t delete_flags,
8629 uint32_t version)
8631 torture_assert(tctx,
8632 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8633 "failed to delete driver");
8635 torture_assert(tctx,
8636 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8637 "failed to delete driver");
8639 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8640 torture_fail(tctx, "deleted driver still enumerated");
8643 torture_assert(tctx,
8644 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8645 "2nd delete failed");
8647 return true;
8650 static bool test_PrinterDriver_args(struct torture_context *tctx,
8651 struct dcerpc_binding_handle *b,
8652 const char *server_name,
8653 uint32_t level,
8654 struct spoolss_AddDriverInfo8 *r,
8655 uint32_t add_flags,
8656 uint32_t delete_flags,
8657 uint32_t delete_version,
8658 bool ex,
8659 const char *remote_driver_dir)
8661 bool ret = true;
8663 switch (level) {
8664 case 1:
8665 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8666 break;
8667 case 2:
8668 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8669 break;
8670 case 3:
8671 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8672 break;
8673 case 4:
8674 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8675 break;
8676 case 6:
8677 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8678 break;
8679 case 8:
8680 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8681 break;
8682 default:
8683 return false;
8686 if (ret == false) {
8687 return ret;
8690 if (level == 1) {
8691 return ret;
8694 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8696 if (!ex && (level == 6 || level == 8)) {
8697 return ret;
8701 struct dcerpc_pipe *p2;
8702 struct policy_handle hive_handle;
8703 struct dcerpc_binding_handle *b2;
8705 torture_assert_ntstatus_ok(tctx,
8706 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8707 "could not open winreg pipe");
8708 b2 = p2->binding_handle;
8710 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8712 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8714 test_winreg_CloseKey(tctx, b2, &hive_handle);
8716 talloc_free(p2);
8719 if (ex) {
8720 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8721 } else {
8722 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8726 static bool fillup_printserver_info(struct torture_context *tctx,
8727 struct dcerpc_pipe *p,
8728 struct torture_driver_context *d)
8730 struct policy_handle server_handle;
8731 struct dcerpc_binding_handle *b = p->binding_handle;
8732 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8734 torture_assert(tctx,
8735 test_OpenPrinter_server(tctx, p, &server_handle),
8736 "failed to open printserver");
8737 torture_assert(tctx,
8738 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8739 "failed to get environment");
8740 torture_assert(tctx,
8741 test_ClosePrinter(tctx, b, &server_handle),
8742 "failed to close printserver");
8744 torture_assert(tctx,
8745 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8746 d->local.environment ? d->local.environment : d->remote.environment,
8747 &d->remote.driver_directory),
8748 "failed to get driver directory");
8750 return true;
8753 static const char *driver_directory_dir(const char *driver_directory)
8755 char *p;
8757 p = strrchr(driver_directory, '\\');
8758 if (p) {
8759 return p+1;
8762 return NULL;
8765 static const char *driver_directory_share(struct torture_context *tctx,
8766 const char *driver_directory)
8768 const char *p;
8769 char *tok;
8771 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8772 driver_directory += 2;
8775 p = talloc_strdup(tctx, driver_directory);
8777 torture_assert(tctx,
8778 next_token_talloc(tctx, &p, &tok, "\\"),
8779 "cannot explode uri");
8780 torture_assert(tctx,
8781 next_token_talloc(tctx, &p, &tok, "\\"),
8782 "cannot explode uri");
8784 return tok;
8787 static bool upload_printer_driver_file(struct torture_context *tctx,
8788 struct smbcli_state *cli,
8789 struct torture_driver_context *d,
8790 const char *file_name)
8792 XFILE *f;
8793 int fnum;
8794 uint8_t *buf;
8795 int maxwrite = 64512;
8796 off_t nread = 0;
8797 size_t start = 0;
8798 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8799 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8800 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8802 if (!file_name || strlen(file_name) == 0) {
8803 return true;
8806 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8808 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8809 if (fnum == -1) {
8810 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8813 f = x_fopen(local_name, O_RDONLY, 0);
8814 if (f == NULL) {
8815 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8818 buf = talloc_array(tctx, uint8_t, maxwrite);
8819 if (!buf) {
8820 return false;
8823 while (!x_feof(f)) {
8824 int n = maxwrite;
8825 int ret;
8827 if ((n = x_fread(buf, 1, n, f)) < 1) {
8828 if((n == 0) && x_feof(f))
8829 break; /* Empty local file. */
8831 torture_warning(tctx,
8832 "failed to read file: %s\n", strerror(errno));
8833 break;
8836 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8838 if (n != ret) {
8839 torture_warning(tctx,
8840 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8841 break;
8844 nread += n;
8847 x_fclose(f);
8849 torture_assert_ntstatus_ok(tctx,
8850 smbcli_close(cli->tree, fnum),
8851 "failed to close file");
8853 return true;
8856 static bool connect_printer_driver_share(struct torture_context *tctx,
8857 const char *server_name,
8858 const char *share_name,
8859 struct smbcli_state **cli)
8861 struct smbcli_options smb_options;
8862 struct smbcli_session_options smb_session_options;
8864 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8865 share_name, server_name);
8867 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8868 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8870 torture_assert_ntstatus_ok(tctx,
8871 smbcli_full_connection(tctx, cli, server_name,
8872 lpcfg_smb_ports(tctx->lp_ctx),
8873 share_name, NULL,
8874 lpcfg_socket_options(tctx->lp_ctx),
8875 cmdline_credentials,
8876 lpcfg_resolve_context(tctx->lp_ctx),
8877 tctx->ev,
8878 &smb_options,
8879 &smb_session_options,
8880 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8881 "failed to open driver share");
8883 return true;
8886 static bool upload_printer_driver(struct torture_context *tctx,
8887 const char *server_name,
8888 struct torture_driver_context *d)
8890 struct smbcli_state *cli;
8891 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8892 int i;
8894 torture_assert(tctx,
8895 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8896 "failed to connect to driver share");
8898 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8899 server_name, share_name);
8901 torture_assert(tctx,
8902 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8903 "failed to upload driver_path");
8904 torture_assert(tctx,
8905 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8906 "failed to upload data_file");
8907 torture_assert(tctx,
8908 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8909 "failed to upload config_file");
8910 torture_assert(tctx,
8911 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8912 "failed to upload help_file");
8913 if (d->info8.dependent_files) {
8914 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8915 torture_assert(tctx,
8916 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8917 "failed to upload dependent_files");
8921 talloc_free(cli);
8923 return true;
8926 static bool check_printer_driver_file(struct torture_context *tctx,
8927 struct smbcli_state *cli,
8928 struct torture_driver_context *d,
8929 const char *file_name)
8931 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
8932 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
8933 remote_arch_dir,
8934 d->info8.version,
8935 file_name);
8936 int fnum;
8938 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
8940 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
8942 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
8943 if (fnum == -1) {
8944 return false;
8947 torture_assert_ntstatus_ok(tctx,
8948 smbcli_close(cli->tree, fnum),
8949 "failed to close driver file");
8951 return true;
8954 static bool check_printer_driver_files(struct torture_context *tctx,
8955 const char *server_name,
8956 struct torture_driver_context *d,
8957 bool expect_exist)
8959 struct smbcli_state *cli;
8960 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8961 int i;
8963 torture_assert(tctx,
8964 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8965 "failed to connect to driver share");
8967 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
8968 (expect_exist ? "": "non-"),
8969 server_name, share_name);
8971 if (d->info8.driver_path && d->info8.driver_path[0]) {
8972 torture_assert(tctx,
8973 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
8974 "failed driver_path check");
8976 if (d->info8.data_file && d->info8.data_file[0]) {
8977 torture_assert(tctx,
8978 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
8979 "failed data_file check");
8981 if (d->info8.config_file && d->info8.config_file[0]) {
8982 torture_assert(tctx,
8983 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
8984 "failed config_file check");
8986 if (d->info8.help_file && d->info8.help_file[0]) {
8987 torture_assert(tctx,
8988 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
8989 "failed help_file check");
8991 if (d->info8.dependent_files) {
8992 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8993 torture_assert(tctx,
8994 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
8995 "failed dependent_files check");
8999 talloc_free(cli);
9001 return true;
9004 static bool remove_printer_driver_file(struct torture_context *tctx,
9005 struct smbcli_state *cli,
9006 struct torture_driver_context *d,
9007 const char *file_name)
9009 const char *remote_name;
9010 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9012 if (!file_name || strlen(file_name) == 0) {
9013 return true;
9016 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9018 torture_comment(tctx, "Removing %s\n", remote_name);
9020 torture_assert_ntstatus_ok(tctx,
9021 smbcli_unlink(cli->tree, remote_name),
9022 "failed to unlink");
9024 return true;
9027 static bool remove_printer_driver(struct torture_context *tctx,
9028 const char *server_name,
9029 struct torture_driver_context *d)
9031 struct smbcli_state *cli;
9032 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9033 int i;
9035 torture_assert(tctx,
9036 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9037 "failed to connect to driver share");
9039 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9040 server_name, share_name);
9042 torture_assert(tctx,
9043 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9044 "failed to remove driver_path");
9045 torture_assert(tctx,
9046 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9047 "failed to remove data_file");
9048 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9049 torture_assert(tctx,
9050 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9051 "failed to remove config_file");
9053 torture_assert(tctx,
9054 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9055 "failed to remove help_file");
9056 if (d->info8.dependent_files) {
9057 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9058 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9059 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9060 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9061 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9062 continue;
9064 torture_assert(tctx,
9065 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9066 "failed to remove dependent_files");
9070 talloc_free(cli);
9072 return true;
9076 static bool test_add_driver_arg(struct torture_context *tctx,
9077 struct dcerpc_pipe *p,
9078 struct torture_driver_context *d)
9080 bool ret = true;
9081 struct dcerpc_binding_handle *b = p->binding_handle;
9082 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9083 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9084 int i;
9085 struct spoolss_AddDriverInfo8 info8;
9086 uint32_t add_flags = APD_COPY_NEW_FILES;
9087 uint32_t delete_flags = 0;
9089 ZERO_STRUCT(info8);
9091 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9092 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9094 torture_assert(tctx,
9095 fillup_printserver_info(tctx, p, d),
9096 "failed to fillup printserver info");
9098 if (!directory_exist(d->local.driver_directory)) {
9099 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9102 torture_assert(tctx,
9103 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9104 "failed to upload printer driver");
9106 info8 = d->info8;
9107 if (d->info8.dependent_files) {
9108 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9109 if (d->info8.dependent_files->string) {
9110 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9112 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9113 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9114 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9118 info8.architecture = d->local.environment;
9120 for (i=0; i < ARRAY_SIZE(levels); i++) {
9122 if (torture_setting_bool(tctx, "samba3", false)) {
9123 switch (levels[i]) {
9124 case 2:
9125 case 4:
9126 case 8:
9127 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9128 continue;
9129 default:
9130 break;
9133 if (torture_setting_bool(tctx, "w2k3", false)) {
9134 switch (levels[i]) {
9135 case 8:
9136 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9137 continue;
9138 default:
9139 break;
9143 torture_comment(tctx,
9144 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9145 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9147 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);
9150 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9151 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9152 if (d->info8.config_file) {
9153 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9155 if (d->info8.help_file) {
9156 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9158 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9159 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9160 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9164 for (i=0; i < ARRAY_SIZE(levels); i++) {
9166 if (torture_setting_bool(tctx, "samba3", false)) {
9167 switch (levels[i]) {
9168 case 2:
9169 case 4:
9170 case 8:
9171 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9172 continue;
9173 default:
9174 break;
9177 if (torture_setting_bool(tctx, "w2k3", false)) {
9178 switch (levels[i]) {
9179 case 8:
9180 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9181 continue;
9182 default:
9183 break;
9187 torture_comment(tctx,
9188 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9189 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9191 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);
9194 torture_assert(tctx,
9195 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9196 "failed to remove printer driver");
9198 torture_comment(tctx, "\n");
9200 return ret;
9203 static bool test_add_driver_ex_64(struct torture_context *tctx,
9204 struct dcerpc_pipe *p)
9206 struct torture_driver_context *d;
9208 d = talloc_zero(tctx, struct torture_driver_context);
9210 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9211 d->info8.driver_name = TORTURE_DRIVER_EX;
9212 d->info8.architecture = NULL;
9213 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9214 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9215 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9216 d->local.environment = talloc_strdup(d, "Windows x64");
9217 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9218 d->ex = true;
9220 return test_add_driver_arg(tctx, p, d);
9223 static bool test_add_driver_ex_32(struct torture_context *tctx,
9224 struct dcerpc_pipe *p)
9226 struct torture_driver_context *d;
9228 d = talloc_zero(tctx, struct torture_driver_context);
9230 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9231 d->info8.driver_name = TORTURE_DRIVER_EX;
9232 d->info8.architecture = NULL;
9233 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9234 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9235 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9236 d->local.environment = talloc_strdup(d, "Windows NT x86");
9237 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9238 d->ex = true;
9240 return test_add_driver_arg(tctx, p, d);
9243 static bool test_add_driver_64(struct torture_context *tctx,
9244 struct dcerpc_pipe *p)
9246 struct torture_driver_context *d;
9248 d = talloc_zero(tctx, struct torture_driver_context);
9250 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9251 d->info8.driver_name = TORTURE_DRIVER;
9252 d->info8.architecture = NULL;
9253 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9254 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9255 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9256 d->local.environment = talloc_strdup(d, "Windows x64");
9257 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9258 d->ex = false;
9260 return test_add_driver_arg(tctx, p, d);
9263 static bool test_add_driver_32(struct torture_context *tctx,
9264 struct dcerpc_pipe *p)
9266 struct torture_driver_context *d;
9268 d = talloc_zero(tctx, struct torture_driver_context);
9270 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9271 d->info8.driver_name = TORTURE_DRIVER;
9272 d->info8.architecture = NULL;
9273 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9274 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9275 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9276 d->local.environment = talloc_strdup(d, "Windows NT x86");
9277 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9278 d->ex = false;
9280 return test_add_driver_arg(tctx, p, d);
9283 static bool test_add_driver_adobe(struct torture_context *tctx,
9284 struct dcerpc_pipe *p)
9286 struct torture_driver_context *d;
9288 if (!torture_setting_bool(tctx, "samba3", false)) {
9289 torture_skip(tctx, "skipping adobe test which only works against samba3");
9292 d = talloc_zero(tctx, struct torture_driver_context);
9294 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9295 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9296 d->info8.architecture = NULL;
9297 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9298 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9299 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9300 #if 0
9301 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9302 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9303 #endif
9304 d->local.environment = talloc_strdup(d, "Windows 4.0");
9305 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9306 d->ex = false;
9308 return test_add_driver_arg(tctx, p, d);
9311 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9312 struct dcerpc_pipe *p)
9314 struct torture_driver_context *d;
9315 struct spoolss_StringArray *a;
9317 if (!torture_setting_bool(tctx, "samba3", false)) {
9318 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9321 d = talloc_zero(tctx, struct torture_driver_context);
9323 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9324 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9325 d->info8.architecture = NULL;
9326 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9327 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9328 d->info8.config_file = NULL;
9329 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9330 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9331 d->info8.default_datatype = talloc_strdup(d, "RAW");
9333 a = talloc_zero(d, struct spoolss_StringArray);
9334 a->string = talloc_zero_array(a, const char *, 7);
9335 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9336 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9337 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9338 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9339 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9340 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9342 d->info8.dependent_files = a;
9343 d->local.environment = talloc_strdup(d, "Windows 4.0");
9344 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9345 d->ex = false;
9347 return test_add_driver_arg(tctx, p, d);
9350 static bool test_add_driver_timestamps(struct torture_context *tctx,
9351 struct dcerpc_pipe *p)
9353 struct torture_driver_context *d;
9354 struct timeval t = timeval_current();
9356 d = talloc_zero(tctx, struct torture_driver_context);
9358 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9359 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9360 d->info8.architecture = NULL;
9361 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9362 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9363 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9364 d->info8.driver_date = timeval_to_nttime(&t);
9365 d->local.environment = talloc_strdup(d, "Windows NT x86");
9366 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9367 d->ex = true;
9369 torture_assert(tctx,
9370 test_add_driver_arg(tctx, p, d),
9371 "");
9373 unix_to_nt_time(&d->info8.driver_date, 1);
9375 torture_assert(tctx,
9376 test_add_driver_arg(tctx, p, d),
9377 "");
9379 return true;
9382 static bool test_multiple_drivers(struct torture_context *tctx,
9383 struct dcerpc_pipe *p)
9385 struct torture_driver_context *d;
9386 struct dcerpc_binding_handle *b = p->binding_handle;
9387 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9388 int i;
9389 struct spoolss_AddDriverInfo8 info8;
9390 uint32_t add_flags = APD_COPY_NEW_FILES;
9391 uint32_t delete_flags = 0;
9393 d = talloc_zero(tctx, struct torture_driver_context);
9395 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9396 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9397 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9398 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9399 d->local.environment = talloc_strdup(d, "Windows NT x86");
9400 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9401 d->ex = true;
9403 torture_assert(tctx,
9404 fillup_printserver_info(tctx, p, d),
9405 "failed to fillup printserver info");
9407 if (!directory_exist(d->local.driver_directory)) {
9408 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9411 torture_assert(tctx,
9412 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9413 "failed to upload printer driver");
9415 info8 = d->info8;
9416 info8.architecture = d->local.environment;
9418 for (i=0; i < 3; i++) {
9419 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9421 torture_assert(tctx,
9422 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9423 "failed to add driver");
9426 torture_assert(tctx,
9427 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9428 "failed to delete driver");
9430 torture_assert(tctx,
9431 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9432 "torture_test_driver_1 no longer on the server");
9434 torture_assert(tctx,
9435 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9436 "torture_test_driver_2 no longer on the server");
9438 torture_assert(tctx,
9439 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9440 "failed to delete driver");
9442 torture_assert(tctx,
9443 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9444 "torture_test_driver_2 no longer on the server");
9446 torture_assert(tctx,
9447 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9448 "failed to delete driver");
9450 torture_assert(tctx,
9451 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9452 "failed to remove printer driver");
9454 return true;
9457 static bool test_del_driver_all_files(struct torture_context *tctx,
9458 struct dcerpc_pipe *p)
9460 struct torture_driver_context *d;
9461 struct spoolss_StringArray *a;
9462 uint32_t add_flags = APD_COPY_NEW_FILES;
9463 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9464 struct dcerpc_binding_handle *b = p->binding_handle;
9465 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9467 d = talloc_zero(tctx, struct torture_driver_context);
9469 d->ex = true;
9470 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9471 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9472 d->info8.architecture = NULL;
9473 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9474 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9475 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9476 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9477 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9478 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9480 a = talloc_zero(d, struct spoolss_StringArray);
9481 a->string = talloc_zero_array(a, const char *, 3);
9482 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9483 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9485 d->info8.dependent_files = a;
9486 d->info8.architecture = d->local.environment;
9488 torture_assert(tctx,
9489 fillup_printserver_info(tctx, p, d),
9490 "failed to fillup printserver info");
9492 if (!directory_exist(d->local.driver_directory)) {
9493 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9496 torture_assert(tctx,
9497 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9498 "failed to upload printer driver");
9500 torture_assert(tctx,
9501 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9502 "failed to add driver");
9504 torture_assert(tctx,
9505 test_DeletePrinterDriverEx(tctx, b, server_name_slash, d->info8.driver_name, d->local.environment, delete_flags, d->info8.version),
9506 "failed to delete driver");
9508 torture_assert(tctx,
9509 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9510 "printer driver file check failed");
9512 return true;
9515 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9517 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9519 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9520 "driver", &ndr_table_spoolss);
9521 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9522 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9524 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9525 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9527 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9529 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9531 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9533 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9535 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9537 return suite;