s4-smbtorture: Make test names lowercase and dot-separated.
[Samba.git] / source4 / torture / rpc / spoolss.c
blob26e53eb2524b8eda6d17b3f809440a3f19d80134
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Stefan Metzmacher 2005
7 Copyright (C) Jelmer Vernooij 2007
8 Copyright (C) Guenther Deschner 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
42 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
43 #define TORTURE_PRINTER "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX "torture_printer_ex"
46 #define TORTURE_DRIVER "torture_driver"
47 #define TORTURE_DRIVER_EX "torture_driver_ex"
48 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
49 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
50 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
52 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
53 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
54 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
55 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
56 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
57 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
59 struct test_spoolss_context {
60 struct dcerpc_pipe *spoolss_pipe;
62 /* server environment */
63 const char *environment;
65 /* print server handle */
66 struct policy_handle server_handle;
68 /* for EnumPorts */
69 uint32_t port_count[3];
70 union spoolss_PortInfo *ports[3];
72 /* for EnumPrinterDrivers */
73 uint32_t driver_count[8];
74 union spoolss_DriverInfo *drivers[8];
76 /* for EnumMonitors */
77 uint32_t monitor_count[3];
78 union spoolss_MonitorInfo *monitors[3];
80 /* for EnumPrintProcessors */
81 uint32_t print_processor_count[2];
82 union spoolss_PrintProcessorInfo *print_processors[2];
84 /* for EnumPrinters */
85 uint32_t printer_count[6];
86 union spoolss_PrinterInfo *printers[6];
89 struct torture_driver_context {
90 struct {
91 const char *driver_directory;
92 const char *environment;
93 } local;
94 struct {
95 const char *driver_directory;
96 const char *environment;
97 } remote;
98 struct spoolss_AddDriverInfo8 info8;
99 bool ex;
102 struct torture_printer_context {
103 struct dcerpc_pipe *spoolss_pipe;
104 struct spoolss_SetPrinterInfo2 info2;
105 struct torture_driver_context driver;
106 bool ex;
107 bool wellknown;
108 bool added_driver;
109 bool have_driver;
110 struct spoolss_DeviceMode *devmode;
111 struct policy_handle handle;
114 static bool upload_printer_driver(struct torture_context *tctx,
115 const char *server_name,
116 struct torture_driver_context *d);
117 static bool remove_printer_driver(struct torture_context *tctx,
118 const char *server_name,
119 struct torture_driver_context *d);
120 static bool fillup_printserver_info(struct torture_context *tctx,
121 struct dcerpc_pipe *p,
122 struct torture_driver_context *d);
123 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
124 struct dcerpc_binding_handle *b,
125 const char *server_name,
126 struct spoolss_AddDriverInfo8 *r,
127 uint32_t flags,
128 bool ex);
130 #define COMPARE_STRING(tctx, c,r,e) \
131 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
133 /* not every compiler supports __typeof__() */
134 #if (__GNUC__ >= 3)
135 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
136 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
137 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
139 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
140 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
142 } while(0)
143 #else
144 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
145 #endif
147 #define COMPARE_UINT32(tctx, c, r, e) do {\
148 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
149 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
150 } while(0)
152 #define COMPARE_UINT64(tctx, c, r, e) do {\
153 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
154 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
155 } while(0)
158 #define COMPARE_NTTIME(tctx, c, r, e) do {\
159 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
160 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
161 } while(0)
163 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
164 int __i; \
165 if (!c.e && !r.e) { \
166 break; \
168 if (c.e && !r.e) { \
169 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
171 if (!c.e && r.e) { \
172 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
174 for (__i=0;c.e[__i] != NULL; __i++) { \
175 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
177 } while(0)
179 #define CHECK_ALIGN(size, n) do {\
180 if (size % n) {\
181 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
182 size, n, size + n - (size % n));\
184 } while(0)
186 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
188 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
189 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
190 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
191 uint32_t round_size = DO_ROUND(size, align);\
192 if (round_size != needed) {\
193 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
194 CHECK_ALIGN(size, align);\
197 } while(0)
199 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
200 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
201 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
202 uint32_t round_size = DO_ROUND(size, align);\
203 if (round_size != needed) {\
204 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
205 CHECK_ALIGN(size, align);\
208 } while(0)
210 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
211 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
212 uint32_t size = ndr_size_##fn(info, level, 0);\
213 uint32_t round_size = DO_ROUND(size, align);\
214 if (round_size != needed) {\
215 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
216 CHECK_ALIGN(size, align);\
219 } while(0)
221 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
222 const union spoolss_PrinterInfo *i,
223 uint32_t level,
224 union spoolss_SetPrinterInfo *s)
226 switch (level) {
227 case 0:
228 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
229 break;
230 case 2:
231 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
232 s->info2->servername = i->info2.servername;
233 s->info2->printername = i->info2.printername;
234 s->info2->sharename = i->info2.sharename;
235 s->info2->portname = i->info2.portname;
236 s->info2->drivername = i->info2.drivername;
237 s->info2->comment = i->info2.comment;
238 s->info2->location = i->info2.location;
239 s->info2->devmode_ptr = 0;
240 s->info2->sepfile = i->info2.sepfile;
241 s->info2->printprocessor = i->info2.printprocessor;
242 s->info2->datatype = i->info2.datatype;
243 s->info2->parameters = i->info2.parameters;
244 s->info2->secdesc_ptr = 0;
245 s->info2->attributes = i->info2.attributes;
246 s->info2->priority = i->info2.priority;
247 s->info2->defaultpriority = i->info2.defaultpriority;
248 s->info2->starttime = i->info2.starttime;
249 s->info2->untiltime = i->info2.untiltime;
250 s->info2->status = i->info2.status;
251 s->info2->cjobs = i->info2.cjobs;
252 s->info2->averageppm = i->info2.averageppm;
253 break;
254 case 3:
255 case 4:
256 case 5:
257 case 6:
258 case 7:
259 case 8:
260 case 9:
261 default:
262 return false;
265 return true;
268 static bool test_OpenPrinter_server(struct torture_context *tctx,
269 struct dcerpc_pipe *p,
270 struct policy_handle *server_handle)
272 NTSTATUS status;
273 struct spoolss_OpenPrinter op;
274 struct dcerpc_binding_handle *b = p->binding_handle;
276 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
277 op.in.datatype = NULL;
278 op.in.devmode_ctr.devmode= NULL;
279 op.in.access_mask = 0;
280 op.out.handle = server_handle;
282 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
284 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
285 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
286 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
288 return true;
291 static bool test_EnumPorts(struct torture_context *tctx,
292 void *private_data)
294 struct test_spoolss_context *ctx =
295 talloc_get_type_abort(private_data, struct test_spoolss_context);
296 struct dcerpc_pipe *p = ctx->spoolss_pipe;
297 struct dcerpc_binding_handle *b = p->binding_handle;
298 NTSTATUS status;
299 struct spoolss_EnumPorts r;
300 uint16_t levels[] = { 1, 2 };
301 int i, j;
303 for (i=0;i<ARRAY_SIZE(levels);i++) {
304 int level = levels[i];
305 DATA_BLOB blob;
306 uint32_t needed;
307 uint32_t count;
308 union spoolss_PortInfo *info;
310 r.in.servername = "";
311 r.in.level = level;
312 r.in.buffer = NULL;
313 r.in.offered = 0;
314 r.out.needed = &needed;
315 r.out.count = &count;
316 r.out.info = &info;
318 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
320 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
321 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
322 if (W_ERROR_IS_OK(r.out.result)) {
323 /* TODO: do some more checks here */
324 continue;
326 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
327 "EnumPorts unexpected return code");
329 blob = data_blob_talloc_zero(ctx, needed);
330 r.in.buffer = &blob;
331 r.in.offered = needed;
333 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
334 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
336 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
338 torture_assert(tctx, info, "EnumPorts returned no info");
340 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
342 ctx->port_count[level] = count;
343 ctx->ports[level] = info;
346 for (i=1;i<ARRAY_SIZE(levels);i++) {
347 int level = levels[i];
348 int old_level = levels[i-1];
349 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
350 "EnumPorts invalid value");
352 /* if the array sizes are not the same we would maybe segfault in the following code */
354 for (i=0;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 for (j=0;j<ctx->port_count[level];j++) {
357 union spoolss_PortInfo *cur = &ctx->ports[level][j];
358 union spoolss_PortInfo *ref = &ctx->ports[2][j];
359 switch (level) {
360 case 1:
361 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
362 break;
363 case 2:
364 /* level 2 is our reference, and it makes no sense to compare it to itself */
365 break;
370 return true;
373 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
374 void *private_data)
376 struct test_spoolss_context *ctx =
377 talloc_get_type_abort(private_data, struct test_spoolss_context);
379 NTSTATUS status;
380 struct dcerpc_pipe *p = ctx->spoolss_pipe;
381 struct dcerpc_binding_handle *b = p->binding_handle;
382 struct spoolss_GetPrintProcessorDirectory r;
383 struct {
384 uint16_t level;
385 const char *server;
386 } levels[] = {{
387 .level = 1,
388 .server = NULL
390 .level = 1,
391 .server = ""
393 .level = 78,
394 .server = ""
396 .level = 1,
397 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
399 .level = 1024,
400 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
403 int i;
404 uint32_t needed;
406 for (i=0;i<ARRAY_SIZE(levels);i++) {
407 int level = levels[i].level;
408 DATA_BLOB blob;
410 r.in.server = levels[i].server;
411 r.in.environment = ctx->environment;
412 r.in.level = level;
413 r.in.buffer = NULL;
414 r.in.offered = 0;
415 r.out.needed = &needed;
417 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
419 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
420 torture_assert_ntstatus_ok(tctx, status,
421 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
422 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
423 "GetPrintProcessorDirectory unexpected return code");
425 blob = data_blob_talloc_zero(tctx, needed);
426 r.in.buffer = &blob;
427 r.in.offered = needed;
429 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
430 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
432 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
434 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
437 return true;
441 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
442 void *private_data)
444 struct test_spoolss_context *ctx =
445 talloc_get_type_abort(private_data, struct test_spoolss_context);
447 NTSTATUS status;
448 struct dcerpc_pipe *p = ctx->spoolss_pipe;
449 struct dcerpc_binding_handle *b = p->binding_handle;
450 struct spoolss_GetPrinterDriverDirectory r;
451 struct {
452 uint16_t level;
453 const char *server;
454 } levels[] = {{
455 .level = 1,
456 .server = NULL
458 .level = 1,
459 .server = ""
461 .level = 78,
462 .server = ""
464 .level = 1,
465 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
467 .level = 1024,
468 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
471 int i;
472 uint32_t needed;
474 for (i=0;i<ARRAY_SIZE(levels);i++) {
475 int level = levels[i].level;
476 DATA_BLOB blob;
478 r.in.server = levels[i].server;
479 r.in.environment = ctx->environment;
480 r.in.level = level;
481 r.in.buffer = NULL;
482 r.in.offered = 0;
483 r.out.needed = &needed;
485 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
487 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
488 torture_assert_ntstatus_ok(tctx, status,
489 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
490 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
491 "GetPrinterDriverDirectory unexpected return code");
493 blob = data_blob_talloc_zero(tctx, needed);
494 r.in.buffer = &blob;
495 r.in.offered = needed;
497 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
498 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
500 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
502 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
505 return true;
508 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
509 struct dcerpc_binding_handle *b,
510 const char *server_name,
511 const char *environment,
512 uint32_t level,
513 uint32_t *count_p,
514 union spoolss_DriverInfo **info_p)
516 struct spoolss_EnumPrinterDrivers r;
517 uint32_t needed;
518 uint32_t count;
519 union spoolss_DriverInfo *info;
521 r.in.server = server_name;
522 r.in.environment = environment;
523 r.in.level = level;
524 r.in.buffer = NULL;
525 r.in.offered = 0;
526 r.out.needed = &needed;
527 r.out.count = &count;
528 r.out.info = &info;
530 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
531 r.in.environment, r.in.level);
533 torture_assert_ntstatus_ok(tctx,
534 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
535 "EnumPrinterDrivers failed");
536 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
537 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
538 r.in.buffer = &blob;
539 r.in.offered = needed;
541 torture_assert_ntstatus_ok(tctx,
542 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
543 "EnumPrinterDrivers failed");
546 torture_assert_werr_ok(tctx, r.out.result,
547 "EnumPrinterDrivers failed");
549 if (count_p) {
550 *count_p = count;
552 if (info_p) {
553 *info_p = info;
556 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
558 return true;
562 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
563 struct dcerpc_binding_handle *b,
564 const char *server_name,
565 const char *environment,
566 uint32_t level,
567 const char *driver_name)
569 uint32_t count;
570 union spoolss_DriverInfo *info;
571 int i;
573 torture_assert(tctx,
574 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
575 "failed to enumerate printer drivers");
577 for (i=0; i < count; i++) {
578 const char *driver_name_ret;
579 switch (level) {
580 case 1:
581 driver_name_ret = info[i].info1.driver_name;
582 break;
583 case 2:
584 driver_name_ret = info[i].info2.driver_name;
585 break;
586 case 3:
587 driver_name_ret = info[i].info3.driver_name;
588 break;
589 case 4:
590 driver_name_ret = info[i].info4.driver_name;
591 break;
592 case 5:
593 driver_name_ret = info[i].info5.driver_name;
594 break;
595 case 6:
596 driver_name_ret = info[i].info6.driver_name;
597 break;
598 case 7:
599 driver_name_ret = info[i].info7.driver_name;
600 break;
601 case 8:
602 driver_name_ret = info[i].info8.driver_name;
603 break;
604 default:
605 break;
607 if (strequal(driver_name, driver_name_ret)) {
608 return true;
612 return false;
615 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
616 void *private_data)
618 struct test_spoolss_context *ctx =
619 talloc_get_type_abort(private_data, struct test_spoolss_context);
620 struct dcerpc_pipe *p = ctx->spoolss_pipe;
621 struct dcerpc_binding_handle *b = p->binding_handle;
622 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
623 int i, j, a;
625 /* FIXME: gd, come back and fix "" as server, and handle
626 * priority of returned error codes in torture test and samba 3
627 * server */
628 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
629 const char *environments[2];
631 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
632 environments[1] = ctx->environment;
634 for (a=0;a<ARRAY_SIZE(environments);a++) {
636 for (i=0;i<ARRAY_SIZE(levels);i++) {
637 int level = levels[i];
638 uint32_t count;
639 union spoolss_DriverInfo *info;
641 torture_assert(tctx,
642 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
643 "failed to enumerate drivers");
645 ctx->driver_count[level] = count;
646 ctx->drivers[level] = info;
649 for (i=1;i<ARRAY_SIZE(levels);i++) {
650 int level = levels[i];
651 int old_level = levels[i-1];
653 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
654 "EnumPrinterDrivers invalid value");
657 for (i=0;i<ARRAY_SIZE(levels);i++) {
658 int level = levels[i];
660 for (j=0;j<ctx->driver_count[level];j++) {
661 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
662 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
664 switch (level) {
665 case 1:
666 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
667 break;
668 case 2:
669 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
670 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
671 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
672 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
673 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
674 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
675 break;
676 case 3:
677 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
678 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
679 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
680 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
681 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
682 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
683 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
684 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
685 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
686 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
687 break;
688 case 4:
689 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
690 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
691 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
692 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
693 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
694 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
695 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
696 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
697 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
698 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
699 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
700 break;
701 case 5:
702 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
703 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
704 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
705 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
706 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
707 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
708 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
709 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
710 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
711 break;
712 case 6:
713 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
714 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
715 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
716 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
717 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
718 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
719 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
720 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
721 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
722 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
723 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
724 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
725 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
726 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
727 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
728 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
729 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
730 break;
731 case 8:
732 /* level 8 is our reference, and it makes no sense to compare it to itself */
733 break;
739 return true;
742 static bool test_EnumMonitors(struct torture_context *tctx,
743 void *private_data)
745 struct test_spoolss_context *ctx =
746 talloc_get_type_abort(private_data, struct test_spoolss_context);
747 struct dcerpc_pipe *p = ctx->spoolss_pipe;
748 struct dcerpc_binding_handle *b = p->binding_handle;
749 NTSTATUS status;
750 struct spoolss_EnumMonitors r;
751 uint16_t levels[] = { 1, 2 };
752 int i, j;
754 for (i=0;i<ARRAY_SIZE(levels);i++) {
755 int level = levels[i];
756 DATA_BLOB blob;
757 uint32_t needed;
758 uint32_t count;
759 union spoolss_MonitorInfo *info;
761 r.in.servername = "";
762 r.in.level = level;
763 r.in.buffer = NULL;
764 r.in.offered = 0;
765 r.out.needed = &needed;
766 r.out.count = &count;
767 r.out.info = &info;
769 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
771 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
772 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
773 if (W_ERROR_IS_OK(r.out.result)) {
774 /* TODO: do some more checks here */
775 continue;
777 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
778 "EnumMonitors failed");
780 blob = data_blob_talloc_zero(ctx, needed);
781 r.in.buffer = &blob;
782 r.in.offered = needed;
784 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
785 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
787 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
789 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
791 ctx->monitor_count[level] = count;
792 ctx->monitors[level] = info;
795 for (i=1;i<ARRAY_SIZE(levels);i++) {
796 int level = levels[i];
797 int old_level = levels[i-1];
798 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
799 "EnumMonitors invalid value");
802 for (i=0;i<ARRAY_SIZE(levels);i++) {
803 int level = levels[i];
804 for (j=0;j<ctx->monitor_count[level];j++) {
805 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
806 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
807 switch (level) {
808 case 1:
809 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
810 break;
811 case 2:
812 /* level 2 is our reference, and it makes no sense to compare it to itself */
813 break;
818 return true;
821 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
822 struct dcerpc_binding_handle *b,
823 const char *environment,
824 uint32_t level,
825 uint32_t *count_p,
826 union spoolss_PrintProcessorInfo **info_p,
827 WERROR expected_result)
829 struct spoolss_EnumPrintProcessors r;
830 DATA_BLOB blob;
831 uint32_t needed;
832 uint32_t count;
833 union spoolss_PrintProcessorInfo *info;
835 r.in.servername = "";
836 r.in.environment = environment;
837 r.in.level = level;
838 r.in.buffer = NULL;
839 r.in.offered = 0;
840 r.out.needed = &needed;
841 r.out.count = &count;
842 r.out.info = &info;
844 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
845 r.in.environment, r.in.level);
847 torture_assert_ntstatus_ok(tctx,
848 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
849 "EnumPrintProcessors failed");
850 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
851 blob = data_blob_talloc_zero(tctx, needed);
852 r.in.buffer = &blob;
853 r.in.offered = needed;
854 torture_assert_ntstatus_ok(tctx,
855 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
856 "EnumPrintProcessors failed");
858 torture_assert_werr_equal(tctx, r.out.result, expected_result,
859 "EnumPrintProcessors failed");
861 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
863 if (count_p) {
864 *count_p = count;
866 if (info_p) {
867 *info_p = info;
870 return true;
873 static bool test_EnumPrintProcessors(struct torture_context *tctx,
874 void *private_data)
876 struct test_spoolss_context *ctx =
877 talloc_get_type_abort(private_data, struct test_spoolss_context);
879 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
880 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
881 int i;
882 struct dcerpc_pipe *p = ctx->spoolss_pipe;
883 struct dcerpc_binding_handle *b = p->binding_handle;
885 torture_assert(tctx,
886 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
887 "test_EnumPrintProcessors_level failed");
889 for (i=0;i<ARRAY_SIZE(levels);i++) {
890 union spoolss_PrintProcessorInfo *info;
891 uint32_t count;
892 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
894 torture_assert(tctx,
895 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
896 "test_EnumPrintProcessors_level failed");
899 return true;
902 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
903 struct dcerpc_binding_handle *b,
904 const char *print_processor_name,
905 uint32_t level,
906 uint32_t *count_p,
907 union spoolss_PrintProcDataTypesInfo **info_p,
908 WERROR expected_result)
910 struct spoolss_EnumPrintProcDataTypes r;
911 DATA_BLOB blob;
912 uint32_t needed;
913 uint32_t count;
914 union spoolss_PrintProcDataTypesInfo *info;
916 r.in.servername = "";
917 r.in.print_processor_name = print_processor_name;
918 r.in.level = level;
919 r.in.buffer = NULL;
920 r.in.offered = 0;
921 r.out.needed = &needed;
922 r.out.count = &count;
923 r.out.info = &info;
925 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
926 r.in.print_processor_name, r.in.level);
928 torture_assert_ntstatus_ok(tctx,
929 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
930 "EnumPrintProcDataTypes failed");
931 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
932 blob = data_blob_talloc_zero(tctx, needed);
933 r.in.buffer = &blob;
934 r.in.offered = needed;
935 torture_assert_ntstatus_ok(tctx,
936 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
937 "EnumPrintProcDataTypes failed");
939 torture_assert_werr_equal(tctx, r.out.result, expected_result,
940 "EnumPrintProcDataTypes failed");
942 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
944 if (count_p) {
945 *count_p = count;
947 if (info_p) {
948 *info_p = info;
951 return true;
954 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
955 void *private_data)
957 struct test_spoolss_context *ctx =
958 talloc_get_type_abort(private_data, struct test_spoolss_context);
960 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
961 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
962 int i;
963 struct dcerpc_pipe *p = ctx->spoolss_pipe;
964 struct dcerpc_binding_handle *b = p->binding_handle;
966 torture_assert(tctx,
967 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
968 "test_EnumPrintProcDataTypes_level failed");
970 torture_assert(tctx,
971 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
972 "test_EnumPrintProcDataTypes_level failed");
974 for (i=0;i<ARRAY_SIZE(levels);i++) {
975 int level = levels[i];
976 uint32_t count;
977 union spoolss_PrintProcDataTypesInfo *info;
978 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
980 torture_assert(tctx,
981 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
982 "test_EnumPrintProcDataTypes_level failed");
986 union spoolss_PrintProcessorInfo *info;
987 uint32_t count;
989 torture_assert(tctx,
990 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
991 "test_EnumPrintProcessors_level failed");
993 for (i=0; i < count; i++) {
994 torture_assert(tctx,
995 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
996 "test_EnumPrintProcDataTypes_level failed");
1001 return true;
1004 static bool test_EnumPrinters(struct torture_context *tctx,
1005 void *private_data)
1007 struct test_spoolss_context *ctx =
1008 talloc_get_type_abort(private_data, struct test_spoolss_context);
1009 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1010 struct dcerpc_binding_handle *b = p->binding_handle;
1011 struct spoolss_EnumPrinters r;
1012 NTSTATUS status;
1013 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1014 int i, j;
1016 for (i=0;i<ARRAY_SIZE(levels);i++) {
1017 int level = levels[i];
1018 DATA_BLOB blob;
1019 uint32_t needed;
1020 uint32_t count;
1021 union spoolss_PrinterInfo *info;
1023 r.in.flags = PRINTER_ENUM_LOCAL;
1024 r.in.server = "";
1025 r.in.level = level;
1026 r.in.buffer = NULL;
1027 r.in.offered = 0;
1028 r.out.needed = &needed;
1029 r.out.count = &count;
1030 r.out.info = &info;
1032 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1034 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1035 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1036 if (W_ERROR_IS_OK(r.out.result)) {
1037 /* TODO: do some more checks here */
1038 continue;
1040 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1041 "EnumPrinters unexpected return code");
1043 blob = data_blob_talloc_zero(ctx, needed);
1044 r.in.buffer = &blob;
1045 r.in.offered = needed;
1047 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1048 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1050 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1052 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1054 ctx->printer_count[level] = count;
1055 ctx->printers[level] = info;
1058 for (i=1;i<ARRAY_SIZE(levels);i++) {
1059 int level = levels[i];
1060 int old_level = levels[i-1];
1061 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1062 "EnumPrinters invalid value");
1065 for (i=0;i<ARRAY_SIZE(levels);i++) {
1066 int level = levels[i];
1067 for (j=0;j<ctx->printer_count[level];j++) {
1068 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1069 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1070 switch (level) {
1071 case 0:
1072 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1073 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1074 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1075 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1076 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1077 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1078 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1079 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1080 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1081 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1082 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1083 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1084 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1085 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1086 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1087 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1088 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1089 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1090 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1091 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1092 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1093 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1094 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1095 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1096 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1097 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1099 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1101 break;
1102 case 1:
1103 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1104 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1105 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1106 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1107 break;
1108 case 2:
1109 /* level 2 is our reference, and it makes no sense to compare it to itself */
1110 break;
1111 case 4:
1112 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1113 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1114 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1115 break;
1116 case 5:
1117 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1118 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1119 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1120 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1121 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1122 break;
1127 /* TODO:
1128 * - verify that the port of a printer was in the list returned by EnumPorts
1131 return true;
1134 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1135 struct dcerpc_binding_handle *b,
1136 struct policy_handle *handle,
1137 const char *driver_name,
1138 const char *environment);
1140 bool test_GetPrinter_level(struct torture_context *tctx,
1141 struct dcerpc_binding_handle *b,
1142 struct policy_handle *handle,
1143 uint32_t level,
1144 union spoolss_PrinterInfo *info)
1146 struct spoolss_GetPrinter r;
1147 uint32_t needed;
1149 r.in.handle = handle;
1150 r.in.level = level;
1151 r.in.buffer = NULL;
1152 r.in.offered = 0;
1153 r.out.needed = &needed;
1155 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1157 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1158 "GetPrinter failed");
1160 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1161 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1162 r.in.buffer = &blob;
1163 r.in.offered = needed;
1165 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1166 "GetPrinter failed");
1169 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1171 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1173 if (info && r.out.info) {
1174 *info = *r.out.info;
1177 return true;
1181 static bool test_GetPrinter(struct torture_context *tctx,
1182 struct dcerpc_binding_handle *b,
1183 struct policy_handle *handle,
1184 const char *environment)
1186 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1187 int i;
1189 for (i=0;i<ARRAY_SIZE(levels);i++) {
1191 union spoolss_PrinterInfo info;
1193 ZERO_STRUCT(info);
1195 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1196 "failed to call GetPrinter");
1198 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1199 torture_assert(tctx,
1200 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1201 "failed to call test_GetPrinterDriver2");
1205 return true;
1208 static bool test_SetPrinter(struct torture_context *tctx,
1209 struct dcerpc_binding_handle *b,
1210 struct policy_handle *handle,
1211 struct spoolss_SetPrinterInfoCtr *info_ctr,
1212 struct spoolss_DevmodeContainer *devmode_ctr,
1213 struct sec_desc_buf *secdesc_ctr,
1214 enum spoolss_PrinterControl command)
1216 struct spoolss_SetPrinter r;
1218 r.in.handle = handle;
1219 r.in.info_ctr = info_ctr;
1220 r.in.devmode_ctr = devmode_ctr;
1221 r.in.secdesc_ctr = secdesc_ctr;
1222 r.in.command = command;
1224 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1226 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1227 "failed to call SetPrinter");
1228 torture_assert_werr_ok(tctx, r.out.result,
1229 "failed to call SetPrinter");
1231 return true;
1234 static bool test_SetPrinter_errors(struct torture_context *tctx,
1235 struct dcerpc_binding_handle *b,
1236 struct policy_handle *handle)
1238 struct spoolss_SetPrinter r;
1239 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1240 int i;
1242 struct spoolss_SetPrinterInfoCtr info_ctr;
1243 struct spoolss_DevmodeContainer devmode_ctr;
1244 struct sec_desc_buf secdesc_ctr;
1246 info_ctr.level = 0;
1247 info_ctr.info.info0 = NULL;
1249 ZERO_STRUCT(devmode_ctr);
1250 ZERO_STRUCT(secdesc_ctr);
1252 r.in.handle = handle;
1253 r.in.info_ctr = &info_ctr;
1254 r.in.devmode_ctr = &devmode_ctr;
1255 r.in.secdesc_ctr = &secdesc_ctr;
1256 r.in.command = 0;
1258 torture_comment(tctx, "Testing SetPrinter all zero\n");
1260 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1261 "failed to call SetPrinter");
1262 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1263 "failed to call SetPrinter");
1265 again:
1266 for (i=0; i < ARRAY_SIZE(levels); i++) {
1268 struct spoolss_SetPrinterInfo0 info0;
1269 struct spoolss_SetPrinterInfo1 info1;
1270 struct spoolss_SetPrinterInfo2 info2;
1271 struct spoolss_SetPrinterInfo3 info3;
1272 struct spoolss_SetPrinterInfo4 info4;
1273 struct spoolss_SetPrinterInfo5 info5;
1274 struct spoolss_SetPrinterInfo6 info6;
1275 struct spoolss_SetPrinterInfo7 info7;
1276 struct spoolss_SetPrinterInfo8 info8;
1277 struct spoolss_SetPrinterInfo9 info9;
1280 info_ctr.level = levels[i];
1281 switch (levels[i]) {
1282 case 0:
1283 ZERO_STRUCT(info0);
1284 info_ctr.info.info0 = &info0;
1285 break;
1286 case 1:
1287 ZERO_STRUCT(info1);
1288 info_ctr.info.info1 = &info1;
1289 break;
1290 case 2:
1291 ZERO_STRUCT(info2);
1292 info_ctr.info.info2 = &info2;
1293 break;
1294 case 3:
1295 ZERO_STRUCT(info3);
1296 info_ctr.info.info3 = &info3;
1297 break;
1298 case 4:
1299 ZERO_STRUCT(info4);
1300 info_ctr.info.info4 = &info4;
1301 break;
1302 case 5:
1303 ZERO_STRUCT(info5);
1304 info_ctr.info.info5 = &info5;
1305 break;
1306 case 6:
1307 ZERO_STRUCT(info6);
1308 info_ctr.info.info6 = &info6;
1309 break;
1310 case 7:
1311 ZERO_STRUCT(info7);
1312 info_ctr.info.info7 = &info7;
1313 break;
1314 case 8:
1315 ZERO_STRUCT(info8);
1316 info_ctr.info.info8 = &info8;
1317 break;
1318 case 9:
1319 ZERO_STRUCT(info9);
1320 info_ctr.info.info9 = &info9;
1321 break;
1324 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1325 info_ctr.level, r.in.command);
1327 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1328 "failed to call SetPrinter");
1330 switch (r.in.command) {
1331 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1332 /* is ignored for all levels other then 0 */
1333 if (info_ctr.level > 0) {
1334 /* ignored then */
1335 break;
1337 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1338 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1339 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1340 if (info_ctr.level > 0) {
1341 /* is invalid for all levels other then 0 */
1342 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1343 "unexpected error code returned");
1344 continue;
1345 } else {
1346 torture_assert_werr_ok(tctx, r.out.result,
1347 "failed to call SetPrinter with non 0 command");
1348 continue;
1350 break;
1352 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1353 /* FIXME: gd needs further investigation */
1354 default:
1355 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1356 "unexpected error code returned");
1357 continue;
1360 switch (info_ctr.level) {
1361 case 1:
1362 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1363 "unexpected error code returned");
1364 break;
1365 case 2:
1366 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1367 "unexpected error code returned");
1368 break;
1369 case 3:
1370 case 4:
1371 case 5:
1372 case 7:
1373 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1374 "unexpected error code returned");
1375 break;
1376 case 9:
1377 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1378 "unexpected error code returned");
1379 break;
1380 default:
1381 torture_assert_werr_ok(tctx, r.out.result,
1382 "failed to call SetPrinter");
1383 break;
1387 if (r.in.command < 5) {
1388 r.in.command++;
1389 goto again;
1392 return true;
1395 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1397 if ((r->level == 2) && (r->info.info2)) {
1398 r->info.info2->secdesc_ptr = 0;
1399 r->info.info2->devmode_ptr = 0;
1403 static bool test_PrinterInfo(struct torture_context *tctx,
1404 struct dcerpc_binding_handle *b,
1405 struct policy_handle *handle)
1407 NTSTATUS status;
1408 struct spoolss_SetPrinter s;
1409 struct spoolss_GetPrinter q;
1410 struct spoolss_GetPrinter q0;
1411 struct spoolss_SetPrinterInfoCtr info_ctr;
1412 union spoolss_PrinterInfo info;
1413 struct spoolss_DevmodeContainer devmode_ctr;
1414 struct sec_desc_buf secdesc_ctr;
1415 uint32_t needed;
1416 bool ret = true;
1417 int i;
1419 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1421 uint32_t status_list[] = {
1422 /* these do not stick
1423 PRINTER_STATUS_PAUSED,
1424 PRINTER_STATUS_ERROR,
1425 PRINTER_STATUS_PENDING_DELETION, */
1426 PRINTER_STATUS_PAPER_JAM,
1427 PRINTER_STATUS_PAPER_OUT,
1428 PRINTER_STATUS_MANUAL_FEED,
1429 PRINTER_STATUS_PAPER_PROBLEM,
1430 PRINTER_STATUS_OFFLINE,
1431 PRINTER_STATUS_IO_ACTIVE,
1432 PRINTER_STATUS_BUSY,
1433 PRINTER_STATUS_PRINTING,
1434 PRINTER_STATUS_OUTPUT_BIN_FULL,
1435 PRINTER_STATUS_NOT_AVAILABLE,
1436 PRINTER_STATUS_WAITING,
1437 PRINTER_STATUS_PROCESSING,
1438 PRINTER_STATUS_INITIALIZING,
1439 PRINTER_STATUS_WARMING_UP,
1440 PRINTER_STATUS_TONER_LOW,
1441 PRINTER_STATUS_NO_TONER,
1442 PRINTER_STATUS_PAGE_PUNT,
1443 PRINTER_STATUS_USER_INTERVENTION,
1444 PRINTER_STATUS_OUT_OF_MEMORY,
1445 PRINTER_STATUS_DOOR_OPEN,
1446 PRINTER_STATUS_SERVER_UNKNOWN,
1447 PRINTER_STATUS_POWER_SAVE,
1448 /* these do not stick
1449 0x02000000,
1450 0x04000000,
1451 0x08000000,
1452 0x10000000,
1453 0x20000000,
1454 0x40000000,
1455 0x80000000 */
1457 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1458 uint32_t attribute_list[] = {
1459 PRINTER_ATTRIBUTE_QUEUED,
1460 /* fails with WERR_INVALID_DATATYPE:
1461 PRINTER_ATTRIBUTE_DIRECT, */
1462 /* does not stick
1463 PRINTER_ATTRIBUTE_DEFAULT, */
1464 PRINTER_ATTRIBUTE_SHARED,
1465 /* does not stick
1466 PRINTER_ATTRIBUTE_NETWORK, */
1467 PRINTER_ATTRIBUTE_HIDDEN,
1468 PRINTER_ATTRIBUTE_LOCAL,
1469 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1470 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1471 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1472 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1473 /* does not stick
1474 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1475 /* fails with WERR_INVALID_DATATYPE:
1476 PRINTER_ATTRIBUTE_RAW_ONLY, */
1477 /* these do not stick
1478 PRINTER_ATTRIBUTE_PUBLISHED,
1479 PRINTER_ATTRIBUTE_FAX,
1480 PRINTER_ATTRIBUTE_TS,
1481 0x00010000,
1482 0x00020000,
1483 0x00040000,
1484 0x00080000,
1485 0x00100000,
1486 0x00200000,
1487 0x00400000,
1488 0x00800000,
1489 0x01000000,
1490 0x02000000,
1491 0x04000000,
1492 0x08000000,
1493 0x10000000,
1494 0x20000000,
1495 0x40000000,
1496 0x80000000 */
1499 ZERO_STRUCT(devmode_ctr);
1500 ZERO_STRUCT(secdesc_ctr);
1502 s.in.handle = handle;
1503 s.in.command = 0;
1504 s.in.info_ctr = &info_ctr;
1505 s.in.devmode_ctr = &devmode_ctr;
1506 s.in.secdesc_ctr = &secdesc_ctr;
1508 q.in.handle = handle;
1509 q.out.info = &info;
1510 q0 = q;
1512 #define TESTGETCALL(call, r) \
1513 r.in.buffer = NULL; \
1514 r.in.offered = 0;\
1515 r.out.needed = &needed; \
1516 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1517 if (!NT_STATUS_IS_OK(status)) { \
1518 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1519 r.in.level, nt_errstr(status), __location__); \
1520 ret = false; \
1521 break; \
1523 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1524 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1525 r.in.buffer = &blob; \
1526 r.in.offered = needed; \
1528 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1529 if (!NT_STATUS_IS_OK(status)) { \
1530 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1531 r.in.level, nt_errstr(status), __location__); \
1532 ret = false; \
1533 break; \
1535 if (!W_ERROR_IS_OK(r.out.result)) { \
1536 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1537 r.in.level, win_errstr(r.out.result), __location__); \
1538 ret = false; \
1539 break; \
1543 #define TESTSETCALL_EXP(call, r, err) \
1544 clear_info2(&info_ctr);\
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.info_ctr->level, nt_errstr(status), __location__); \
1549 ret = false; \
1550 break; \
1552 if (!W_ERROR_IS_OK(err)) { \
1553 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1554 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1555 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1556 ret = false; \
1558 break; \
1560 if (!W_ERROR_IS_OK(r.out.result)) { \
1561 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1562 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1563 ret = false; \
1564 break; \
1567 #define TESTSETCALL(call, r) \
1568 TESTSETCALL_EXP(call, r, WERR_OK)
1570 #define STRING_EQUAL(s1, s2, field) \
1571 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1572 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1573 #field, s2, __location__); \
1574 ret = false; \
1575 break; \
1578 #define MEM_EQUAL(s1, s2, length, field) \
1579 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1580 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1581 #field, (const char *)s2, __location__); \
1582 ret = false; \
1583 break; \
1586 #define INT_EQUAL(i1, i2, field) \
1587 if (i1 != i2) { \
1588 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1589 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1590 ret = false; \
1591 break; \
1594 #define SD_EQUAL(sd1, sd2, field) \
1595 if (!security_descriptor_equal(sd1, sd2)) { \
1596 torture_comment(tctx, "Failed to set %s (%s)\n", \
1597 #field, __location__); \
1598 ret = false; \
1599 break; \
1602 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1603 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1604 q.in.level = lvl1; \
1605 TESTGETCALL(GetPrinter, q) \
1606 info_ctr.level = lvl1; \
1607 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1608 info_ctr.info.info ## lvl1->field1 = value;\
1609 TESTSETCALL_EXP(SetPrinter, s, err) \
1610 info_ctr.info.info ## lvl1->field1 = ""; \
1611 TESTGETCALL(GetPrinter, q) \
1612 info_ctr.info.info ## lvl1->field1 = value; \
1613 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1614 q.in.level = lvl2; \
1615 TESTGETCALL(GetPrinter, q) \
1616 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1617 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1618 } while (0)
1620 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1621 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1622 } while (0);
1624 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1625 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626 q.in.level = lvl1; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.level = lvl1; \
1629 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630 info_ctr.info.info ## lvl1->field1 = value; \
1631 TESTSETCALL(SetPrinter, s) \
1632 info_ctr.info.info ## lvl1->field1 = 0; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1635 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1636 q.in.level = lvl2; \
1637 TESTGETCALL(GetPrinter, q) \
1638 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1640 } while (0)
1642 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1643 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1644 } while (0)
1646 q0.in.level = 0;
1647 do { TESTGETCALL(GetPrinter, q0) } while (0);
1649 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1650 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1652 /* level 0 printername does not stick */
1653 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1654 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1655 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1656 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1657 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1658 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1659 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1660 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1661 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1662 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1663 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1664 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1665 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1666 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1667 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1669 /* servername can be set but does not stick
1670 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1671 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1672 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1675 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1676 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1677 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1678 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1679 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1681 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1682 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1683 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1684 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1685 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1686 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1687 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1688 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1689 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1690 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1692 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1693 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1694 attribute_list[i],
1695 (attribute_list[i] | default_attribute)
1696 ); */
1697 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1698 attribute_list[i],
1699 (attribute_list[i] | default_attribute)
1701 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1702 attribute_list[i],
1703 (attribute_list[i] | default_attribute)
1705 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1706 attribute_list[i],
1707 (attribute_list[i] | default_attribute)
1709 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1710 attribute_list[i],
1711 (attribute_list[i] | default_attribute)
1712 ); */
1713 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1714 attribute_list[i],
1715 (attribute_list[i] | default_attribute)
1717 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1718 attribute_list[i],
1719 (attribute_list[i] | default_attribute)
1721 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1722 attribute_list[i],
1723 (attribute_list[i] | default_attribute)
1725 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1726 attribute_list[i],
1727 (attribute_list[i] | default_attribute)
1728 ); */
1729 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1730 attribute_list[i],
1731 (attribute_list[i] | default_attribute)
1733 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1734 attribute_list[i],
1735 (attribute_list[i] | default_attribute)
1737 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1738 attribute_list[i],
1739 (attribute_list[i] | default_attribute)
1743 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1744 /* level 2 sets do not stick
1745 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1746 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1747 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1748 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1749 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1750 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1753 /* priorities need to be between 0 and 99
1754 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1755 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1756 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1757 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1758 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1759 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1760 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1761 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1762 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1764 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1765 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1767 /* does not stick
1768 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1769 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1771 /* does not stick
1772 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1773 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1775 /* FIXME: gd also test devmode and secdesc behavior */
1778 /* verify composition of level 1 description field */
1779 const char *description;
1780 const char *tmp;
1782 q0.in.level = 1;
1783 do { TESTGETCALL(GetPrinter, q0) } while (0);
1785 description = talloc_strdup(tctx, q0.out.info->info1.description);
1787 q0.in.level = 2;
1788 do { TESTGETCALL(GetPrinter, q0) } while (0);
1790 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1791 q0.out.info->info2.printername,
1792 q0.out.info->info2.drivername,
1793 q0.out.info->info2.location);
1795 do { STRING_EQUAL(description, tmp, "description")} while (0);
1798 return ret;
1801 static bool test_security_descriptor_equal(struct torture_context *tctx,
1802 const struct security_descriptor *sd1,
1803 const struct security_descriptor *sd2)
1805 if (sd1 == sd2) {
1806 return true;
1809 if (!sd1 || !sd2) {
1810 torture_comment(tctx, "%s\n", __location__);
1811 return false;
1814 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1815 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1817 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1818 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1820 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1821 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1822 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1823 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1824 return false;
1826 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1827 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1828 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1829 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1830 return false;
1833 return true;
1836 static bool test_sd_set_level(struct torture_context *tctx,
1837 struct dcerpc_binding_handle *b,
1838 struct policy_handle *handle,
1839 uint32_t level,
1840 struct security_descriptor *sd)
1842 struct spoolss_SetPrinterInfoCtr info_ctr;
1843 struct spoolss_DevmodeContainer devmode_ctr;
1844 struct sec_desc_buf secdesc_ctr;
1845 union spoolss_SetPrinterInfo sinfo;
1847 ZERO_STRUCT(devmode_ctr);
1848 ZERO_STRUCT(secdesc_ctr);
1850 switch (level) {
1851 case 2: {
1852 union spoolss_PrinterInfo info;
1853 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1854 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1856 info_ctr.level = 2;
1857 info_ctr.info = sinfo;
1859 break;
1861 case 3: {
1862 struct spoolss_SetPrinterInfo3 info3;
1864 info3.sec_desc_ptr = 0;
1866 info_ctr.level = 3;
1867 info_ctr.info.info3 = &info3;
1869 break;
1871 default:
1872 return false;
1875 secdesc_ctr.sd = sd;
1877 torture_assert(tctx,
1878 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1880 return true;
1883 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1884 struct dcerpc_binding_handle *b,
1885 struct policy_handle *handle)
1887 union spoolss_PrinterInfo info;
1888 struct security_descriptor *sd1, *sd2;
1889 int i;
1891 /* just compare level 2 and level 3 */
1893 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1895 sd1 = info.info2.secdesc;
1897 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1899 sd2 = info.info3.secdesc;
1901 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1902 "SD level 2 != SD level 3");
1905 /* query level 2, set level 2, query level 2 */
1907 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1909 sd1 = info.info2.secdesc;
1911 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1913 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1915 sd2 = info.info2.secdesc;
1916 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1917 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1918 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1921 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1922 "SD level 2 != SD level 2 after SD has been set via level 2");
1925 /* query level 2, set level 3, query level 2 */
1927 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1929 sd1 = info.info2.secdesc;
1931 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1933 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1935 sd2 = info.info2.secdesc;
1937 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1938 "SD level 2 != SD level 2 after SD has been set via level 3");
1940 /* set modified sd level 3, query level 2 */
1942 for (i=0; i < 93; i++) {
1943 struct security_ace a;
1944 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1945 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1946 a.flags = 0;
1947 a.size = 0; /* autogenerated */
1948 a.access_mask = 0;
1949 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1950 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1953 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1955 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1956 sd2 = info.info2.secdesc;
1958 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1959 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1960 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1963 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1964 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1967 return true;
1971 * wrapper call that saves original sd, runs tests, and restores sd
1974 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1975 struct dcerpc_binding_handle *b,
1976 struct policy_handle *handle)
1978 union spoolss_PrinterInfo info;
1979 struct security_descriptor *sd;
1980 bool ret = true;
1982 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1984 /* save original sd */
1986 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1987 "failed to get initial security descriptor");
1989 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1991 /* run tests */
1993 ret = test_PrinterInfo_SDs(tctx, b, handle);
1995 /* restore original sd */
1997 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1998 "failed to restore initial security descriptor");
2000 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2001 ret ? "succeeded" : "failed");
2004 return ret;
2007 static bool test_devmode_set_level(struct torture_context *tctx,
2008 struct dcerpc_binding_handle *b,
2009 struct policy_handle *handle,
2010 uint32_t level,
2011 struct spoolss_DeviceMode *devmode)
2013 struct spoolss_SetPrinterInfoCtr info_ctr;
2014 struct spoolss_DevmodeContainer devmode_ctr;
2015 struct sec_desc_buf secdesc_ctr;
2016 union spoolss_SetPrinterInfo sinfo;
2018 ZERO_STRUCT(devmode_ctr);
2019 ZERO_STRUCT(secdesc_ctr);
2021 switch (level) {
2022 case 2: {
2023 union spoolss_PrinterInfo info;
2024 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2025 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2027 info_ctr.level = 2;
2028 info_ctr.info = sinfo;
2030 break;
2032 case 8: {
2033 struct spoolss_SetPrinterInfo8 info8;
2035 info8.devmode_ptr = 0;
2037 info_ctr.level = 8;
2038 info_ctr.info.info8 = &info8;
2040 break;
2042 default:
2043 return false;
2046 devmode_ctr.devmode = devmode;
2048 torture_assert(tctx,
2049 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2051 return true;
2055 static bool test_devicemode_equal(struct torture_context *tctx,
2056 const struct spoolss_DeviceMode *d1,
2057 const struct spoolss_DeviceMode *d2)
2059 if (d1 == d2) {
2060 return true;
2063 if (!d1 || !d2) {
2064 torture_comment(tctx, "%s\n", __location__);
2065 return false;
2067 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2068 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2069 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2070 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2071 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2072 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2073 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2074 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2075 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2076 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2077 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2078 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2079 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2080 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2081 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2082 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2083 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2084 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2085 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2086 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2087 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2088 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2089 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2090 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2091 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2092 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2093 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2094 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2095 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2096 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2097 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2098 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2099 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2100 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2101 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2103 return true;
2106 static bool test_devicemode_full(struct torture_context *tctx,
2107 struct dcerpc_binding_handle *b,
2108 struct policy_handle *handle)
2110 struct spoolss_SetPrinter s;
2111 struct spoolss_GetPrinter q;
2112 struct spoolss_GetPrinter q0;
2113 struct spoolss_SetPrinterInfoCtr info_ctr;
2114 struct spoolss_SetPrinterInfo8 info8;
2115 union spoolss_PrinterInfo info;
2116 struct spoolss_DevmodeContainer devmode_ctr;
2117 struct sec_desc_buf secdesc_ctr;
2118 uint32_t needed;
2119 bool ret = true;
2120 NTSTATUS status;
2122 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2123 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2124 q.in.level = lvl1; \
2125 TESTGETCALL(GetPrinter, q) \
2126 info_ctr.level = lvl1; \
2127 if (lvl1 == 2) {\
2128 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2129 } else if (lvl1 == 8) {\
2130 info_ctr.info.info ## lvl1 = &info8; \
2132 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2133 devmode_ctr.devmode->field1 = value; \
2134 TESTSETCALL(SetPrinter, s) \
2135 TESTGETCALL(GetPrinter, q) \
2136 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2137 q.in.level = lvl2; \
2138 TESTGETCALL(GetPrinter, q) \
2139 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2140 } while (0)
2142 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2143 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2144 } while (0)
2146 ZERO_STRUCT(devmode_ctr);
2147 ZERO_STRUCT(secdesc_ctr);
2148 ZERO_STRUCT(info8);
2150 s.in.handle = handle;
2151 s.in.command = 0;
2152 s.in.info_ctr = &info_ctr;
2153 s.in.devmode_ctr = &devmode_ctr;
2154 s.in.secdesc_ctr = &secdesc_ctr;
2156 q.in.handle = handle;
2157 q.out.info = &info;
2158 q0 = q;
2160 #if 0
2161 const char *devicename;/* [charset(UTF16)] */
2162 enum spoolss_DeviceModeSpecVersion specversion;
2163 uint16_t driverversion;
2164 uint16_t size;
2165 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2166 uint32_t fields;
2167 #endif
2169 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2170 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2171 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2172 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2173 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2174 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2175 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2176 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2177 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2178 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2179 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2180 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2181 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2182 #if 0
2183 const char *formname;/* [charset(UTF16)] */
2184 #endif
2185 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2186 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2187 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2188 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2189 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2190 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2191 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2192 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2193 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2194 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2195 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2196 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2197 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2198 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2200 return ret;
2203 static bool call_OpenPrinterEx(struct torture_context *tctx,
2204 struct dcerpc_pipe *p,
2205 const char *name,
2206 struct spoolss_DeviceMode *devmode,
2207 struct policy_handle *handle);
2209 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2210 struct dcerpc_pipe *p,
2211 struct policy_handle *handle,
2212 const char *name)
2214 union spoolss_PrinterInfo info;
2215 struct spoolss_DeviceMode *devmode;
2216 struct spoolss_DeviceMode *devmode2;
2217 struct policy_handle handle_devmode;
2218 struct dcerpc_binding_handle *b = p->binding_handle;
2220 /* simply compare level8 and level2 devmode */
2222 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2224 devmode = info.info8.devmode;
2226 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2228 devmode2 = info.info2.devmode;
2230 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2231 "DM level 8 != DM level 2");
2234 /* set devicemode level 8 and see if it persists */
2236 devmode->copies = 93;
2237 devmode->formname = talloc_strdup(tctx, "Legal");
2239 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2241 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2243 devmode2 = info.info8.devmode;
2245 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2246 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2248 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2250 devmode2 = info.info2.devmode;
2252 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2253 "modified DM level 8 != DM level 2");
2256 /* set devicemode level 2 and see if it persists */
2258 devmode->copies = 39;
2259 devmode->formname = talloc_strdup(tctx, "Executive");
2261 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2263 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2265 devmode2 = info.info8.devmode;
2267 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2268 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2270 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2272 devmode2 = info.info2.devmode;
2274 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2275 "modified DM level 8 != DM level 2");
2278 /* check every single bit in public part of devicemode */
2280 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2281 "failed to set every single devicemode component");
2284 /* change formname upon open and see if it persists in getprinter calls */
2286 devmode->formname = talloc_strdup(tctx, "A4");
2287 devmode->copies = 42;
2289 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2290 "failed to open printer handle");
2292 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2294 devmode2 = info.info8.devmode;
2296 if (strequal(devmode->devicename, devmode2->devicename)) {
2297 torture_warning(tctx, "devicenames are the same\n");
2298 } else {
2299 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2300 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2303 if (strequal(devmode->formname, devmode2->formname)) {
2304 torture_warning(tctx, "formname are the same\n");
2305 } else {
2306 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2307 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2310 if (devmode->copies == devmode2->copies) {
2311 torture_warning(tctx, "copies are the same\n");
2312 } else {
2313 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2314 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2317 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2319 devmode2 = info.info2.devmode;
2321 if (strequal(devmode->devicename, devmode2->devicename)) {
2322 torture_warning(tctx, "devicenames are the same\n");
2323 } else {
2324 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2325 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2328 if (strequal(devmode->formname, devmode2->formname)) {
2329 torture_warning(tctx, "formname is the same\n");
2330 } else {
2331 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2332 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2335 if (devmode->copies == devmode2->copies) {
2336 torture_warning(tctx, "copies are the same\n");
2337 } else {
2338 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2339 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2342 test_ClosePrinter(tctx, b, &handle_devmode);
2344 return true;
2348 * wrapper call that saves original devmode, runs tests, and restores devmode
2351 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2352 struct dcerpc_pipe *p,
2353 struct policy_handle *handle,
2354 const char *name,
2355 struct spoolss_DeviceMode *addprinter_devmode)
2357 union spoolss_PrinterInfo info;
2358 struct spoolss_DeviceMode *devmode;
2359 bool ret = true;
2360 struct dcerpc_binding_handle *b = p->binding_handle;
2362 torture_comment(tctx, "Testing Printer Devicemodes\n");
2364 /* save original devmode */
2366 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2367 "failed to get initial global devicemode");
2369 devmode = info.info8.devmode;
2371 if (addprinter_devmode) {
2372 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2373 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2377 /* run tests */
2379 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2381 /* restore original devmode */
2383 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2384 "failed to restore initial global device mode");
2386 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2387 ret ? "succeeded" : "failed");
2390 return ret;
2393 bool test_ClosePrinter(struct torture_context *tctx,
2394 struct dcerpc_binding_handle *b,
2395 struct policy_handle *handle)
2397 NTSTATUS status;
2398 struct spoolss_ClosePrinter r;
2400 r.in.handle = handle;
2401 r.out.handle = handle;
2403 torture_comment(tctx, "Testing ClosePrinter\n");
2405 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2406 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2407 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2409 return true;
2412 static bool test_GetForm_args(struct torture_context *tctx,
2413 struct dcerpc_binding_handle *b,
2414 struct policy_handle *handle,
2415 const char *form_name,
2416 uint32_t level,
2417 union spoolss_FormInfo *info_p)
2419 NTSTATUS status;
2420 struct spoolss_GetForm r;
2421 uint32_t needed;
2423 r.in.handle = handle;
2424 r.in.form_name = form_name;
2425 r.in.level = level;
2426 r.in.buffer = NULL;
2427 r.in.offered = 0;
2428 r.out.needed = &needed;
2430 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2432 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2433 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2435 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2436 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2437 r.in.buffer = &blob;
2438 r.in.offered = needed;
2439 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2440 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2442 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2444 torture_assert(tctx, r.out.info, "No form info returned");
2447 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2449 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2451 if (info_p) {
2452 *info_p = *r.out.info;
2455 return true;
2458 static bool test_GetForm(struct torture_context *tctx,
2459 struct dcerpc_binding_handle *b,
2460 struct policy_handle *handle,
2461 const char *form_name,
2462 uint32_t level)
2464 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2467 static bool test_EnumForms(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 bool print_server,
2471 uint32_t level,
2472 uint32_t *count_p,
2473 union spoolss_FormInfo **info_p)
2475 struct spoolss_EnumForms r;
2476 uint32_t needed;
2477 uint32_t count;
2478 union spoolss_FormInfo *info;
2480 r.in.handle = handle;
2481 r.in.level = level;
2482 r.in.buffer = NULL;
2483 r.in.offered = 0;
2484 r.out.needed = &needed;
2485 r.out.count = &count;
2486 r.out.info = &info;
2488 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2490 torture_assert_ntstatus_ok(tctx,
2491 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2492 "EnumForms failed");
2494 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2495 torture_skip(tctx, "EnumForms level 2 not supported");
2498 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2499 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2502 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2503 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2504 r.in.buffer = &blob;
2505 r.in.offered = needed;
2507 torture_assert_ntstatus_ok(tctx,
2508 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2509 "EnumForms failed");
2511 torture_assert(tctx, info, "No forms returned");
2514 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2516 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2518 if (info_p) {
2519 *info_p = info;
2521 if (count_p) {
2522 *count_p = count;
2525 return true;
2528 static bool test_EnumForms_all(struct torture_context *tctx,
2529 struct dcerpc_binding_handle *b,
2530 struct policy_handle *handle,
2531 bool print_server)
2533 uint32_t levels[] = { 1, 2 };
2534 int i, j;
2536 for (i=0; i<ARRAY_SIZE(levels); i++) {
2538 uint32_t count = 0;
2539 union spoolss_FormInfo *info = NULL;
2541 torture_assert(tctx,
2542 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2543 "failed to enum forms");
2545 for (j = 0; j < count; j++) {
2546 if (!print_server) {
2547 torture_assert(tctx,
2548 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2549 "failed to get form");
2554 return true;
2557 static bool test_EnumForms_find_one(struct torture_context *tctx,
2558 struct dcerpc_binding_handle *b,
2559 struct policy_handle *handle,
2560 bool print_server,
2561 const char *form_name)
2563 union spoolss_FormInfo *info;
2564 uint32_t count;
2565 bool found = false;
2566 int i;
2568 torture_assert(tctx,
2569 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2570 "failed to enumerate forms");
2572 for (i=0; i<count; i++) {
2573 if (strequal(form_name, info[i].info1.form_name)) {
2574 found = true;
2575 break;
2579 return found;
2582 static bool test_DeleteForm(struct torture_context *tctx,
2583 struct dcerpc_binding_handle *b,
2584 struct policy_handle *handle,
2585 const char *form_name,
2586 WERROR expected_result)
2588 struct spoolss_DeleteForm r;
2590 r.in.handle = handle;
2591 r.in.form_name = form_name;
2593 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2595 torture_assert_ntstatus_ok(tctx,
2596 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2597 "DeleteForm failed");
2598 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2599 "DeleteForm gave unexpected result");
2600 if (W_ERROR_IS_OK(r.out.result)) {
2601 torture_assert_ntstatus_ok(tctx,
2602 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2603 "2nd DeleteForm failed");
2604 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2605 "2nd DeleteForm failed");
2608 return true;
2611 static bool test_AddForm(struct torture_context *tctx,
2612 struct dcerpc_binding_handle *b,
2613 struct policy_handle *handle,
2614 uint32_t level,
2615 union spoolss_AddFormInfo *info,
2616 WERROR expected_result)
2618 struct spoolss_AddForm r;
2620 if (level != 1) {
2621 torture_skip(tctx, "only level 1 supported");
2624 r.in.handle = handle;
2625 r.in.level = level;
2626 r.in.info = *info;
2628 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2629 r.in.info.info1->form_name, r.in.level,
2630 r.in.info.info1->flags);
2632 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2633 "AddForm failed");
2634 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2635 "AddForm gave unexpected result");
2637 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2638 "2nd AddForm failed");
2639 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2640 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2641 "2nd AddForm gave unexpected result");
2642 } else {
2643 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2644 "2nd AddForm gave unexpected result");
2647 return true;
2650 static bool test_SetForm(struct torture_context *tctx,
2651 struct dcerpc_binding_handle *b,
2652 struct policy_handle *handle,
2653 const char *form_name,
2654 uint32_t level,
2655 union spoolss_AddFormInfo *info)
2657 struct spoolss_SetForm r;
2659 r.in.handle = handle;
2660 r.in.form_name = form_name;
2661 r.in.level = level;
2662 r.in.info = *info;
2664 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2665 form_name, r.in.level);
2667 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2668 "SetForm failed");
2670 torture_assert_werr_ok(tctx, r.out.result,
2671 "SetForm failed");
2673 return true;
2676 static bool test_GetForm_winreg(struct torture_context *tctx,
2677 struct dcerpc_binding_handle *b,
2678 struct policy_handle *handle,
2679 const char *key_name,
2680 const char *form_name,
2681 enum winreg_Type *w_type,
2682 uint32_t *w_size,
2683 uint32_t *w_length,
2684 uint8_t **w_data);
2686 static bool test_Forms_args(struct torture_context *tctx,
2687 struct dcerpc_binding_handle *b,
2688 struct policy_handle *handle,
2689 bool print_server,
2690 const char *printer_name,
2691 struct dcerpc_binding_handle *winreg_handle,
2692 struct policy_handle *hive_handle,
2693 const char *form_name,
2694 struct spoolss_AddFormInfo1 *info1,
2695 WERROR expected_add_result,
2696 WERROR expected_delete_result)
2698 union spoolss_FormInfo info;
2699 union spoolss_AddFormInfo add_info;
2701 enum winreg_Type w_type;
2702 uint32_t w_size;
2703 uint32_t w_length;
2704 uint8_t *w_data;
2706 add_info.info1 = info1;
2708 torture_assert(tctx,
2709 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2710 "failed to add form");
2712 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2714 struct spoolss_FormInfo1 i1;
2716 torture_assert(tctx,
2717 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2718 "failed to get form via winreg");
2720 i1.size.width = IVAL(w_data, 0);
2721 i1.size.height = IVAL(w_data, 4);
2722 i1.area.left = IVAL(w_data, 8);
2723 i1.area.top = IVAL(w_data, 12);
2724 i1.area.right = IVAL(w_data, 16);
2725 i1.area.bottom = IVAL(w_data, 20);
2726 /* skip index here */
2727 i1.flags = IVAL(w_data, 28);
2729 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2730 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2731 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2732 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2733 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2734 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2735 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2736 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2737 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2738 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2741 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2742 torture_assert(tctx,
2743 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2744 "failed to get added form");
2746 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2747 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2748 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2749 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2750 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2751 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2752 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2754 if (winreg_handle && hive_handle) {
2756 struct spoolss_FormInfo1 i1;
2758 i1.size.width = IVAL(w_data, 0);
2759 i1.size.height = IVAL(w_data, 4);
2760 i1.area.left = IVAL(w_data, 8);
2761 i1.area.top = IVAL(w_data, 12);
2762 i1.area.right = IVAL(w_data, 16);
2763 i1.area.bottom = IVAL(w_data, 20);
2764 /* skip index here */
2765 i1.flags = IVAL(w_data, 28);
2767 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2768 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2769 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2770 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2771 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2772 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2773 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2776 add_info.info1->size.width = 1234;
2778 torture_assert(tctx,
2779 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2780 "failed to set form");
2781 torture_assert(tctx,
2782 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2783 "failed to get setted form");
2785 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2788 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2789 torture_assert(tctx,
2790 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2791 "Newly added form not found in enum call");
2794 torture_assert(tctx,
2795 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2796 "failed to delete form");
2798 return true;
2801 static bool test_Forms(struct torture_context *tctx,
2802 struct dcerpc_binding_handle *b,
2803 struct policy_handle *handle,
2804 bool print_server,
2805 const char *printer_name,
2806 struct dcerpc_binding_handle *winreg_handle,
2807 struct policy_handle *hive_handle)
2809 const struct spoolss_FormSize size = {
2810 .width = 50,
2811 .height = 25
2813 const struct spoolss_FormArea area = {
2814 .left = 5,
2815 .top = 10,
2816 .right = 45,
2817 .bottom = 15
2819 int i;
2821 struct {
2822 struct spoolss_AddFormInfo1 info1;
2823 WERROR expected_add_result;
2824 WERROR expected_delete_result;
2825 } forms[] = {
2827 .info1 = {
2828 .flags = SPOOLSS_FORM_USER,
2829 .form_name = "testform_user",
2830 .size = size,
2831 .area = area,
2833 .expected_add_result = WERR_OK,
2834 .expected_delete_result = WERR_OK
2837 weird, we can add a builtin form but we can never remove it
2838 again - gd
2841 .info1 = {
2842 .flags = SPOOLSS_FORM_BUILTIN,
2843 .form_name = "testform_builtin",
2844 .size = size,
2845 .area = area,
2847 .expected_add_result = WERR_OK,
2848 .expected_delete_result = WERR_INVALID_PARAM,
2852 .info1 = {
2853 .flags = SPOOLSS_FORM_PRINTER,
2854 .form_name = "testform_printer",
2855 .size = size,
2856 .area = area,
2858 .expected_add_result = WERR_OK,
2859 .expected_delete_result = WERR_OK
2862 .info1 = {
2863 .flags = SPOOLSS_FORM_USER,
2864 .form_name = "Letter",
2865 .size = size,
2866 .area = area,
2868 .expected_add_result = WERR_FILE_EXISTS,
2869 .expected_delete_result = WERR_INVALID_PARAM
2872 .info1 = {
2873 .flags = SPOOLSS_FORM_BUILTIN,
2874 .form_name = "Letter",
2875 .size = size,
2876 .area = area,
2878 .expected_add_result = WERR_FILE_EXISTS,
2879 .expected_delete_result = WERR_INVALID_PARAM
2882 .info1 = {
2883 .flags = SPOOLSS_FORM_PRINTER,
2884 .form_name = "Letter",
2885 .size = size,
2886 .area = area,
2888 .expected_add_result = WERR_FILE_EXISTS,
2889 .expected_delete_result = WERR_INVALID_PARAM
2892 .info1 = {
2893 .flags = 12345,
2894 .form_name = "invalid_flags",
2895 .size = size,
2896 .area = area,
2898 .expected_add_result = WERR_INVALID_PARAM,
2899 .expected_delete_result = WERR_INVALID_FORM_NAME
2904 for (i=0; i < ARRAY_SIZE(forms); i++) {
2905 torture_assert(tctx,
2906 test_Forms_args(tctx, b, handle, print_server, printer_name,
2907 winreg_handle, hive_handle,
2908 forms[i].info1.form_name,
2909 &forms[i].info1,
2910 forms[i].expected_add_result,
2911 forms[i].expected_delete_result),
2912 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2915 return true;
2918 static bool test_EnumPorts_old(struct torture_context *tctx,
2919 void *private_data)
2921 struct test_spoolss_context *ctx =
2922 talloc_get_type_abort(private_data, struct test_spoolss_context);
2924 NTSTATUS status;
2925 struct spoolss_EnumPorts r;
2926 uint32_t needed;
2927 uint32_t count;
2928 union spoolss_PortInfo *info;
2929 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2930 struct dcerpc_binding_handle *b = p->binding_handle;
2932 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2933 dcerpc_server_name(p));
2934 r.in.level = 2;
2935 r.in.buffer = NULL;
2936 r.in.offered = 0;
2937 r.out.needed = &needed;
2938 r.out.count = &count;
2939 r.out.info = &info;
2941 torture_comment(tctx, "Testing EnumPorts\n");
2943 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2945 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2947 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2948 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2949 r.in.buffer = &blob;
2950 r.in.offered = needed;
2952 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2953 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2954 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2956 torture_assert(tctx, info, "No ports returned");
2959 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2961 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
2963 return true;
2966 static bool test_AddPort(struct torture_context *tctx,
2967 void *private_data)
2969 struct test_spoolss_context *ctx =
2970 talloc_get_type_abort(private_data, struct test_spoolss_context);
2972 NTSTATUS status;
2973 struct spoolss_AddPort r;
2974 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2975 struct dcerpc_binding_handle *b = p->binding_handle;
2977 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2978 dcerpc_server_name(p));
2979 r.in.unknown = 0;
2980 r.in.monitor_name = "foo";
2982 torture_comment(tctx, "Testing AddPort\n");
2984 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2986 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2988 /* win2k3 returns WERR_NOT_SUPPORTED */
2990 #if 0
2992 if (!W_ERROR_IS_OK(r.out.result)) {
2993 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2994 return false;
2997 #endif
2999 return true;
3002 static bool test_GetJob_args(struct torture_context *tctx,
3003 struct dcerpc_binding_handle *b,
3004 struct policy_handle *handle,
3005 uint32_t job_id,
3006 uint32_t level,
3007 union spoolss_JobInfo *info_p)
3009 NTSTATUS status;
3010 struct spoolss_GetJob r;
3011 union spoolss_JobInfo info;
3012 uint32_t needed;
3014 r.in.handle = handle;
3015 r.in.job_id = job_id;
3016 r.in.level = level;
3017 r.in.buffer = NULL;
3018 r.in.offered = 0;
3019 r.out.needed = &needed;
3020 r.out.info = &info;
3022 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3024 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3025 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3026 if (level == 0) {
3027 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3030 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3031 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3032 r.in.buffer = &blob;
3033 r.in.offered = needed;
3035 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3036 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3039 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3040 torture_assert(tctx, r.out.info, "No job info returned");
3042 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3044 if (info_p) {
3045 *info_p = *r.out.info;
3048 return true;
3051 static bool test_GetJob(struct torture_context *tctx,
3052 struct dcerpc_binding_handle *b,
3053 struct policy_handle *handle,
3054 uint32_t job_id)
3056 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3057 uint32_t i;
3059 for (i=0; i < ARRAY_SIZE(levels); i++) {
3060 torture_assert(tctx,
3061 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3062 "GetJob failed");
3065 return true;
3068 static bool test_SetJob(struct torture_context *tctx,
3069 struct dcerpc_binding_handle *b,
3070 struct policy_handle *handle,
3071 uint32_t job_id,
3072 struct spoolss_JobInfoContainer *ctr,
3073 enum spoolss_JobControl command)
3075 NTSTATUS status;
3076 struct spoolss_SetJob r;
3078 r.in.handle = handle;
3079 r.in.job_id = job_id;
3080 r.in.ctr = ctr;
3081 r.in.command = command;
3083 switch (command) {
3084 case SPOOLSS_JOB_CONTROL_PAUSE:
3085 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3086 break;
3087 case SPOOLSS_JOB_CONTROL_RESUME:
3088 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3089 break;
3090 case SPOOLSS_JOB_CONTROL_CANCEL:
3091 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3092 break;
3093 case SPOOLSS_JOB_CONTROL_RESTART:
3094 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3095 break;
3096 case SPOOLSS_JOB_CONTROL_DELETE:
3097 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3098 break;
3099 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3100 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3101 break;
3102 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3103 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3104 break;
3105 case SPOOLSS_JOB_CONTROL_RETAIN:
3106 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3107 break;
3108 case SPOOLSS_JOB_CONTROL_RELEASE:
3109 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3110 break;
3111 default:
3112 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3113 break;
3116 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3117 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3118 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3120 return true;
3123 static bool test_AddJob(struct torture_context *tctx,
3124 struct dcerpc_binding_handle *b,
3125 struct policy_handle *handle)
3127 NTSTATUS status;
3128 struct spoolss_AddJob r;
3129 uint32_t needed;
3131 r.in.level = 0;
3132 r.in.handle = handle;
3133 r.in.offered = 0;
3134 r.out.needed = &needed;
3135 r.in.buffer = r.out.buffer = NULL;
3137 torture_comment(tctx, "Testing AddJob\n");
3139 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3140 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3142 r.in.level = 1;
3144 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3145 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3147 return true;
3151 static bool test_EnumJobs_args(struct torture_context *tctx,
3152 struct dcerpc_binding_handle *b,
3153 struct policy_handle *handle,
3154 uint32_t level,
3155 uint32_t *count_p,
3156 union spoolss_JobInfo **info_p)
3158 NTSTATUS status;
3159 struct spoolss_EnumJobs r;
3160 uint32_t needed;
3161 uint32_t count;
3162 union spoolss_JobInfo *info;
3164 r.in.handle = handle;
3165 r.in.firstjob = 0;
3166 r.in.numjobs = 0xffffffff;
3167 r.in.level = level;
3168 r.in.buffer = NULL;
3169 r.in.offered = 0;
3170 r.out.needed = &needed;
3171 r.out.count = &count;
3172 r.out.info = &info;
3174 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3176 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3178 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3180 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3181 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3182 r.in.buffer = &blob;
3183 r.in.offered = needed;
3185 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3187 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3188 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3189 torture_assert(tctx, info, "No jobs returned");
3191 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3193 } else {
3194 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3197 if (count_p) {
3198 *count_p = count;
3200 if (info_p) {
3201 *info_p = info;
3204 return true;
3207 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3208 struct dcerpc_binding_handle *b,
3209 struct policy_handle *handle,
3210 uint32_t *job_id)
3212 NTSTATUS status;
3213 struct spoolss_StartDocPrinter s;
3214 struct spoolss_DocumentInfo1 info1;
3215 struct spoolss_StartPagePrinter sp;
3216 struct spoolss_WritePrinter w;
3217 struct spoolss_EndPagePrinter ep;
3218 struct spoolss_EndDocPrinter e;
3219 int i;
3220 uint32_t num_written;
3222 torture_comment(tctx, "Testing StartDocPrinter\n");
3224 s.in.handle = handle;
3225 s.in.level = 1;
3226 s.in.info.info1 = &info1;
3227 s.out.job_id = job_id;
3228 info1.document_name = "TorturePrintJob";
3229 info1.output_file = NULL;
3230 info1.datatype = "RAW";
3232 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3233 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3234 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3236 for (i=1; i < 4; i++) {
3237 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3239 sp.in.handle = handle;
3241 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3242 torture_assert_ntstatus_ok(tctx, status,
3243 "dcerpc_spoolss_StartPagePrinter failed");
3244 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3246 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3248 w.in.handle = handle;
3249 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3250 w.out.num_written = &num_written;
3252 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3253 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3254 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3256 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3258 ep.in.handle = handle;
3260 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3261 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3262 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3265 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3267 e.in.handle = handle;
3269 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3270 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3271 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3273 return true;
3276 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3277 struct dcerpc_binding_handle *b,
3278 struct policy_handle *handle,
3279 uint32_t num_jobs,
3280 uint32_t *job_ids)
3282 uint32_t count;
3283 union spoolss_JobInfo *info = NULL;
3284 int i;
3286 torture_assert(tctx,
3287 test_AddJob(tctx, b, handle),
3288 "AddJob failed");
3290 torture_assert(tctx,
3291 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3292 "EnumJobs level 1 failed");
3294 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3296 for (i=0; i < num_jobs; i++) {
3297 union spoolss_JobInfo ginfo;
3298 const char *document_name;
3299 const char *new_document_name = "any_other_docname";
3300 struct spoolss_JobInfoContainer ctr;
3301 struct spoolss_SetJobInfo1 info1;
3303 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3305 torture_assert(tctx,
3306 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3307 "failed to call test_GetJob");
3309 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3311 document_name = ginfo.info1.document_name;
3313 info1.job_id = ginfo.info1.job_id;
3314 info1.printer_name = ginfo.info1.printer_name;
3315 info1.server_name = ginfo.info1.server_name;
3316 info1.user_name = ginfo.info1.user_name;
3317 info1.document_name = new_document_name;
3318 info1.data_type = ginfo.info1.data_type;
3319 info1.text_status = ginfo.info1.text_status;
3320 info1.status = ginfo.info1.status;
3321 info1.priority = ginfo.info1.priority;
3322 info1.position = ginfo.info1.position;
3323 info1.total_pages = ginfo.info1.total_pages;
3324 info1.pages_printed = ginfo.info1.pages_printed;
3325 info1.submitted = ginfo.info1.submitted;
3327 ctr.level = 1;
3328 ctr.info.info1 = &info1;
3330 torture_assert(tctx,
3331 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3332 "failed to call test_SetJob level 1");
3334 torture_assert(tctx,
3335 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3336 "failed to call test_GetJob");
3338 if (strequal(ginfo.info1.document_name, document_name)) {
3339 torture_warning(tctx,
3340 "document_name did *NOT* change from '%s' to '%s'\n",
3341 document_name, new_document_name);
3345 for (i=0; i < num_jobs; i++) {
3346 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3347 torture_warning(tctx, "failed to pause printjob\n");
3349 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3350 torture_warning(tctx, "failed to resume printjob\n");
3354 return true;
3357 static bool test_DoPrintTest(struct torture_context *tctx,
3358 struct dcerpc_binding_handle *b,
3359 struct policy_handle *handle)
3361 bool ret = true;
3362 uint32_t num_jobs = 8;
3363 uint32_t *job_ids;
3364 int i;
3366 torture_comment(tctx, "Testing real print operations\n");
3368 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3370 for (i=0; i < num_jobs; i++) {
3371 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3374 for (i=0; i < num_jobs; i++) {
3375 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3378 if (ret == true) {
3379 torture_comment(tctx, "real print operations test succeeded\n\n");
3382 return ret;
3385 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3386 struct dcerpc_binding_handle *b,
3387 struct policy_handle *handle)
3389 bool ret = true;
3390 uint32_t num_jobs = 8;
3391 uint32_t *job_ids;
3392 int i;
3393 torture_comment(tctx, "Testing real print operations (extended)\n");
3395 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3397 for (i=0; i < num_jobs; i++) {
3398 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3401 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3403 for (i=0; i < num_jobs; i++) {
3404 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3407 if (ret == true) {
3408 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3411 return ret;
3414 static bool test_PausePrinter(struct torture_context *tctx,
3415 struct dcerpc_binding_handle *b,
3416 struct policy_handle *handle)
3418 NTSTATUS status;
3419 struct spoolss_SetPrinter r;
3420 struct spoolss_SetPrinterInfoCtr info_ctr;
3421 struct spoolss_DevmodeContainer devmode_ctr;
3422 struct sec_desc_buf secdesc_ctr;
3424 info_ctr.level = 0;
3425 info_ctr.info.info0 = NULL;
3427 ZERO_STRUCT(devmode_ctr);
3428 ZERO_STRUCT(secdesc_ctr);
3430 r.in.handle = handle;
3431 r.in.info_ctr = &info_ctr;
3432 r.in.devmode_ctr = &devmode_ctr;
3433 r.in.secdesc_ctr = &secdesc_ctr;
3434 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3436 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3438 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3440 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3442 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3444 return true;
3447 static bool test_ResumePrinter(struct torture_context *tctx,
3448 struct dcerpc_binding_handle *b,
3449 struct policy_handle *handle)
3451 NTSTATUS status;
3452 struct spoolss_SetPrinter r;
3453 struct spoolss_SetPrinterInfoCtr info_ctr;
3454 struct spoolss_DevmodeContainer devmode_ctr;
3455 struct sec_desc_buf secdesc_ctr;
3457 info_ctr.level = 0;
3458 info_ctr.info.info0 = NULL;
3460 ZERO_STRUCT(devmode_ctr);
3461 ZERO_STRUCT(secdesc_ctr);
3463 r.in.handle = handle;
3464 r.in.info_ctr = &info_ctr;
3465 r.in.devmode_ctr = &devmode_ctr;
3466 r.in.secdesc_ctr = &secdesc_ctr;
3467 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3469 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3471 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3473 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3475 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3477 return true;
3480 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3481 struct dcerpc_binding_handle *b,
3482 struct policy_handle *handle,
3483 const char *value_name,
3484 enum winreg_Type *expected_type,
3485 enum winreg_Type *type_p,
3486 uint8_t **data_p,
3487 uint32_t *needed_p)
3489 NTSTATUS status;
3490 struct spoolss_GetPrinterData r;
3491 uint32_t needed;
3492 enum winreg_Type type;
3493 union spoolss_PrinterData data;
3495 r.in.handle = handle;
3496 r.in.value_name = value_name;
3497 r.in.offered = 0;
3498 r.out.needed = &needed;
3499 r.out.type = &type;
3500 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3502 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3504 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3505 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3507 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3508 if (expected_type) {
3509 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3511 r.in.offered = needed;
3512 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3513 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3514 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3517 torture_assert_werr_ok(tctx, r.out.result,
3518 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3520 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3522 if (type_p) {
3523 *type_p = type;
3526 if (data_p) {
3527 *data_p = r.out.data;
3530 if (needed_p) {
3531 *needed_p = needed;
3534 return true;
3537 static bool test_GetPrinterData(struct torture_context *tctx,
3538 struct dcerpc_binding_handle *b,
3539 struct policy_handle *handle,
3540 const char *value_name,
3541 enum winreg_Type *type_p,
3542 uint8_t **data_p,
3543 uint32_t *needed_p)
3545 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3546 NULL, type_p, data_p, needed_p);
3549 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3550 struct dcerpc_pipe *p,
3551 struct policy_handle *handle,
3552 const char *key_name,
3553 const char *value_name,
3554 enum winreg_Type *expected_type,
3555 enum winreg_Type *type_p,
3556 uint8_t **data_p,
3557 uint32_t *needed_p)
3559 NTSTATUS status;
3560 struct spoolss_GetPrinterDataEx r;
3561 enum winreg_Type type;
3562 uint32_t needed;
3563 union spoolss_PrinterData data;
3564 struct dcerpc_binding_handle *b = p->binding_handle;
3566 r.in.handle = handle;
3567 r.in.key_name = key_name;
3568 r.in.value_name = value_name;
3569 r.in.offered = 0;
3570 r.out.type = &type;
3571 r.out.needed = &needed;
3572 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3574 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3575 r.in.key_name, r.in.value_name);
3577 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3580 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3582 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3585 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3586 if (expected_type) {
3587 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3589 r.in.offered = needed;
3590 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3591 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3592 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3595 torture_assert_werr_ok(tctx, r.out.result,
3596 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3598 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3600 if (type_p) {
3601 *type_p = type;
3604 if (data_p) {
3605 *data_p = r.out.data;
3608 if (needed_p) {
3609 *needed_p = needed;
3612 return true;
3615 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3616 struct dcerpc_pipe *p,
3617 struct policy_handle *handle,
3618 const char *key_name,
3619 const char *value_name,
3620 enum winreg_Type *type_p,
3621 uint8_t **data_p,
3622 uint32_t *needed_p)
3624 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3625 NULL, type_p, data_p, needed_p);
3628 static bool test_get_environment(struct torture_context *tctx,
3629 struct dcerpc_binding_handle *b,
3630 struct policy_handle *handle,
3631 const char **architecture)
3633 DATA_BLOB blob;
3634 enum winreg_Type type;
3635 uint8_t *data;
3636 uint32_t needed;
3638 torture_assert(tctx,
3639 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3640 "failed to get Architecture");
3642 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3644 blob = data_blob_const(data, needed);
3645 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3647 return true;
3650 static bool test_GetPrinterData_list(struct torture_context *tctx,
3651 void *private_data)
3653 struct test_spoolss_context *ctx =
3654 talloc_get_type_abort(private_data, struct test_spoolss_context);
3655 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3656 struct dcerpc_binding_handle *b = p->binding_handle;
3657 const char *list[] = {
3658 "W3SvcInstalled",
3659 "BeepEnabled",
3660 "EventLog",
3661 /* "NetPopup", not on w2k8 */
3662 /* "NetPopupToComputer", not on w2k8 */
3663 "MajorVersion",
3664 "MinorVersion",
3665 "DefaultSpoolDirectory",
3666 "Architecture",
3667 "DsPresent",
3668 "OSVersion",
3669 /* "OSVersionEx", not on s3 */
3670 "DNSMachineName"
3672 int i;
3674 for (i=0; i < ARRAY_SIZE(list); i++) {
3675 enum winreg_Type type, type_ex;
3676 uint8_t *data, *data_ex;
3677 uint32_t needed, needed_ex;
3679 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3680 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3681 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3682 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3683 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3684 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3685 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3688 return true;
3691 static bool test_EnumPrinterData(struct torture_context *tctx,
3692 struct dcerpc_pipe *p,
3693 struct policy_handle *handle,
3694 uint32_t enum_index,
3695 uint32_t value_offered,
3696 uint32_t data_offered,
3697 enum winreg_Type *type_p,
3698 uint32_t *value_needed_p,
3699 uint32_t *data_needed_p,
3700 const char **value_name_p,
3701 uint8_t **data_p,
3702 WERROR *result_p)
3704 struct spoolss_EnumPrinterData r;
3705 uint32_t data_needed;
3706 uint32_t value_needed;
3707 enum winreg_Type type;
3708 struct dcerpc_binding_handle *b = p->binding_handle;
3710 r.in.handle = handle;
3711 r.in.enum_index = enum_index;
3712 r.in.value_offered = value_offered;
3713 r.in.data_offered = data_offered;
3714 r.out.data_needed = &data_needed;
3715 r.out.value_needed = &value_needed;
3716 r.out.type = &type;
3717 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3718 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3720 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3722 torture_assert_ntstatus_ok(tctx,
3723 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3724 "EnumPrinterData failed");
3726 if (type_p) {
3727 *type_p = type;
3729 if (value_needed_p) {
3730 *value_needed_p = value_needed;
3732 if (data_needed_p) {
3733 *data_needed_p = data_needed;
3735 if (value_name_p) {
3736 *value_name_p = r.out.value_name;
3738 if (data_p) {
3739 *data_p = r.out.data;
3741 if (result_p) {
3742 *result_p = r.out.result;
3745 return true;
3749 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3750 struct dcerpc_pipe *p,
3751 struct policy_handle *handle)
3753 uint32_t enum_index = 0;
3754 enum winreg_Type type;
3755 uint32_t value_needed;
3756 uint32_t data_needed;
3757 uint8_t *data;
3758 const char *value_name;
3759 WERROR result;
3761 torture_comment(tctx, "Testing EnumPrinterData\n");
3763 do {
3764 torture_assert(tctx,
3765 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3766 &type, &value_needed, &data_needed,
3767 &value_name, &data, &result),
3768 "EnumPrinterData failed");
3770 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3771 break;
3774 torture_assert(tctx,
3775 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3776 &type, &value_needed, &data_needed,
3777 &value_name, &data, &result),
3778 "EnumPrinterData failed");
3780 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3781 break;
3784 enum_index++;
3786 } while (W_ERROR_IS_OK(result));
3788 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3790 return true;
3793 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3794 struct dcerpc_binding_handle *b,
3795 struct policy_handle *handle,
3796 const char *key_name,
3797 uint32_t *count_p,
3798 struct spoolss_PrinterEnumValues **info_p)
3800 struct spoolss_EnumPrinterDataEx r;
3801 struct spoolss_PrinterEnumValues *info;
3802 uint32_t needed;
3803 uint32_t count;
3805 r.in.handle = handle;
3806 r.in.key_name = key_name;
3807 r.in.offered = 0;
3808 r.out.needed = &needed;
3809 r.out.count = &count;
3810 r.out.info = &info;
3812 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3814 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3815 "EnumPrinterDataEx failed");
3816 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3817 r.in.offered = needed;
3818 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3819 "EnumPrinterDataEx failed");
3822 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3824 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3826 if (count_p) {
3827 *count_p = count;
3829 if (info_p) {
3830 *info_p = info;
3833 return true;
3836 static bool test_SetPrinterData(struct torture_context *tctx,
3837 struct dcerpc_binding_handle *b,
3838 struct policy_handle *handle,
3839 const char *value_name,
3840 enum winreg_Type type,
3841 uint8_t *data,
3842 uint32_t offered);
3843 static bool test_DeletePrinterData(struct torture_context *tctx,
3844 struct dcerpc_binding_handle *b,
3845 struct policy_handle *handle,
3846 const char *value_name);
3848 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3849 struct dcerpc_pipe *p,
3850 struct policy_handle *handle)
3852 uint32_t count;
3853 struct spoolss_PrinterEnumValues *info;
3854 int i;
3855 uint32_t value_needed, data_needed;
3856 uint32_t value_offered, data_offered;
3857 WERROR result;
3858 struct dcerpc_binding_handle *b = p->binding_handle;
3860 enum winreg_Type type;
3861 DATA_BLOB blob;
3863 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3865 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3866 type = REG_SZ;
3868 torture_assert(tctx,
3869 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3870 "SetPrinterData failed");
3872 blob = data_blob_string_const("torture_data2");
3874 torture_assert(tctx,
3875 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3876 "SetPrinterData failed");
3878 blob = data_blob_talloc(tctx, NULL, 4);
3879 SIVAL(blob.data, 0, 0x11223344);
3881 torture_assert(tctx,
3882 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3883 "SetPrinterData failed");
3885 torture_assert(tctx,
3886 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3887 "failed to call EnumPrinterDataEx");
3889 /* get the max sizes for value and data */
3891 torture_assert(tctx,
3892 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3893 NULL, &value_needed, &data_needed,
3894 NULL, NULL, &result),
3895 "EnumPrinterData failed");
3896 torture_assert_werr_ok(tctx, result, "unexpected result");
3898 /* check if the reply from the EnumPrinterData really matches max values */
3900 for (i=0; i < count; i++) {
3901 if (info[i].value_name_len > value_needed) {
3902 torture_fail(tctx,
3903 talloc_asprintf(tctx,
3904 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3905 info[i].value_name_len, value_needed));
3907 if (info[i].data_length > data_needed) {
3908 torture_fail(tctx,
3909 talloc_asprintf(tctx,
3910 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3911 info[i].data_length, data_needed));
3915 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3916 * sort or not sort the replies by value name, we should be able to do
3917 * the following entry comparison */
3919 data_offered = data_needed;
3920 value_offered = value_needed;
3922 for (i=0; i < count; i++) {
3924 const char *value_name;
3925 uint8_t *data;
3927 torture_assert(tctx,
3928 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3929 &type, &value_needed, &data_needed,
3930 &value_name, &data, &result),
3931 "EnumPrinterData failed");
3933 if (i -1 == count) {
3934 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3935 "unexpected result");
3936 break;
3937 } else {
3938 torture_assert_werr_ok(tctx, result, "unexpected result");
3941 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3942 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3943 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3944 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3945 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3948 torture_assert(tctx,
3949 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3950 "DeletePrinterData failed");
3951 torture_assert(tctx,
3952 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3953 "DeletePrinterData failed");
3954 torture_assert(tctx,
3955 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3956 "DeletePrinterData failed");
3958 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3960 return true;
3963 static bool test_DeletePrinterData(struct torture_context *tctx,
3964 struct dcerpc_binding_handle *b,
3965 struct policy_handle *handle,
3966 const char *value_name)
3968 NTSTATUS status;
3969 struct spoolss_DeletePrinterData r;
3971 r.in.handle = handle;
3972 r.in.value_name = value_name;
3974 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3975 r.in.value_name);
3977 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3979 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3980 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3982 return true;
3985 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3986 struct dcerpc_binding_handle *b,
3987 struct policy_handle *handle,
3988 const char *key_name,
3989 const char *value_name)
3991 struct spoolss_DeletePrinterDataEx r;
3993 r.in.handle = handle;
3994 r.in.key_name = key_name;
3995 r.in.value_name = value_name;
3997 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3998 r.in.key_name, r.in.value_name);
4000 torture_assert_ntstatus_ok(tctx,
4001 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4002 "DeletePrinterDataEx failed");
4003 torture_assert_werr_ok(tctx, r.out.result,
4004 "DeletePrinterDataEx failed");
4006 return true;
4009 static bool test_DeletePrinterKey(struct torture_context *tctx,
4010 struct dcerpc_binding_handle *b,
4011 struct policy_handle *handle,
4012 const char *key_name)
4014 struct spoolss_DeletePrinterKey r;
4016 r.in.handle = handle;
4017 r.in.key_name = key_name;
4019 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4021 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4022 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4023 return true;
4026 torture_assert_ntstatus_ok(tctx,
4027 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4028 "DeletePrinterKey failed");
4029 torture_assert_werr_ok(tctx, r.out.result,
4030 "DeletePrinterKey failed");
4032 return true;
4035 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4036 struct dcerpc_binding_handle *b,
4037 struct policy_handle *handle)
4039 struct winreg_OpenHKLM r;
4041 r.in.system_name = NULL;
4042 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4043 r.out.handle = handle;
4045 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4047 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4048 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4050 return true;
4053 static void init_winreg_String(struct winreg_String *name, const char *s)
4055 name->name = s;
4056 if (s) {
4057 name->name_len = 2 * (strlen_m(s) + 1);
4058 name->name_size = name->name_len;
4059 } else {
4060 name->name_len = 0;
4061 name->name_size = 0;
4065 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4066 struct dcerpc_binding_handle *b,
4067 struct policy_handle *hive_handle,
4068 const char *keyname,
4069 uint32_t options,
4070 struct policy_handle *key_handle)
4072 struct winreg_OpenKey r;
4074 r.in.parent_handle = hive_handle;
4075 init_winreg_String(&r.in.keyname, keyname);
4076 r.in.options = options;
4077 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4078 r.out.handle = key_handle;
4080 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4082 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4083 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4085 return true;
4088 static bool test_winreg_OpenKey(struct torture_context *tctx,
4089 struct dcerpc_binding_handle *b,
4090 struct policy_handle *hive_handle,
4091 const char *keyname,
4092 struct policy_handle *key_handle)
4094 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4095 REG_OPTION_NON_VOLATILE, key_handle);
4098 static bool test_winreg_CloseKey(struct torture_context *tctx,
4099 struct dcerpc_binding_handle *b,
4100 struct policy_handle *handle)
4102 struct winreg_CloseKey r;
4104 r.in.handle = handle;
4105 r.out.handle = handle;
4107 torture_comment(tctx, "Testing winreg_CloseKey\n");
4109 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4110 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4112 return true;
4115 bool test_winreg_QueryValue(struct torture_context *tctx,
4116 struct dcerpc_binding_handle *b,
4117 struct policy_handle *handle,
4118 const char *value_name,
4119 enum winreg_Type *type_p,
4120 uint32_t *data_size_p,
4121 uint32_t *data_length_p,
4122 uint8_t **data_p)
4124 struct winreg_QueryValue r;
4125 enum winreg_Type type = REG_NONE;
4126 uint32_t data_size = 0;
4127 uint32_t data_length = 0;
4128 struct winreg_String valuename;
4129 uint8_t *data = NULL;
4131 init_winreg_String(&valuename, value_name);
4133 data = talloc_zero_array(tctx, uint8_t, 0);
4135 r.in.handle = handle;
4136 r.in.value_name = &valuename;
4137 r.in.type = &type;
4138 r.in.data_size = &data_size;
4139 r.in.data_length = &data_length;
4140 r.in.data = data;
4141 r.out.type = &type;
4142 r.out.data = data;
4143 r.out.data_size = &data_size;
4144 r.out.data_length = &data_length;
4146 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4148 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4149 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4150 *r.in.data_size = *r.out.data_size;
4151 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4152 r.in.data = data;
4153 r.out.data = data;
4154 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4156 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4158 if (type_p) {
4159 *type_p = *r.out.type;
4161 if (data_size_p) {
4162 *data_size_p = *r.out.data_size;
4164 if (data_length_p) {
4165 *data_length_p = *r.out.data_length;
4167 if (data_p) {
4168 *data_p = r.out.data;
4171 return true;
4174 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4175 struct dcerpc_binding_handle *b,
4176 struct policy_handle *handle,
4177 const char *printer_name,
4178 const char *key_name,
4179 const char *value_name,
4180 enum winreg_Type *w_type,
4181 uint32_t *w_size,
4182 uint32_t *w_length,
4183 uint8_t **w_data)
4185 const char *printer_key;
4186 struct policy_handle key_handle;
4188 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4189 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4191 torture_assert(tctx,
4192 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4194 torture_assert(tctx,
4195 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4197 torture_assert(tctx,
4198 test_winreg_CloseKey(tctx, b, &key_handle), "");
4200 return true;
4203 static bool test_GetForm_winreg(struct torture_context *tctx,
4204 struct dcerpc_binding_handle *b,
4205 struct policy_handle *handle,
4206 const char *key_name,
4207 const char *form_name,
4208 enum winreg_Type *w_type,
4209 uint32_t *w_size,
4210 uint32_t *w_length,
4211 uint8_t **w_data)
4213 struct policy_handle key_handle;
4215 torture_assert(tctx,
4216 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4218 torture_assert(tctx,
4219 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4221 torture_assert(tctx,
4222 test_winreg_CloseKey(tctx, b, &key_handle), "");
4224 return true;
4227 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4228 struct dcerpc_binding_handle *b,
4229 struct policy_handle *handle,
4230 const char *symlink_keyname,
4231 const char *symlink_destination)
4233 /* check if the first key is a symlink to the second key */
4235 enum winreg_Type w_type;
4236 uint32_t w_size;
4237 uint32_t w_length;
4238 uint8_t *w_data;
4239 struct policy_handle key_handle;
4240 DATA_BLOB blob;
4241 const char *str;
4243 if (torture_setting_bool(tctx, "samba3", false)) {
4244 torture_skip(tctx, "skip winreg symlink test against samba");
4247 torture_assert(tctx,
4248 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4249 "failed to open key link");
4251 torture_assert(tctx,
4252 test_winreg_QueryValue(tctx, b, &key_handle,
4253 "SymbolicLinkValue",
4254 &w_type, &w_size, &w_length, &w_data),
4255 "failed to query for 'SymbolicLinkValue' attribute");
4257 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4259 blob = data_blob(w_data, w_size);
4260 str = reg_val_data_string(tctx, REG_SZ, blob);
4262 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4264 torture_assert(tctx,
4265 test_winreg_CloseKey(tctx, b, &key_handle),
4266 "failed to close key link");
4268 return true;
4271 static const char *strip_unc(const char *unc)
4273 char *name;
4275 if (!unc) {
4276 return NULL;
4279 if (unc[0] == '\\' && unc[1] == '\\') {
4280 unc +=2;
4283 name = strchr(unc, '\\');
4284 if (name) {
4285 return name+1;
4288 return unc;
4291 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4292 struct dcerpc_binding_handle *b,
4293 struct policy_handle *handle,
4294 const char *printer_name,
4295 struct dcerpc_binding_handle *winreg_handle,
4296 struct policy_handle *hive_handle)
4298 union spoolss_PrinterInfo info;
4299 const char *keys[] = {
4300 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4301 TOP_LEVEL_PRINT_PRINTERS_KEY
4303 int i;
4304 const char *printername, *sharename;
4306 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4308 torture_assert(tctx,
4309 test_GetPrinter_level(tctx, b, handle, 2, &info),
4310 "failed to get printer info level 2");
4312 printername = strip_unc(info.info2.printername);
4313 sharename = strip_unc(info.info2.sharename);
4315 #define test_sz(wname, iname) \
4316 do {\
4317 DATA_BLOB blob;\
4318 const char *str;\
4319 enum winreg_Type w_type;\
4320 uint32_t w_size;\
4321 uint32_t w_length;\
4322 uint8_t *w_data;\
4323 torture_assert(tctx,\
4324 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4325 &w_type, &w_size, &w_length, &w_data),\
4326 "failed to query winreg");\
4327 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4328 blob = data_blob(w_data, w_size);\
4329 str = reg_val_data_string(tctx, REG_SZ, blob);\
4330 if (w_size == 2 && iname == NULL) {\
4331 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4332 } else {\
4333 torture_assert_str_equal(tctx, str, iname,\
4334 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4336 } while(0);
4338 #define test_dword(wname, iname) \
4339 do {\
4340 uint32_t value;\
4341 enum winreg_Type w_type;\
4342 uint32_t w_size;\
4343 uint32_t w_length;\
4344 uint8_t *w_data;\
4345 torture_assert(tctx,\
4346 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4347 &w_type, &w_size, &w_length, &w_data),\
4348 "failed to query winreg");\
4349 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4350 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4351 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4352 value = IVAL(w_data, 0);\
4353 torture_assert_int_equal(tctx, value, iname,\
4354 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4355 } while(0);
4357 #define test_dm(wname, iname) \
4358 do {\
4359 DATA_BLOB blob;\
4360 struct spoolss_DeviceMode dm;\
4361 enum ndr_err_code ndr_err;\
4362 enum winreg_Type w_type;\
4363 uint32_t w_size;\
4364 uint32_t w_length;\
4365 uint8_t *w_data;\
4366 torture_assert(tctx,\
4367 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4368 &w_type, &w_size, &w_length, &w_data),\
4369 "failed to query winreg");\
4370 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4371 blob = data_blob(w_data, w_size);\
4372 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4373 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4374 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4375 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4376 "dm unequal");\
4377 } while(0);
4379 #define test_sd(wname, iname) \
4380 do {\
4381 DATA_BLOB blob;\
4382 struct security_descriptor sd;\
4383 enum ndr_err_code ndr_err;\
4384 enum winreg_Type w_type;\
4385 uint32_t w_size;\
4386 uint32_t w_length;\
4387 uint8_t *w_data;\
4388 torture_assert(tctx,\
4389 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4390 &w_type, &w_size, &w_length, &w_data),\
4391 "failed to query winreg");\
4392 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4393 blob = data_blob(w_data, w_size);\
4394 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4395 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4396 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4397 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4398 "sd unequal");\
4399 } while(0);
4401 #define test_multi_sz(wname, iname) \
4402 do {\
4403 DATA_BLOB blob;\
4404 const char **array;\
4405 enum winreg_Type w_type;\
4406 uint32_t w_size;\
4407 uint32_t w_length;\
4408 uint8_t *w_data;\
4409 int i;\
4410 torture_assert(tctx,\
4411 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4412 &w_type, &w_size, &w_length, &w_data),\
4413 "failed to query winreg");\
4414 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4415 blob = data_blob(w_data, w_size);\
4416 torture_assert(tctx, \
4417 pull_reg_multi_sz(tctx, &blob, &array),\
4418 "failed to pull multi sz");\
4419 for (i=0; array[i] != NULL; i++) {\
4420 torture_assert_str_equal(tctx, array[i], iname[i],\
4421 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4423 } while(0);
4425 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4426 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4427 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4429 torture_warning(tctx, "failed to check for winreg symlink");
4432 for (i=0; i < ARRAY_SIZE(keys); i++) {
4434 const char *printer_key;
4435 struct policy_handle key_handle;
4437 printer_key = talloc_asprintf(tctx, "%s\\%s",
4438 keys[i], printer_name);
4440 torture_assert(tctx,
4441 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4443 test_sz("Name", printername);
4444 test_sz("Share Name", sharename);
4445 test_sz("Port", info.info2.portname);
4446 test_sz("Printer Driver", info.info2.drivername);
4447 test_sz("Description", info.info2.comment);
4448 test_sz("Location", info.info2.location);
4449 test_sz("Separator File", info.info2.sepfile);
4450 test_sz("Print Processor", info.info2.printprocessor);
4451 test_sz("Datatype", info.info2.datatype);
4452 test_sz("Parameters", info.info2.parameters);
4453 /* winreg: 0, spoolss not */
4454 /* test_dword("Attributes", info.info2.attributes); */
4455 test_dword("Priority", info.info2.priority);
4456 test_dword("Default Priority", info.info2.defaultpriority);
4457 /* winreg: 60, spoolss: 0 */
4458 /* test_dword("StartTime", info.info2.starttime); */
4459 /* test_dword("UntilTime", info.info2.untiltime); */
4460 /* winreg != spoolss */
4461 /* test_dword("Status", info.info2.status); */
4462 test_dm("Default DevMode", info.info2.devmode);
4463 test_sd("Security", info.info2.secdesc);
4465 torture_assert(tctx,
4466 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4469 #undef test_dm
4470 #undef test_sd
4472 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4474 return true;
4477 static bool test_PrintProcessors(struct torture_context *tctx,
4478 struct dcerpc_binding_handle *b,
4479 const char *environment,
4480 struct dcerpc_binding_handle *winreg_handle,
4481 struct policy_handle *hive_handle)
4483 union spoolss_PrintProcessorInfo *info;
4484 uint32_t count;
4485 int i;
4487 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4489 torture_assert(tctx,
4490 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4491 "failed to enum print processors level 1");
4493 for (i=0; i < count; i++) {
4495 const char *processor_key;
4496 struct policy_handle key_handle;
4498 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4499 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4500 environment,
4501 info[i].info1.print_processor_name);
4503 torture_assert(tctx,
4504 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4506 /* nothing to check in there so far */
4508 torture_assert(tctx,
4509 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4512 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4514 return true;
4517 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4518 struct dcerpc_binding_handle *b,
4519 struct policy_handle *handle,
4520 const char *driver_name,
4521 const char *architecture,
4522 uint32_t level,
4523 uint32_t client_major_version,
4524 uint32_t client_minor_version,
4525 union spoolss_DriverInfo *info_p,
4526 WERROR *result);
4528 static const char *strip_path(const char *path)
4530 char *p;
4532 if (path == NULL) {
4533 return NULL;
4536 p = strrchr(path, '\\');
4537 if (p) {
4538 return p+1;
4541 return path;
4544 static const char **strip_paths(const char **path_array)
4546 int i;
4548 if (path_array == NULL) {
4549 return NULL;
4552 for (i=0; path_array[i] != NULL; i++) {
4553 path_array[i] = strip_path(path_array[i]);
4556 return path_array;
4559 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4561 time_t t;
4562 struct tm *tm;
4563 t = nt_time_to_unix(nt);
4564 tm = localtime(&t);
4566 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4567 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4570 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4572 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4573 (unsigned)((v >> 48) & 0xFFFF),
4574 (unsigned)((v >> 32) & 0xFFFF),
4575 (unsigned)((v >> 16) & 0xFFFF),
4576 (unsigned)(v & 0xFFFF));
4579 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4580 struct dcerpc_binding_handle *b,
4581 struct policy_handle *handle,
4582 const char *printer_name,
4583 const char *driver_name,
4584 const char *environment,
4585 struct dcerpc_binding_handle *winreg_handle,
4586 struct policy_handle *hive_handle)
4588 WERROR result;
4589 union spoolss_DriverInfo info;
4590 const char *driver_key;
4591 struct policy_handle key_handle;
4593 const char *driver_path;
4594 const char *data_file;
4595 const char *config_file;
4596 const char *help_file;
4597 const char **dependent_files;
4599 const char *driver_date;
4600 const char *inbox_driver_date;
4602 const char *driver_version;
4603 const char *inbox_driver_version;
4605 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4607 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4608 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4609 environment,
4611 driver_name);
4613 torture_assert(tctx,
4614 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4615 "failed to open driver key");
4617 if (torture_setting_bool(tctx, "samba3", false)) {
4618 goto try_level3;
4621 torture_assert(tctx,
4622 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4623 "failed to get driver info level 8");
4625 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4626 goto try_level6;
4629 driver_path = strip_path(info.info8.driver_path);
4630 data_file = strip_path(info.info8.data_file);
4631 config_file = strip_path(info.info8.config_file);
4632 help_file = strip_path(info.info8.help_file);
4633 dependent_files = strip_paths(info.info8.dependent_files);
4635 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4636 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4638 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4639 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4641 test_sz("Configuration File", config_file);
4642 test_sz("Data File", data_file);
4643 test_sz("Datatype", info.info8.default_datatype);
4644 test_sz("Driver", driver_path);
4645 test_sz("DriverDate", driver_date);
4646 test_sz("DriverVersion", driver_version);
4647 test_sz("HardwareID", info.info8.hardware_id);
4648 test_sz("Help File", help_file);
4649 test_sz("InfPath", info.info8.inf_path);
4650 test_sz("Manufacturer", info.info8.manufacturer_name);
4651 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4652 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4653 test_sz("Monitor", info.info8.monitor_name);
4654 test_sz("OEM URL", info.info8.manufacturer_url);
4655 test_sz("Print Processor", info.info8.print_processor);
4656 test_sz("Provider", info.info8.provider);
4657 test_sz("VendorSetup", info.info8.vendor_setup);
4658 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4659 test_multi_sz("Dependent Files", dependent_files);
4660 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4661 test_multi_sz("Previous Names", info.info8.previous_names);
4662 /* test_dword("Attributes", ?); */
4663 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4664 test_dword("Version", info.info8.version);
4665 /* test_dword("TempDir", ?); */
4667 try_level6:
4669 torture_assert(tctx,
4670 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4671 "failed to get driver info level 6");
4673 driver_path = strip_path(info.info6.driver_path);
4674 data_file = strip_path(info.info6.data_file);
4675 config_file = strip_path(info.info6.config_file);
4676 help_file = strip_path(info.info6.help_file);
4677 dependent_files = strip_paths(info.info6.dependent_files);
4679 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4681 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4683 test_sz("Configuration File", config_file);
4684 test_sz("Data File", data_file);
4685 test_sz("Datatype", info.info6.default_datatype);
4686 test_sz("Driver", driver_path);
4687 test_sz("DriverDate", driver_date);
4688 test_sz("DriverVersion", driver_version);
4689 test_sz("HardwareID", info.info6.hardware_id);
4690 test_sz("Help File", help_file);
4691 test_sz("Manufacturer", info.info6.manufacturer_name);
4692 test_sz("Monitor", info.info6.monitor_name);
4693 test_sz("OEM URL", info.info6.manufacturer_url);
4694 test_sz("Provider", info.info6.provider);
4695 test_multi_sz("Dependent Files", dependent_files);
4696 test_multi_sz("Previous Names", info.info6.previous_names);
4697 /* test_dword("Attributes", ?); */
4698 test_dword("Version", info.info6.version);
4699 /* test_dword("TempDir", ?); */
4701 try_level3:
4703 torture_assert(tctx,
4704 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4705 "failed to get driver info level 3");
4707 driver_path = strip_path(info.info3.driver_path);
4708 data_file = strip_path(info.info3.data_file);
4709 config_file = strip_path(info.info3.config_file);
4710 help_file = strip_path(info.info3.help_file);
4711 dependent_files = strip_paths(info.info3.dependent_files);
4713 test_sz("Configuration File", config_file);
4714 test_sz("Data File", data_file);
4715 test_sz("Datatype", info.info3.default_datatype);
4716 test_sz("Driver", driver_path);
4717 test_sz("Help File", help_file);
4718 test_sz("Monitor", info.info3.monitor_name);
4719 test_multi_sz("Dependent Files", dependent_files);
4720 /* test_dword("Attributes", ?); */
4721 test_dword("Version", info.info3.version);
4722 /* test_dword("TempDir", ?); */
4725 torture_assert(tctx,
4726 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4728 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4730 return true;
4733 #undef test_sz
4734 #undef test_dword
4736 static bool test_SetPrinterData(struct torture_context *tctx,
4737 struct dcerpc_binding_handle *b,
4738 struct policy_handle *handle,
4739 const char *value_name,
4740 enum winreg_Type type,
4741 uint8_t *data,
4742 uint32_t offered)
4744 struct spoolss_SetPrinterData r;
4746 r.in.handle = handle;
4747 r.in.value_name = value_name;
4748 r.in.type = type;
4749 r.in.data = data;
4750 r.in.offered = offered;
4752 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4753 r.in.value_name);
4755 torture_assert_ntstatus_ok(tctx,
4756 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4757 "SetPrinterData failed");
4758 torture_assert_werr_ok(tctx, r.out.result,
4759 "SetPrinterData failed");
4761 return true;
4764 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4765 struct dcerpc_binding_handle *b,
4766 struct policy_handle *handle,
4767 const char *printer_name,
4768 struct dcerpc_binding_handle *winreg_handle,
4769 struct policy_handle *hive_handle)
4771 const char *values[] = {
4772 "spootyfoot",
4773 "spooty\\foot",
4774 #if 0
4775 /* FIXME: not working with s3 atm. */
4776 "spooty,foot",
4777 "spooty,fo,ot",
4778 #endif
4779 "spooty foot",
4780 #if 0
4781 /* FIXME: not working with s3 atm. */
4782 "spooty\\fo,ot",
4783 "spooty,fo\\ot"
4784 #endif
4786 int i;
4788 for (i=0; i < ARRAY_SIZE(values); i++) {
4790 enum winreg_Type type, expected_type = REG_SZ;
4791 DATA_BLOB blob;
4792 uint8_t *data;
4793 uint32_t needed;
4795 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4796 type = REG_SZ;
4798 torture_assert(tctx,
4799 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4800 "SetPrinterData failed");
4802 torture_assert(tctx,
4803 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4804 "GetPrinterData failed");
4806 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4807 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4808 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4810 if (winreg_handle && hive_handle) {
4812 enum winreg_Type w_type;
4813 uint32_t w_size;
4814 uint32_t w_length;
4815 uint8_t *w_data;
4817 torture_assert(tctx,
4818 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4819 printer_name, "PrinterDriverData", values[i],
4820 &w_type, &w_size, &w_length, &w_data), "");
4822 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4823 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4824 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4825 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4828 torture_assert(tctx,
4829 test_DeletePrinterData(tctx, b, handle, values[i]),
4830 "DeletePrinterData failed");
4833 return true;
4837 static bool test_EnumPrinterKey(struct torture_context *tctx,
4838 struct dcerpc_binding_handle *b,
4839 struct policy_handle *handle,
4840 const char *key_name,
4841 const char ***array);
4843 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4844 struct dcerpc_binding_handle *b,
4845 struct policy_handle *handle,
4846 const char *key_name,
4847 const char *value_name,
4848 enum winreg_Type type,
4849 uint8_t *data,
4850 uint32_t offered)
4852 NTSTATUS status;
4853 struct spoolss_SetPrinterDataEx r;
4855 r.in.handle = handle;
4856 r.in.key_name = key_name;
4857 r.in.value_name = value_name;
4858 r.in.type = type;
4859 r.in.data = data;
4860 r.in.offered = offered;
4862 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4863 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4865 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4867 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4868 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4870 return true;
4873 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4874 struct dcerpc_pipe *p,
4875 struct policy_handle *handle)
4877 struct dcerpc_binding_handle *b = p->binding_handle;
4878 const char *value_name = "dog";
4879 const char *keys[] = {
4880 "torturedataex",
4881 "torture data ex",
4882 "torturedataex_with_subkey\\subkey",
4883 "torturedataex_with_subkey\\subkey:0",
4884 "torturedataex_with_subkey\\subkey:1",
4885 "torturedataex_with_subkey\\subkey\\subsubkey",
4886 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4887 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4888 "torture,data",
4889 "torture,data,ex",
4890 "torture,data\\ex",
4891 "torture\\data,ex",
4892 "torture/data",
4893 "torture/data ex",
4894 "torture/data ex/sub",
4895 "torture//data",
4896 "torture//data ex",
4897 "torture//data ex/sub",
4898 "torture//data ex//sub",
4900 int i;
4902 for (i=0; i < ARRAY_SIZE(keys); i++) {
4904 char *c;
4905 const char *key;
4906 enum winreg_Type type;
4907 DATA_BLOB blob_in, blob_out;
4908 const char **subkeys;
4909 uint32_t ecount;
4910 struct spoolss_PrinterEnumValues *einfo;
4911 uint32_t needed;
4913 blob_in = data_blob_talloc(tctx, NULL, 42);
4915 generate_random_buffer(blob_in.data, blob_in.length);
4917 torture_assert(tctx,
4918 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
4919 "failed to call SetPrinterDataEx");
4921 torture_assert(tctx,
4922 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
4923 "failed to call GetPrinterDataEx");
4925 blob_out.length = needed;
4926 torture_assert(tctx,
4927 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4928 "failed to call EnumPrinterDataEx");
4930 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
4931 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
4932 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
4934 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4935 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4936 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4937 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
4938 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
4939 if (einfo[0].data_length > 0) {
4940 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
4943 key = talloc_strdup(tctx, keys[i]);
4945 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4946 return false;
4949 c = strchr(key, '\\');
4950 if (c) {
4951 int k;
4953 /* we have subkeys */
4955 *c = 0;
4957 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4958 return false;
4961 for (k=0; subkeys && subkeys[k]; k++) {
4963 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4965 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4966 return false;
4970 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4971 return false;
4974 } else {
4975 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4976 return false;
4981 return true;
4984 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
4985 struct dcerpc_pipe *p,
4986 struct policy_handle *handle)
4988 struct dcerpc_binding_handle *b = p->binding_handle;
4989 const char *key = "torturedataex";
4990 const char *values[] = {
4991 "torture_value",
4992 "torture value",
4993 "torture,value",
4994 "torture/value",
4995 "torture\\value",
4996 "torture\\\\value"
4998 int i;
5000 for (i=0; i < ARRAY_SIZE(values); i++) {
5002 enum winreg_Type type;
5003 DATA_BLOB blob_in, blob_out;
5004 uint32_t ecount;
5005 struct spoolss_PrinterEnumValues *einfo;
5006 uint32_t needed;
5008 if (torture_setting_bool(tctx, "samba3", false)) {
5009 char *q;
5010 q = strrchr(values[i], ',');
5011 if (q) {
5012 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5013 values[i]);
5014 continue;
5018 blob_in = data_blob_talloc(tctx, NULL, 42);
5020 generate_random_buffer(blob_in.data, blob_in.length);
5022 torture_assert(tctx,
5023 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5024 "failed to call SetPrinterDataEx");
5026 torture_assert(tctx,
5027 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5028 "failed to call GetPrinterDataEx");
5030 blob_out.length = needed;
5031 torture_assert(tctx,
5032 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5033 "failed to call EnumPrinterDataEx");
5035 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5036 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5037 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5039 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5040 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5041 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5042 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5043 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5044 if (einfo[0].data_length > 0) {
5045 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5048 torture_assert(tctx,
5049 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5050 "failed to call DeletePrinterDataEx");
5053 return true;
5057 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5058 struct dcerpc_pipe *p,
5059 struct policy_handle *handle,
5060 const char *printername,
5061 struct dcerpc_binding_handle *winreg_handle,
5062 struct policy_handle *hive_handle)
5064 struct dcerpc_binding_handle *b = p->binding_handle;
5065 const char *value_name = "dog";
5066 const char *key_name = "torturedataex";
5067 enum winreg_Type types[] = {
5068 REG_SZ,
5069 REG_MULTI_SZ,
5070 REG_DWORD,
5071 REG_BINARY
5073 const char *str = "abcdefghi";
5074 int t, s;
5076 for (t=0; t < ARRAY_SIZE(types); t++) {
5077 for (s=0; s < strlen(str); s++) {
5079 enum winreg_Type type;
5080 const char *string = talloc_strndup(tctx, str, s);
5081 const char *array[2];
5082 DATA_BLOB blob = data_blob_string_const(string);
5083 DATA_BLOB data;
5084 uint8_t *data_out;
5085 uint32_t needed, offered = 0;
5086 uint32_t ecount;
5087 struct spoolss_PrinterEnumValues *einfo;
5089 array[0] = talloc_strdup(tctx, string);
5090 array[1] = NULL;
5092 if (types[t] == REG_DWORD) {
5093 s = 0xffff;
5096 switch (types[t]) {
5097 case REG_BINARY:
5098 data = blob;
5099 offered = blob.length;
5100 break;
5101 case REG_DWORD:
5102 data = data_blob_talloc(tctx, NULL, 4);
5103 SIVAL(data.data, 0, 0x12345678);
5104 offered = 4;
5105 break;
5106 case REG_SZ:
5107 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5108 type = REG_SZ;
5109 offered = data.length;
5110 /*strlen_m_term(data.string)*2;*/
5111 break;
5112 case REG_MULTI_SZ:
5113 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5114 type = REG_MULTI_SZ;
5115 offered = data.length;
5116 break;
5117 default:
5118 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5121 torture_assert(tctx,
5122 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5123 "failed to call SetPrinterDataEx");
5125 torture_assert(tctx,
5126 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5127 "failed to call GetPrinterDataEx");
5129 torture_assert(tctx,
5130 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5131 "failed to call EnumPrinterDataEx");
5133 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5134 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5135 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5137 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5138 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5139 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5140 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5141 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5142 if (einfo[0].data_length > 0) {
5143 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5146 if (winreg_handle && hive_handle) {
5147 enum winreg_Type w_type;
5148 uint32_t w_size;
5149 uint32_t w_length;
5150 uint8_t *w_data;
5152 torture_assert(tctx,
5153 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5154 printername, key_name, value_name,
5155 &w_type, &w_size, &w_length, &w_data), "");
5157 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5158 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5159 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5160 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5163 torture_assert(tctx,
5164 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5165 "failed to call DeletePrinterDataEx");
5169 return true;
5172 static bool test_PrinterData_winreg(struct torture_context *tctx,
5173 struct dcerpc_pipe *p,
5174 struct policy_handle *handle,
5175 const char *printer_name)
5177 struct dcerpc_binding_handle *b = p->binding_handle;
5178 struct dcerpc_pipe *p2;
5179 bool ret = true;
5180 struct policy_handle hive_handle;
5181 struct dcerpc_binding_handle *b2;
5183 torture_assert_ntstatus_ok(tctx,
5184 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5185 "could not open winreg pipe");
5186 b2 = p2->binding_handle;
5188 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5190 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5191 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5193 test_winreg_CloseKey(tctx, b2, &hive_handle);
5195 talloc_free(p2);
5197 return ret;
5200 static bool test_Forms_winreg(struct torture_context *tctx,
5201 struct dcerpc_binding_handle *b,
5202 struct policy_handle *handle,
5203 bool print_server,
5204 const char *printer_name)
5206 struct dcerpc_pipe *p2;
5207 bool ret = true;
5208 struct policy_handle hive_handle;
5209 struct dcerpc_binding_handle *b2;
5211 torture_assert_ntstatus_ok(tctx,
5212 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5213 "could not open winreg pipe");
5214 b2 = p2->binding_handle;
5216 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5218 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5220 test_winreg_CloseKey(tctx, b2, &hive_handle);
5222 talloc_free(p2);
5224 return ret;
5227 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5228 struct dcerpc_pipe *p,
5229 struct policy_handle *handle,
5230 const char *printer_name)
5232 struct dcerpc_binding_handle *b = p->binding_handle;
5233 struct dcerpc_pipe *p2;
5234 bool ret = true;
5235 struct policy_handle hive_handle;
5236 struct dcerpc_binding_handle *b2;
5238 torture_assert_ntstatus_ok(tctx,
5239 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5240 "could not open winreg pipe");
5241 b2 = p2->binding_handle;
5243 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5245 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5247 test_winreg_CloseKey(tctx, b2, &hive_handle);
5249 talloc_free(p2);
5251 return ret;
5254 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5255 struct dcerpc_pipe *p,
5256 struct policy_handle *handle,
5257 const char *printer_name,
5258 const char *driver_name,
5259 const char *environment)
5261 struct dcerpc_binding_handle *b = p->binding_handle;
5262 struct dcerpc_pipe *p2;
5263 bool ret = true;
5264 struct policy_handle hive_handle;
5265 struct dcerpc_binding_handle *b2;
5267 torture_assert_ntstatus_ok(tctx,
5268 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5269 "could not open winreg pipe");
5270 b2 = p2->binding_handle;
5272 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5274 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
5276 test_winreg_CloseKey(tctx, b2, &hive_handle);
5278 talloc_free(p2);
5280 return ret;
5283 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5284 struct dcerpc_binding_handle *b,
5285 const char *environment)
5287 struct dcerpc_pipe *p2;
5288 bool ret = true;
5289 struct policy_handle hive_handle;
5290 struct dcerpc_binding_handle *b2;
5292 torture_assert_ntstatus_ok(tctx,
5293 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5294 "could not open winreg pipe");
5295 b2 = p2->binding_handle;
5297 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5299 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5301 test_winreg_CloseKey(tctx, b2, &hive_handle);
5303 talloc_free(p2);
5305 return ret;
5308 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5309 struct dcerpc_pipe *p,
5310 struct policy_handle *handle,
5311 const char *printer_name)
5313 struct spoolss_SetPrinterInfoCtr info_ctr;
5314 struct spoolss_DevmodeContainer devmode_ctr;
5315 struct sec_desc_buf secdesc_ctr;
5316 union spoolss_SetPrinterInfo sinfo;
5317 union spoolss_PrinterInfo info;
5318 struct dcerpc_binding_handle *b = p->binding_handle;
5319 const char *pname;
5321 ZERO_STRUCT(info_ctr);
5322 ZERO_STRUCT(devmode_ctr);
5323 ZERO_STRUCT(secdesc_ctr);
5325 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5327 torture_assert(tctx,
5328 test_GetPrinter_level(tctx, b, handle, 2, &info),
5329 "failed to query Printer level 2");
5331 torture_assert(tctx,
5332 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5333 "failed to convert");
5335 info_ctr.level = 2;
5336 info_ctr.info = sinfo;
5338 #define TEST_SZ(wname, iname) \
5339 do {\
5340 enum winreg_Type type;\
5341 uint8_t *data;\
5342 uint32_t needed;\
5343 DATA_BLOB blob;\
5344 const char *str;\
5345 torture_assert(tctx,\
5346 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5347 "failed to query");\
5348 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5349 blob = data_blob_const(data, needed);\
5350 torture_assert(tctx,\
5351 pull_reg_sz(tctx, &blob, &str),\
5352 "failed to pull REG_SZ");\
5353 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5354 } while(0);
5357 #define TEST_SET_SZ(wname, iname, val) \
5358 do {\
5359 enum winreg_Type type;\
5360 uint8_t *data;\
5361 uint32_t needed;\
5362 DATA_BLOB blob;\
5363 const char *str;\
5364 sinfo.info2->iname = val;\
5365 torture_assert(tctx,\
5366 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5367 "failed to call SetPrinter");\
5368 torture_assert(tctx,\
5369 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5370 "failed to query");\
5371 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5372 blob = data_blob_const(data, needed);\
5373 torture_assert(tctx,\
5374 pull_reg_sz(tctx, &blob, &str),\
5375 "failed to pull REG_SZ");\
5376 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5377 } while(0);
5379 #define TEST_SET_DWORD(wname, iname, val) \
5380 do {\
5381 enum winreg_Type type;\
5382 uint8_t *data;\
5383 uint32_t needed;\
5384 uint32_t value;\
5385 sinfo.info2->iname = val;\
5386 torture_assert(tctx,\
5387 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5388 "failed to call SetPrinter");\
5389 torture_assert(tctx,\
5390 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5391 "failed to query");\
5392 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5393 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5394 value = IVAL(data, 0); \
5395 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5396 } while(0);
5398 TEST_SET_SZ("description", comment, "newval");
5399 TEST_SET_SZ("location", location, "newval");
5400 /* TEST_SET_DWORD("priority", priority, 25); */
5402 torture_assert(tctx,
5403 test_GetPrinter_level(tctx, b, handle, 2, &info),
5404 "failed to query Printer level 2");
5406 TEST_SZ("description", info.info2.comment);
5407 TEST_SZ("driverName", info.info2.drivername);
5408 TEST_SZ("location", info.info2.location);
5410 pname = strrchr(info.info2.printername, '\\');
5411 if (pname == NULL) {
5412 pname = info.info2.printername;
5413 } else {
5414 pname++;
5416 TEST_SZ("printerName", pname);
5417 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5418 /* TEST_SZ("printShareName", info.info2.sharename); */
5420 /* FIXME gd: complete the list */
5422 #undef TEST_SZ
5423 #undef TEST_SET_SZ
5424 #undef TEST_DWORD
5426 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5428 return true;
5431 static bool test_print_processors_winreg(struct torture_context *tctx,
5432 void *private_data)
5434 struct test_spoolss_context *ctx =
5435 talloc_get_type_abort(private_data, struct test_spoolss_context);
5436 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5437 struct dcerpc_binding_handle *b = p->binding_handle;
5439 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5442 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5443 struct dcerpc_binding_handle *b,
5444 struct policy_handle *handle,
5445 uint32_t *change_id)
5447 enum winreg_Type type;
5448 uint8_t *data;
5449 uint32_t needed;
5451 torture_assert(tctx,
5452 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5453 "failed to call GetPrinterData");
5455 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5456 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5458 *change_id = IVAL(data, 0);
5460 return true;
5463 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5464 struct dcerpc_pipe *p,
5465 struct policy_handle *handle,
5466 uint32_t *change_id)
5468 enum winreg_Type type;
5469 uint8_t *data;
5470 uint32_t needed;
5472 torture_assert(tctx,
5473 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5474 "failed to call GetPrinterData");
5476 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5477 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5479 *change_id = IVAL(data, 0);
5481 return true;
5484 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5485 struct dcerpc_binding_handle *b,
5486 struct policy_handle *handle,
5487 uint32_t *change_id)
5489 union spoolss_PrinterInfo info;
5491 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5492 "failed to query Printer level 0");
5494 *change_id = info.info0.change_id;
5496 return true;
5499 static bool test_ChangeID(struct torture_context *tctx,
5500 struct dcerpc_pipe *p,
5501 struct policy_handle *handle)
5503 uint32_t change_id, change_id_ex, change_id_info;
5504 uint32_t change_id2, change_id_ex2, change_id_info2;
5505 union spoolss_PrinterInfo info;
5506 const char *comment;
5507 struct dcerpc_binding_handle *b = p->binding_handle;
5509 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5511 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5512 "failed to query for ChangeID");
5513 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5514 "failed to query for ChangeID");
5515 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5516 "failed to query for ChangeID");
5518 torture_assert_int_equal(tctx, change_id, change_id_ex,
5519 "change_ids should all be equal");
5520 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5521 "change_ids should all be equal");
5524 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5526 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5527 "failed to query for ChangeID");
5528 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5529 "failed to query Printer level 2");
5530 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5531 "failed to query for ChangeID");
5532 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5533 "failed to query for ChangeID");
5534 torture_assert_int_equal(tctx, change_id, change_id_ex,
5535 "change_id should not have changed");
5536 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5537 "change_id should not have changed");
5540 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5542 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5543 "failed to query for ChangeID");
5544 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5545 "failed to query for ChangeID");
5546 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5547 "failed to query for ChangeID");
5548 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5549 "failed to query Printer level 2");
5550 comment = talloc_strdup(tctx, info.info2.comment);
5553 struct spoolss_SetPrinterInfoCtr info_ctr;
5554 struct spoolss_DevmodeContainer devmode_ctr;
5555 struct sec_desc_buf secdesc_ctr;
5556 union spoolss_SetPrinterInfo sinfo;
5558 ZERO_STRUCT(info_ctr);
5559 ZERO_STRUCT(devmode_ctr);
5560 ZERO_STRUCT(secdesc_ctr);
5563 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5564 sinfo.info2->comment = "torture_comment";
5566 info_ctr.level = 2;
5567 info_ctr.info = sinfo;
5569 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5570 "failed to call SetPrinter");
5572 sinfo.info2->comment = comment;
5574 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5575 "failed to call SetPrinter");
5579 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5580 "failed to query for ChangeID");
5581 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5582 "failed to query for ChangeID");
5583 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5584 "failed to query for ChangeID");
5586 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5587 "change_ids should all be equal");
5588 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5589 "change_ids should all be equal");
5591 torture_assert(tctx, (change_id < change_id2),
5592 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5593 change_id2, change_id));
5594 torture_assert(tctx, (change_id_ex < change_id_ex2),
5595 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5596 change_id_ex2, change_id_ex));
5597 torture_assert(tctx, (change_id_info < change_id_info2),
5598 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5599 change_id_info2, change_id_info));
5601 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5603 return true;
5606 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5607 struct dcerpc_pipe *p,
5608 struct policy_handle *handle)
5610 NTSTATUS status;
5611 struct dcerpc_binding *b;
5612 struct dcerpc_pipe *p2;
5613 struct spoolss_ClosePrinter cp;
5615 /* only makes sense on SMB */
5616 if (p->conn->transport.transport != NCACN_NP) {
5617 return true;
5620 torture_comment(tctx, "Testing close on secondary pipe\n");
5622 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5623 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5625 status = dcerpc_secondary_connection(p, &p2, b);
5626 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5628 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5629 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5631 cp.in.handle = handle;
5632 cp.out.handle = handle;
5634 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5635 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5636 "ERROR: Allowed close on secondary connection");
5638 talloc_free(p2);
5640 return true;
5643 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5644 struct dcerpc_binding_handle *b, const char *name)
5646 NTSTATUS status;
5647 struct spoolss_OpenPrinter op;
5648 struct spoolss_OpenPrinterEx opEx;
5649 struct policy_handle handle;
5650 bool ret = true;
5652 op.in.printername = name;
5653 op.in.datatype = NULL;
5654 op.in.devmode_ctr.devmode= NULL;
5655 op.in.access_mask = 0;
5656 op.out.handle = &handle;
5658 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5660 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5661 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5662 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5663 "unexpected result");
5665 if (W_ERROR_IS_OK(op.out.result)) {
5666 ret &=test_ClosePrinter(tctx, b, &handle);
5669 opEx.in.printername = name;
5670 opEx.in.datatype = NULL;
5671 opEx.in.devmode_ctr.devmode = NULL;
5672 opEx.in.access_mask = 0;
5673 opEx.in.level = 1;
5674 opEx.in.userlevel.level1 = NULL;
5675 opEx.out.handle = &handle;
5677 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5679 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5680 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5681 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5682 "unexpected result");
5684 if (W_ERROR_IS_OK(opEx.out.result)) {
5685 ret &=test_ClosePrinter(tctx, b, &handle);
5688 return ret;
5691 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5692 void *private_data)
5694 struct test_spoolss_context *ctx =
5695 talloc_get_type_abort(private_data, struct test_spoolss_context);
5697 const char *badnames[] = {
5698 "__INVALID_PRINTER__",
5699 "\\\\__INVALID_HOST__",
5701 "\\\\\\",
5702 "\\\\\\__INVALID_PRINTER__"
5704 const char *badname;
5705 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5706 const char *server_name = dcerpc_server_name(p);
5707 struct dcerpc_binding_handle *b = p->binding_handle;
5708 int i;
5710 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5711 torture_assert(tctx,
5712 test_OpenPrinter_badname(tctx, b, badnames[i]),
5713 "");
5716 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5717 torture_assert(tctx,
5718 test_OpenPrinter_badname(tctx, b, badname),
5719 "");
5721 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5722 torture_assert(tctx,
5723 test_OpenPrinter_badname(tctx, b, badname),
5724 "");
5726 return true;
5729 static bool test_OpenPrinter(struct torture_context *tctx,
5730 struct dcerpc_pipe *p,
5731 const char *name,
5732 const char *environment,
5733 bool open_only)
5735 NTSTATUS status;
5736 struct spoolss_OpenPrinter r;
5737 struct policy_handle handle;
5738 bool ret = true;
5739 struct dcerpc_binding_handle *b = p->binding_handle;
5741 r.in.printername = name;
5742 r.in.datatype = NULL;
5743 r.in.devmode_ctr.devmode= NULL;
5744 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5745 r.out.handle = &handle;
5747 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5749 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5751 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5753 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5755 if (open_only) {
5756 goto close_printer;
5759 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5760 ret = false;
5763 if (!torture_setting_bool(tctx, "samba3", false)) {
5764 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5765 ret = false;
5769 close_printer:
5770 if (!test_ClosePrinter(tctx, b, &handle)) {
5771 ret = false;
5774 return ret;
5777 static bool test_OpenPrinterEx(struct torture_context *tctx,
5778 struct dcerpc_binding_handle *b,
5779 const char *printername,
5780 const char *datatype,
5781 struct spoolss_DeviceMode *devmode,
5782 uint32_t access_mask,
5783 uint32_t level,
5784 union spoolss_UserLevel *userlevel,
5785 struct policy_handle *handle,
5786 WERROR expected_result)
5788 struct spoolss_OpenPrinterEx r;
5790 r.in.printername = printername;
5791 r.in.datatype = datatype;
5792 r.in.devmode_ctr.devmode= devmode;
5793 r.in.access_mask = access_mask;
5794 r.in.level = level;
5795 r.in.userlevel = *userlevel;
5796 r.out.handle = handle;
5798 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5800 torture_assert_ntstatus_ok(tctx,
5801 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5802 "OpenPrinterEx failed");
5804 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5805 "OpenPrinterEx failed");
5807 return true;
5810 static bool call_OpenPrinterEx(struct torture_context *tctx,
5811 struct dcerpc_pipe *p,
5812 const char *name,
5813 struct spoolss_DeviceMode *devmode,
5814 struct policy_handle *handle)
5816 union spoolss_UserLevel userlevel;
5817 struct spoolss_UserLevel1 userlevel1;
5818 struct dcerpc_binding_handle *b = p->binding_handle;
5820 userlevel1.size = 1234;
5821 userlevel1.client = "hello";
5822 userlevel1.user = "spottyfoot!";
5823 userlevel1.build = 1;
5824 userlevel1.major = 2;
5825 userlevel1.minor = 3;
5826 userlevel1.processor = 4;
5828 userlevel.level1 = &userlevel1;
5830 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5831 SEC_FLAG_MAXIMUM_ALLOWED,
5833 &userlevel,
5834 handle,
5835 WERR_OK);
5838 static bool test_printer_rename(struct torture_context *tctx,
5839 void *private_data)
5841 struct torture_printer_context *t =
5842 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5843 struct dcerpc_pipe *p = t->spoolss_pipe;
5845 bool ret = true;
5846 union spoolss_PrinterInfo info;
5847 union spoolss_SetPrinterInfo sinfo;
5848 struct spoolss_SetPrinterInfoCtr info_ctr;
5849 struct spoolss_DevmodeContainer devmode_ctr;
5850 struct sec_desc_buf secdesc_ctr;
5851 const char *printer_name;
5852 const char *printer_name_orig;
5853 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5854 struct policy_handle new_handle;
5855 const char *q;
5856 struct dcerpc_binding_handle *b = p->binding_handle;
5858 ZERO_STRUCT(devmode_ctr);
5859 ZERO_STRUCT(secdesc_ctr);
5861 torture_comment(tctx, "Testing Printer rename operations\n");
5863 torture_assert(tctx,
5864 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5865 "failed to call GetPrinter level 2");
5867 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5869 q = strrchr(info.info2.printername, '\\');
5870 if (q) {
5871 torture_warning(tctx,
5872 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5875 torture_assert(tctx,
5876 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5878 sinfo.info2->printername = printer_name_new;
5880 info_ctr.level = 2;
5881 info_ctr.info = sinfo;
5883 torture_assert(tctx,
5884 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5885 "failed to call SetPrinter level 2");
5887 torture_assert(tctx,
5888 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5889 "failed to call GetPrinter level 2");
5891 printer_name = talloc_strdup(tctx, info.info2.printername);
5893 q = strrchr(info.info2.printername, '\\');
5894 if (q) {
5895 torture_warning(tctx,
5896 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5897 q++;
5898 printer_name = q;
5901 torture_assert_str_equal(tctx, printer_name, printer_name_new,
5902 "new printer name was not set");
5904 /* samba currently cannot fully rename printers */
5905 if (!torture_setting_bool(tctx, "samba3", false)) {
5906 torture_assert(tctx,
5907 test_OpenPrinter_badname(tctx, b, printer_name_orig),
5908 "still can open printer with oldname after rename");
5909 } else {
5910 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5913 torture_assert(tctx,
5914 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5915 "failed to open printer with new name");
5917 torture_assert(tctx,
5918 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5919 "failed to call GetPrinter level 2");
5921 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
5922 "new printer name was not set");
5924 torture_assert(tctx,
5925 test_ClosePrinter(tctx, b, &new_handle),
5926 "failed to close printer");
5928 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5930 return ret;
5933 static bool test_openprinter(struct torture_context *tctx,
5934 struct dcerpc_binding_handle *b,
5935 const char *real_printername)
5937 union spoolss_UserLevel userlevel;
5938 struct policy_handle handle;
5939 struct spoolss_UserLevel1 userlevel1;
5940 const char *printername = NULL;
5941 int i;
5943 struct {
5944 const char *suffix;
5945 WERROR expected_result;
5946 } tests[] = {
5948 .suffix = "rubbish",
5949 .expected_result = WERR_INVALID_PRINTER_NAME
5951 .suffix = ", LocalOnl",
5952 .expected_result = WERR_INVALID_PRINTER_NAME
5954 .suffix = ", localOnly",
5955 .expected_result = WERR_INVALID_PRINTER_NAME
5957 .suffix = ", localonl",
5958 .expected_result = WERR_INVALID_PRINTER_NAME
5960 .suffix = ",LocalOnl",
5961 .expected_result = WERR_INVALID_PRINTER_NAME
5963 .suffix = ",localOnl2",
5964 .expected_result = WERR_INVALID_PRINTER_NAME
5966 .suffix = ", DrvConver2t",
5967 .expected_result = WERR_INVALID_PRINTER_NAME
5969 .suffix = ", drvconvert",
5970 .expected_result = WERR_INVALID_PRINTER_NAME
5972 .suffix = ",drvconvert",
5973 .expected_result = WERR_INVALID_PRINTER_NAME
5975 .suffix = ", DrvConvert",
5976 .expected_result = WERR_OK
5978 .suffix = " , DrvConvert",
5979 .expected_result = WERR_INVALID_PRINTER_NAME
5981 .suffix = ",DrvConvert",
5982 .expected_result = WERR_OK
5984 .suffix = ", DrvConvertsadfasdf",
5985 .expected_result = WERR_OK
5987 .suffix = ",DrvConvertasdfasd",
5988 .expected_result = WERR_OK
5990 .suffix = ", LocalOnly",
5991 .expected_result = WERR_OK
5993 .suffix = " , LocalOnly",
5994 .expected_result = WERR_INVALID_PRINTER_NAME
5996 .suffix = ",LocalOnly",
5997 .expected_result = WERR_OK
5999 .suffix = ", LocalOnlysagi4gjfkd",
6000 .expected_result = WERR_OK
6002 .suffix = ",LocalOnlysagi4gjfkd",
6003 .expected_result = WERR_OK
6007 userlevel1.size = 1234;
6008 userlevel1.client = "hello";
6009 userlevel1.user = "spottyfoot!";
6010 userlevel1.build = 1;
6011 userlevel1.major = 2;
6012 userlevel1.minor = 3;
6013 userlevel1.processor = 4;
6015 userlevel.level1 = &userlevel1;
6017 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6019 torture_assert(tctx,
6020 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6021 &userlevel, &handle,
6022 WERR_OK),
6023 "OpenPrinterEx failed");
6024 test_ClosePrinter(tctx, b, &handle);
6026 for (i=0; i < ARRAY_SIZE(tests); i++) {
6028 printername = talloc_asprintf(tctx, "%s%s",
6029 real_printername,
6030 tests[i].suffix);
6032 torture_assert(tctx,
6033 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6034 &userlevel, &handle,
6035 tests[i].expected_result),
6036 "OpenPrinterEx failed");
6037 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6038 test_ClosePrinter(tctx, b, &handle);
6042 return true;
6046 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6047 struct dcerpc_pipe *p,
6048 const char *name,
6049 const char *environment)
6051 struct policy_handle handle;
6052 bool ret = true;
6053 struct dcerpc_binding_handle *b = p->binding_handle;
6055 if (!test_openprinter(tctx, b, name)) {
6056 return false;
6059 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6060 return false;
6063 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6064 ret = false;
6067 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6068 ret = false;
6071 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6072 ret = false;
6075 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6076 ret = false;
6079 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6080 ret = false;
6083 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6084 ret = false;
6087 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6088 ret = false;
6091 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6092 ret = false;
6095 if (!test_printer_all_keys(tctx, b, &handle)) {
6096 ret = false;
6099 if (!test_PausePrinter(tctx, b, &handle)) {
6100 ret = false;
6103 if (!test_DoPrintTest(tctx, b, &handle)) {
6104 ret = false;
6107 if (!test_ResumePrinter(tctx, b, &handle)) {
6108 ret = false;
6111 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6112 ret = false;
6115 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6116 ret = false;
6119 if (!torture_setting_bool(tctx, "samba3", false)) {
6120 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6121 ret = false;
6125 if (!test_ClosePrinter(tctx, b, &handle)) {
6126 ret = false;
6129 return ret;
6132 static bool test_EnumPrinters_old(struct torture_context *tctx,
6133 void *private_data)
6135 struct test_spoolss_context *ctx =
6136 talloc_get_type_abort(private_data, struct test_spoolss_context);
6137 struct spoolss_EnumPrinters r;
6138 NTSTATUS status;
6139 uint16_t levels[] = {1, 2, 4, 5};
6140 int i;
6141 bool ret = true;
6142 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6143 struct dcerpc_binding_handle *b = p->binding_handle;
6145 for (i=0;i<ARRAY_SIZE(levels);i++) {
6146 union spoolss_PrinterInfo *info;
6147 int j;
6148 uint32_t needed;
6149 uint32_t count;
6151 r.in.flags = PRINTER_ENUM_LOCAL;
6152 r.in.server = "";
6153 r.in.level = levels[i];
6154 r.in.buffer = NULL;
6155 r.in.offered = 0;
6156 r.out.needed = &needed;
6157 r.out.count = &count;
6158 r.out.info = &info;
6160 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6162 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6163 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6165 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6166 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6167 r.in.buffer = &blob;
6168 r.in.offered = needed;
6169 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6172 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6174 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6176 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6178 if (!info) {
6179 torture_comment(tctx, "No printers returned\n");
6180 return true;
6183 for (j=0;j<count;j++) {
6184 if (r.in.level == 1) {
6185 char *unc = talloc_strdup(tctx, info[j].info1.name);
6186 char *slash, *name, *full_name;
6187 name = unc;
6188 if (unc[0] == '\\' && unc[1] == '\\') {
6189 unc +=2;
6191 slash = strchr(unc, '\\');
6192 if (slash) {
6193 slash++;
6194 name = slash;
6196 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6197 dcerpc_server_name(p), name);
6198 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6199 ret = false;
6201 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6202 ret = false;
6204 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6205 ret = false;
6207 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6208 ret = false;
6214 return ret;
6217 static bool test_EnumPrinters_level(struct torture_context *tctx,
6218 struct dcerpc_binding_handle *b,
6219 uint32_t flags,
6220 const char *servername,
6221 uint32_t level,
6222 uint32_t *count_p,
6223 union spoolss_PrinterInfo **info_p)
6225 struct spoolss_EnumPrinters r;
6226 union spoolss_PrinterInfo *info;
6227 uint32_t needed;
6228 uint32_t count;
6230 r.in.flags = flags;
6231 r.in.server = servername;
6232 r.in.level = level;
6233 r.in.buffer = NULL;
6234 r.in.offered = 0;
6235 r.out.needed = &needed;
6236 r.out.count = &count;
6237 r.out.info = &info;
6239 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6240 r.in.server, r.in.level);
6242 torture_assert_ntstatus_ok(tctx,
6243 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6244 "EnumPrinters failed");
6245 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6246 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6247 r.in.buffer = &blob;
6248 r.in.offered = needed;
6249 torture_assert_ntstatus_ok(tctx,
6250 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6251 "EnumPrinters failed");
6254 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6256 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6258 if (count_p) {
6259 *count_p = count;
6261 if (info_p) {
6262 *info_p = info;
6265 return true;
6268 static const char *get_short_printername(struct torture_context *tctx,
6269 const char *name)
6271 const char *short_name;
6273 if (name[0] == '\\' && name[1] == '\\') {
6274 name += 2;
6275 short_name = strchr(name, '\\');
6276 if (short_name) {
6277 return talloc_strdup(tctx, short_name+1);
6281 return name;
6284 static const char *get_full_printername(struct torture_context *tctx,
6285 const char *name)
6287 const char *full_name = talloc_strdup(tctx, name);
6288 char *p;
6290 if (name && name[0] == '\\' && name[1] == '\\') {
6291 name += 2;
6292 p = strchr(name, '\\');
6293 if (p) {
6294 return full_name;
6298 return NULL;
6301 static bool test_OnePrinter_servername(struct torture_context *tctx,
6302 struct dcerpc_pipe *p,
6303 struct dcerpc_binding_handle *b,
6304 const char *servername,
6305 const char *printername)
6307 union spoolss_PrinterInfo info;
6308 const char *short_name = get_short_printername(tctx, printername);
6309 const char *full_name = get_full_printername(tctx, printername);
6311 if (short_name) {
6312 struct policy_handle handle;
6313 torture_assert(tctx,
6314 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6315 "failed to open printer");
6317 torture_assert(tctx,
6318 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6319 "failed to get printer info");
6321 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6322 "unexpected servername");
6323 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6324 "unexpected printername");
6326 if (info.info2.devmode) {
6327 const char *expected_devicename;
6328 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6329 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6330 "unexpected devicemode devicename");
6333 torture_assert(tctx,
6334 test_ClosePrinter(tctx, b, &handle),
6335 "failed to close printer");
6338 if (full_name) {
6339 struct policy_handle handle;
6341 torture_assert(tctx,
6342 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6343 "failed to open printer");
6345 torture_assert(tctx,
6346 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6347 "failed to get printer info");
6349 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6350 "unexpected servername");
6351 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6352 "unexpected printername");
6354 if (info.info2.devmode) {
6355 const char *expected_devicename;
6356 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6357 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6358 "unexpected devicemode devicename");
6361 torture_assert(tctx,
6362 test_ClosePrinter(tctx, b, &handle),
6363 "failed to close printer");
6366 return true;
6369 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6370 void *private_data)
6372 struct test_spoolss_context *ctx =
6373 talloc_get_type_abort(private_data, struct test_spoolss_context);
6374 int i;
6375 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6376 struct dcerpc_binding_handle *b = p->binding_handle;
6377 uint32_t count;
6378 union spoolss_PrinterInfo *info;
6379 const char *servername;
6380 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6382 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6384 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6386 torture_assert(tctx,
6387 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6388 "failed to enumerate printers");
6390 for (i=0; i < count; i++) {
6392 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6393 "unexpected servername");
6395 torture_assert(tctx,
6396 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6397 "failed to check printer");
6400 servername = "";
6402 torture_assert(tctx,
6403 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6404 "failed to enumerate printers");
6406 for (i=0; i < count; i++) {
6408 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6409 "unexpected servername");
6411 torture_assert(tctx,
6412 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6413 "failed to check printer");
6417 return true;
6421 static bool test_GetPrinterDriver(struct torture_context *tctx,
6422 struct dcerpc_binding_handle *b,
6423 struct policy_handle *handle,
6424 const char *driver_name)
6426 struct spoolss_GetPrinterDriver r;
6427 uint32_t needed;
6429 r.in.handle = handle;
6430 r.in.architecture = "W32X86";
6431 r.in.level = 1;
6432 r.in.buffer = NULL;
6433 r.in.offered = 0;
6434 r.out.needed = &needed;
6436 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6438 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6439 "failed to call GetPrinterDriver");
6440 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6441 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6442 r.in.buffer = &blob;
6443 r.in.offered = needed;
6444 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6445 "failed to call GetPrinterDriver");
6448 torture_assert_werr_ok(tctx, r.out.result,
6449 "failed to call GetPrinterDriver");
6451 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6453 return true;
6456 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6457 struct dcerpc_binding_handle *b,
6458 struct policy_handle *handle,
6459 const char *driver_name,
6460 const char *architecture,
6461 uint32_t level,
6462 uint32_t client_major_version,
6463 uint32_t client_minor_version,
6464 union spoolss_DriverInfo *info_p,
6465 WERROR *result_p)
6468 struct spoolss_GetPrinterDriver2 r;
6469 uint32_t needed;
6470 uint32_t server_major_version;
6471 uint32_t server_minor_version;
6473 r.in.handle = handle;
6474 r.in.architecture = architecture;
6475 r.in.client_major_version = client_major_version;
6476 r.in.client_minor_version = client_minor_version;
6477 r.in.buffer = NULL;
6478 r.in.offered = 0;
6479 r.in.level = level;
6480 r.out.needed = &needed;
6481 r.out.server_major_version = &server_major_version;
6482 r.out.server_minor_version = &server_minor_version;
6484 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6485 driver_name, r.in.level);
6487 torture_assert_ntstatus_ok(tctx,
6488 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6489 "failed to call GetPrinterDriver2");
6490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6492 r.in.buffer = &blob;
6493 r.in.offered = needed;
6494 torture_assert_ntstatus_ok(tctx,
6495 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6496 "failed to call GetPrinterDriver2");
6499 if (result_p) {
6500 *result_p = r.out.result;
6503 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6504 switch (r.in.level) {
6505 case 101:
6506 case 8:
6507 torture_comment(tctx,
6508 "level %d not implemented, not considering as an error\n",
6509 r.in.level);
6510 return true;
6511 default:
6512 break;
6516 torture_assert_werr_ok(tctx, r.out.result,
6517 "failed to call GetPrinterDriver2");
6519 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6521 if (info_p) {
6522 *info_p = *r.out.info;
6525 return true;
6528 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6529 struct dcerpc_binding_handle *b,
6530 struct policy_handle *handle,
6531 const char *driver_name,
6532 const char *architecture)
6534 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6535 int i;
6538 for (i=0;i<ARRAY_SIZE(levels);i++) {
6540 torture_assert(tctx,
6541 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6542 "");
6545 return true;
6548 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6549 void *private_data)
6551 struct test_spoolss_context *ctx =
6552 talloc_get_type_abort(private_data, struct test_spoolss_context);
6553 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6554 int i;
6555 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6556 struct dcerpc_binding_handle *b = p->binding_handle;
6557 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6559 for (i=0;i<ARRAY_SIZE(levels);i++) {
6561 uint32_t count;
6562 union spoolss_DriverInfo *info;
6564 torture_assert(tctx,
6565 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6566 "failed to enumerate drivers");
6568 if (!info) {
6569 torture_comment(tctx, "No printer drivers returned\n");
6570 break;
6574 return true;
6577 static bool test_DeletePrinter(struct torture_context *tctx,
6578 struct dcerpc_binding_handle *b,
6579 struct policy_handle *handle)
6581 struct spoolss_DeletePrinter r;
6583 torture_comment(tctx, "Testing DeletePrinter\n");
6585 r.in.handle = handle;
6587 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6588 "failed to delete printer");
6589 torture_assert_werr_ok(tctx, r.out.result,
6590 "failed to delete printer");
6592 return true;
6595 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6596 struct dcerpc_binding_handle *b,
6597 uint32_t flags,
6598 uint32_t level,
6599 const char *name,
6600 bool *found)
6602 struct spoolss_EnumPrinters e;
6603 uint32_t count;
6604 union spoolss_PrinterInfo *info;
6605 uint32_t needed;
6606 int i;
6608 *found = false;
6610 e.in.flags = flags;
6611 e.in.server = NULL;
6612 e.in.level = level;
6613 e.in.buffer = NULL;
6614 e.in.offered = 0;
6615 e.out.count = &count;
6616 e.out.info = &info;
6617 e.out.needed = &needed;
6619 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6620 "failed to enum printers");
6622 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6623 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6624 e.in.buffer = &blob;
6625 e.in.offered = needed;
6627 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6628 "failed to enum printers");
6631 torture_assert_werr_ok(tctx, e.out.result,
6632 "failed to enum printers");
6634 for (i=0; i < count; i++) {
6636 const char *current = NULL;
6637 const char *q;
6639 switch (level) {
6640 case 1:
6641 current = info[i].info1.name;
6642 break;
6645 if (strequal(current, name)) {
6646 *found = true;
6647 break;
6650 q = strrchr(current, '\\');
6651 if (q) {
6652 if (!e.in.server) {
6653 torture_warning(tctx,
6654 "server returns printername %s incl. servername although we did not set servername", current);
6656 q++;
6657 if (strequal(q, name)) {
6658 *found = true;
6659 break;
6664 return true;
6667 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6668 struct dcerpc_pipe *p,
6669 const char *printername,
6670 bool ex)
6672 WERROR result;
6673 struct spoolss_AddPrinter r;
6674 struct spoolss_AddPrinterEx rex;
6675 struct spoolss_SetPrinterInfoCtr info_ctr;
6676 struct spoolss_SetPrinterInfo1 info1;
6677 struct spoolss_DevmodeContainer devmode_ctr;
6678 struct sec_desc_buf secdesc_ctr;
6679 struct spoolss_UserLevelCtr userlevel_ctr;
6680 struct policy_handle handle;
6681 bool found = false;
6682 struct dcerpc_binding_handle *b = p->binding_handle;
6684 ZERO_STRUCT(devmode_ctr);
6685 ZERO_STRUCT(secdesc_ctr);
6686 ZERO_STRUCT(userlevel_ctr);
6687 ZERO_STRUCT(info1);
6689 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6690 ex ? "Ex":"", printername);
6692 /* try to add printer to wellknown printer list (level 1) */
6694 userlevel_ctr.level = 1;
6696 info_ctr.info.info1 = &info1;
6697 info_ctr.level = 1;
6699 rex.in.server = NULL;
6700 rex.in.info_ctr = &info_ctr;
6701 rex.in.devmode_ctr = &devmode_ctr;
6702 rex.in.secdesc_ctr = &secdesc_ctr;
6703 rex.in.userlevel_ctr = &userlevel_ctr;
6704 rex.out.handle = &handle;
6706 r.in.server = NULL;
6707 r.in.info_ctr = &info_ctr;
6708 r.in.devmode_ctr = &devmode_ctr;
6709 r.in.secdesc_ctr = &secdesc_ctr;
6710 r.out.handle = &handle;
6712 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6713 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6714 "failed to add printer");
6715 result = ex ? rex.out.result : r.out.result;
6716 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6717 "unexpected result code");
6719 info1.name = printername;
6720 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6722 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6723 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6724 "failed to add printer");
6725 result = ex ? rex.out.result : r.out.result;
6726 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6727 "unexpected result code");
6729 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6730 better do a real check to see the printer is really there */
6732 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6733 PRINTER_ENUM_NETWORK, 1,
6734 printername,
6735 &found),
6736 "failed to enum printers");
6738 torture_assert(tctx, found, "failed to find newly added printer");
6740 info1.flags = 0;
6742 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6743 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6744 "failed to add printer");
6745 result = ex ? rex.out.result : r.out.result;
6746 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6747 "unexpected result code");
6749 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6750 better do a real check to see the printer has really been removed
6751 from the well known printer list */
6753 found = false;
6755 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6756 PRINTER_ENUM_NETWORK, 1,
6757 printername,
6758 &found),
6759 "failed to enum printers");
6760 #if 0
6761 torture_assert(tctx, !found, "printer still in well known printer list");
6762 #endif
6763 return true;
6766 static bool test_AddPrinter_normal(struct torture_context *tctx,
6767 struct dcerpc_pipe *p,
6768 struct policy_handle *handle_p,
6769 const char *printername,
6770 const char *drivername,
6771 const char *portname,
6772 struct spoolss_DeviceMode *devmode,
6773 bool ex)
6775 WERROR result;
6776 struct spoolss_AddPrinter r;
6777 struct spoolss_AddPrinterEx rex;
6778 struct spoolss_SetPrinterInfoCtr info_ctr;
6779 struct spoolss_SetPrinterInfo2 info2;
6780 struct spoolss_DevmodeContainer devmode_ctr;
6781 struct sec_desc_buf secdesc_ctr;
6782 struct spoolss_UserLevelCtr userlevel_ctr;
6783 struct policy_handle handle;
6784 bool found = false;
6785 bool existing_printer_deleted = false;
6786 struct dcerpc_binding_handle *b = p->binding_handle;
6788 ZERO_STRUCT(devmode_ctr);
6789 ZERO_STRUCT(secdesc_ctr);
6790 ZERO_STRUCT(userlevel_ctr);
6792 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6793 ex ? "Ex":"", printername);
6795 devmode_ctr.devmode = devmode;
6797 userlevel_ctr.level = 1;
6799 rex.in.server = NULL;
6800 rex.in.info_ctr = &info_ctr;
6801 rex.in.devmode_ctr = &devmode_ctr;
6802 rex.in.secdesc_ctr = &secdesc_ctr;
6803 rex.in.userlevel_ctr = &userlevel_ctr;
6804 rex.out.handle = &handle;
6806 r.in.server = NULL;
6807 r.in.info_ctr = &info_ctr;
6808 r.in.devmode_ctr = &devmode_ctr;
6809 r.in.secdesc_ctr = &secdesc_ctr;
6810 r.out.handle = &handle;
6812 again:
6814 /* try to add printer to printer list (level 2) */
6816 ZERO_STRUCT(info2);
6818 info_ctr.info.info2 = &info2;
6819 info_ctr.level = 2;
6821 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6822 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6823 "failed to add printer");
6824 result = ex ? rex.out.result : r.out.result;
6825 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6826 "unexpected result code");
6828 info2.printername = printername;
6830 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6831 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6832 "failed to add printer");
6833 result = ex ? rex.out.result : r.out.result;
6835 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6836 struct policy_handle printer_handle;
6838 if (existing_printer_deleted) {
6839 torture_fail(tctx, "already deleted printer still existing?");
6842 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6843 "failed to open printer handle");
6845 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6846 "failed to delete printer");
6848 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6849 "failed to close server handle");
6851 existing_printer_deleted = true;
6853 goto again;
6856 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6857 "unexpected result code");
6859 info2.portname = portname;
6861 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6862 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6863 "failed to add printer");
6864 result = ex ? rex.out.result : r.out.result;
6865 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6866 "unexpected result code");
6868 info2.drivername = drivername;
6870 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6871 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6872 "failed to add printer");
6873 result = ex ? rex.out.result : r.out.result;
6875 /* w2k8r2 allows to add printer w/o defining printprocessor */
6877 if (!W_ERROR_IS_OK(result)) {
6878 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6879 "unexpected result code");
6881 info2.printprocessor = "winprint";
6883 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6884 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6885 "failed to add printer");
6886 result = ex ? rex.out.result : r.out.result;
6887 torture_assert_werr_ok(tctx, result,
6888 "failed to add printer");
6891 *handle_p = handle;
6893 /* we are paranoid, really check if the printer is there now */
6895 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6896 PRINTER_ENUM_LOCAL, 1,
6897 printername,
6898 &found),
6899 "failed to enum printers");
6900 torture_assert(tctx, found, "failed to find newly added printer");
6902 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6903 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6904 "failed to add printer");
6905 result = ex ? rex.out.result : r.out.result;
6906 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6907 "unexpected result code");
6909 return true;
6912 static bool test_printer_info(struct torture_context *tctx,
6913 void *private_data)
6915 struct torture_printer_context *t =
6916 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6917 struct dcerpc_pipe *p = t->spoolss_pipe;
6918 struct dcerpc_binding_handle *b = p->binding_handle;
6920 bool ret = true;
6922 if (torture_setting_bool(tctx, "samba3", false)) {
6923 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6926 if (!test_PrinterInfo(tctx, b, &t->handle)) {
6927 ret = false;
6930 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
6931 ret = false;
6934 return ret;
6937 static bool test_EnumPrinterKey(struct torture_context *tctx,
6938 struct dcerpc_binding_handle *b,
6939 struct policy_handle *handle,
6940 const char *key_name,
6941 const char ***array)
6943 struct spoolss_EnumPrinterKey r;
6944 uint32_t needed = 0;
6945 union spoolss_KeyNames key_buffer;
6946 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6947 uint32_t _ndr_size;
6948 int i;
6950 r.in.handle = handle;
6951 r.in.key_name = key_name;
6952 r.out.key_buffer = &key_buffer;
6953 r.out.needed = &needed;
6954 r.out._ndr_size = &_ndr_size;
6956 for (i=0; i < ARRAY_SIZE(offered); i++) {
6958 if (offered[i] < 0 && needed) {
6959 if (needed <= 4) {
6960 continue;
6962 r.in.offered = needed + offered[i];
6963 } else {
6964 r.in.offered = offered[i];
6967 ZERO_STRUCT(key_buffer);
6969 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6971 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6972 "failed to call EnumPrinterKey");
6973 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6975 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6976 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6977 _ndr_size, r.in.offered/2));
6979 r.in.offered = needed;
6980 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6981 "failed to call EnumPrinterKey");
6984 if (offered[i] > 0) {
6985 torture_assert_werr_ok(tctx, r.out.result,
6986 "failed to call EnumPrinterKey");
6989 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6990 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6991 _ndr_size, r.in.offered/2));
6993 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6994 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6996 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6997 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6999 if (key_buffer.string_array) {
7000 uint32_t calc_needed = 0;
7001 int s;
7002 for (s=0; key_buffer.string_array[s]; s++) {
7003 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7005 if (!key_buffer.string_array[0]) {
7006 calc_needed += 2;
7008 calc_needed += 2;
7010 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7011 "EnumPrinterKey unexpected size");
7015 if (array) {
7016 *array = key_buffer.string_array;
7019 return true;
7022 bool test_printer_all_keys(struct torture_context *tctx,
7023 struct dcerpc_binding_handle *b,
7024 struct policy_handle *handle)
7026 const char **key_array = NULL;
7027 int i;
7029 torture_comment(tctx, "Testing Printer Keys\n");
7031 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7032 "failed to call test_EnumPrinterKey");
7034 for (i=0; key_array && key_array[i]; i++) {
7035 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7036 "failed to call test_EnumPrinterKey");
7038 for (i=0; key_array && key_array[i]; i++) {
7039 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7040 "failed to call test_EnumPrinterDataEx");
7043 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7045 return true;
7048 static bool test_openprinter_wrap(struct torture_context *tctx,
7049 void *private_data)
7051 struct torture_printer_context *t =
7052 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7053 struct dcerpc_pipe *p = t->spoolss_pipe;
7054 struct dcerpc_binding_handle *b = p->binding_handle;
7055 const char *printername = t->info2.printername;
7057 return test_openprinter(tctx, b, printername);
7060 static bool test_csetprinter(struct torture_context *tctx,
7061 void *private_data)
7063 struct torture_printer_context *t =
7064 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7065 struct dcerpc_pipe *p = t->spoolss_pipe;
7067 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7068 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7069 const char *portname = t->info2.portname;
7071 union spoolss_PrinterInfo info;
7072 struct policy_handle new_handle, new_handle2;
7073 struct dcerpc_binding_handle *b = p->binding_handle;
7075 torture_comment(tctx, "Testing c_setprinter\n");
7077 torture_assert(tctx,
7078 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7079 "failed to get level 0 printer info");
7080 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7081 info.info0.c_setprinter);
7083 /* check if c_setprinter on 1st handle increases after a printer has
7084 * been added */
7086 torture_assert(tctx,
7087 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7088 "failed to add new printer");
7089 torture_assert(tctx,
7090 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7091 "failed to get level 0 printer info");
7092 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7093 info.info0.c_setprinter);
7095 /* check if c_setprinter on new handle increases after a printer has
7096 * been added */
7098 torture_assert(tctx,
7099 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7100 "failed to get level 0 printer info");
7101 torture_comment(tctx, "csetprinter on created handle: %d\n",
7102 info.info0.c_setprinter);
7104 /* open the new printer and check if c_setprinter increases */
7106 torture_assert(tctx,
7107 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7108 "failed to open created printer");
7109 torture_assert(tctx,
7110 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7111 "failed to get level 0 printer info");
7112 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7113 info.info0.c_setprinter);
7115 /* cleanup */
7117 torture_assert(tctx,
7118 test_ClosePrinter(tctx, b, &new_handle2),
7119 "failed to close printer");
7120 torture_assert(tctx,
7121 test_DeletePrinter(tctx, b, &new_handle),
7122 "failed to delete new printer");
7124 return true;
7127 static bool compose_local_driver_directory(struct torture_context *tctx,
7128 const char *environment,
7129 const char *local_dir,
7130 const char **path)
7132 char *p;
7134 p = strrchr(local_dir, '/');
7135 if (!p) {
7136 return NULL;
7138 p++;
7140 if (strequal(environment, "Windows x64")) {
7141 if (!strequal(p, "x64")) {
7142 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7144 } else if (strequal(environment, "Windows NT x86")) {
7145 if (!strequal(p, "i386")) {
7146 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7148 } else {
7149 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7152 return true;
7155 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7156 const char *devicename)
7158 struct spoolss_DeviceMode *r;
7160 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7161 if (r == NULL) {
7162 return NULL;
7165 r->devicename = talloc_strdup(r, devicename);
7166 r->specversion = DMSPEC_NT4_AND_ABOVE;
7167 r->driverversion = 0x0600;
7168 r->size = 0x00dc;
7169 r->__driverextra_length = 0;
7170 r->fields = DEVMODE_FORMNAME |
7171 DEVMODE_TTOPTION |
7172 DEVMODE_PRINTQUALITY |
7173 DEVMODE_DEFAULTSOURCE |
7174 DEVMODE_COPIES |
7175 DEVMODE_SCALE |
7176 DEVMODE_PAPERSIZE |
7177 DEVMODE_ORIENTATION;
7178 r->orientation = DMORIENT_PORTRAIT;
7179 r->papersize = DMPAPER_LETTER;
7180 r->paperlength = 0;
7181 r->paperwidth = 0;
7182 r->scale = 100;
7183 r->copies = 55;
7184 r->defaultsource = DMBIN_FORMSOURCE;
7185 r->printquality = DMRES_HIGH;
7186 r->color = DMRES_MONOCHROME;
7187 r->duplex = DMDUP_SIMPLEX;
7188 r->yresolution = 0;
7189 r->ttoption = DMTT_SUBDEV;
7190 r->collate = DMCOLLATE_FALSE;
7191 r->formname = talloc_strdup(r, "Letter");
7193 return r;
7196 static bool test_architecture_buffer(struct torture_context *tctx,
7197 void *private_data)
7199 struct test_spoolss_context *ctx =
7200 talloc_get_type_abort(private_data, struct test_spoolss_context);
7202 struct spoolss_OpenPrinterEx r;
7203 struct spoolss_UserLevel1 u1;
7204 struct policy_handle handle;
7205 uint32_t architectures[] = {
7206 PROCESSOR_ARCHITECTURE_INTEL,
7207 PROCESSOR_ARCHITECTURE_IA64,
7208 PROCESSOR_ARCHITECTURE_AMD64
7210 uint32_t needed[3];
7211 int i;
7212 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7213 struct dcerpc_binding_handle *b = p->binding_handle;
7215 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7217 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7219 u1.size = 0;
7220 u1.client = NULL;
7221 u1.user = NULL;
7222 u1.build = 0;
7223 u1.major = 3;
7224 u1.minor = 0;
7225 u1.processor = architectures[i];
7227 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7228 r.in.datatype = NULL;
7229 r.in.devmode_ctr.devmode= NULL;
7230 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7231 r.in.level = 1;
7232 r.in.userlevel.level1 = &u1;
7233 r.out.handle = &handle;
7235 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7236 torture_assert_werr_ok(tctx, r.out.result, "");
7239 struct spoolss_EnumPrinters e;
7240 uint32_t count;
7241 union spoolss_PrinterInfo *info;
7243 e.in.flags = PRINTER_ENUM_LOCAL;
7244 e.in.server = NULL;
7245 e.in.level = 2;
7246 e.in.buffer = NULL;
7247 e.in.offered = 0;
7248 e.out.count = &count;
7249 e.out.info = &info;
7250 e.out.needed = &needed[i];
7252 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7253 #if 0
7254 torture_comment(tctx, "needed was %d\n", needed[i]);
7255 #endif
7258 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7261 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7262 if (needed[i-1] != needed[i]) {
7263 torture_fail(tctx,
7264 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7265 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7269 return true;
7272 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7273 void *private_data)
7275 struct test_spoolss_context *ctx =
7276 talloc_get_type_abort(private_data, struct test_spoolss_context);
7277 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7278 struct dcerpc_binding_handle *b = p->binding_handle;
7280 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7283 static bool test_PrintServer_Forms(struct torture_context *tctx,
7284 void *private_data)
7286 struct test_spoolss_context *ctx =
7287 talloc_get_type_abort(private_data, struct test_spoolss_context);
7288 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7289 struct dcerpc_binding_handle *b = p->binding_handle;
7291 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7294 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7295 void *private_data)
7297 struct test_spoolss_context *ctx =
7298 talloc_get_type_abort(private_data, struct test_spoolss_context);
7299 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7300 struct dcerpc_binding_handle *b = p->binding_handle;
7302 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7305 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7307 NTSTATUS status;
7309 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7311 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7313 torture_assert(tctx,
7314 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7315 "failed to open printserver");
7316 torture_assert(tctx,
7317 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7318 "failed to get environment");
7320 return true;
7323 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7325 struct test_spoolss_context *t;
7327 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7329 return torture_rpc_spoolss_setup_common(tctx, t);
7332 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7334 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7336 return true;
7339 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7341 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7342 bool ret;
7344 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7345 talloc_free(t);
7347 return ret;
7350 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7352 struct dcerpc_pipe *p;
7353 struct dcerpc_binding_handle *b;
7354 const char *server_name_slash;
7355 const char *driver_name;
7356 const char *printer_name;
7357 const char *port_name;
7359 torture_assert_ntstatus_ok(tctx,
7360 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7361 "Error connecting to server");
7363 p = t->spoolss_pipe;
7364 b = p->binding_handle;
7365 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7367 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7368 t->driver.info8.driver_name = TORTURE_DRIVER;
7369 t->driver.info8.driver_path = "pscript5.dll";
7370 t->driver.info8.data_file = "cups6.ppd";
7371 t->driver.info8.config_file = "ps5ui.dll";
7372 t->driver.info8.help_file = "pscript.hlp";
7373 t->driver.info8.default_datatype = "RAW";
7374 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7375 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7376 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7377 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7378 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7379 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7380 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7381 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7382 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7383 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7385 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7387 t->info2.drivername = "Microsoft XPS Document Writer";
7388 t->info2.portname = "LPT1:";
7390 printer_name = t->info2.printername;
7391 port_name = t->info2.portname;
7393 torture_assert(tctx,
7394 fillup_printserver_info(tctx, p, &t->driver),
7395 "failed to fillup printserver info");
7397 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7399 torture_assert(tctx,
7400 compose_local_driver_directory(tctx, t->driver.remote.environment,
7401 t->driver.local.driver_directory,
7402 &t->driver.local.driver_directory),
7403 "failed to compose local driver directory");
7405 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
7406 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7407 t->info2.drivername, t->driver.remote.environment);
7408 t->have_driver = true;
7409 goto try_add;
7412 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7413 t->info2.drivername, t->driver.remote.environment);
7414 torture_comment(tctx, "trying to upload own driver\n");
7416 if (!directory_exist(t->driver.local.driver_directory)) {
7417 torture_warning(tctx, "no local driver is available!");
7418 t->have_driver = false;
7419 goto try_add;
7422 torture_assert(tctx,
7423 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7424 "failed to upload printer driver");
7426 torture_assert(tctx,
7427 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
7428 "failed to add driver");
7430 t->added_driver = true;
7431 t->have_driver = true;
7433 try_add:
7434 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7436 if (t->wellknown) {
7437 torture_assert(tctx,
7438 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7439 "failed to add wellknown printer");
7440 } else {
7441 torture_assert(tctx,
7442 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7443 "failed to add printer");
7446 return true;
7449 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7451 struct torture_printer_context *t;
7453 *data = t = talloc_zero(tctx, struct torture_printer_context);
7455 t->ex = false;
7456 t->wellknown = false;
7457 t->info2.printername = TORTURE_PRINTER;
7458 t->devmode = NULL;
7460 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7463 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7465 struct torture_printer_context *t;
7467 *data = t = talloc_zero(tctx, struct torture_printer_context);
7469 t->ex = true;
7470 t->wellknown = false;
7471 t->info2.printername = TORTURE_PRINTER_EX;
7472 t->devmode = NULL;
7474 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7477 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7479 struct torture_printer_context *t;
7481 *data = t = talloc_zero(tctx, struct torture_printer_context);
7483 t->ex = false;
7484 t->wellknown = true;
7485 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7486 t->devmode = NULL;
7488 if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7489 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7492 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7495 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7497 struct torture_printer_context *t;
7499 *data = t = talloc_zero(tctx, struct torture_printer_context);
7501 t->ex = true;
7502 t->wellknown = true;
7503 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7504 t->devmode = NULL;
7506 if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7507 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7510 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7513 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7515 struct torture_printer_context *t;
7517 *data = t = talloc_zero(tctx, struct torture_printer_context);
7519 t->ex = true;
7520 t->wellknown = false;
7521 t->info2.printername = TORTURE_PRINTER_EX;
7522 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7524 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7527 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7529 bool found = false;
7530 struct dcerpc_pipe *p = t->spoolss_pipe;
7531 struct dcerpc_binding_handle *b;
7532 const char *printer_name = t->info2.printername;
7534 if (t->added_driver) {
7535 torture_assert(tctx,
7536 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7537 "failed to remove printer driver");
7540 if (p) {
7541 b = p->binding_handle;
7544 if (!t->wellknown) {
7545 torture_assert(tctx,
7546 test_DeletePrinter(tctx, b, &t->handle),
7547 "failed to delete printer");
7549 torture_assert(tctx,
7550 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7551 printer_name, &found),
7552 "failed to enumerate printers");
7554 torture_assert(tctx, !found, "deleted printer still there");
7557 return true;
7560 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7562 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7563 bool ret;
7565 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7566 talloc_free(t);
7568 return ret;
7571 static bool test_print_test(struct torture_context *tctx,
7572 void *private_data)
7574 struct torture_printer_context *t =
7575 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7576 struct dcerpc_pipe *p = t->spoolss_pipe;
7577 struct dcerpc_binding_handle *b = p->binding_handle;
7579 torture_assert(tctx,
7580 test_PausePrinter(tctx, b, &t->handle),
7581 "failed to pause printer");
7583 torture_assert(tctx,
7584 test_DoPrintTest(tctx, b, &t->handle),
7585 "failed to do print test");
7587 torture_assert(tctx,
7588 test_ResumePrinter(tctx, b, &t->handle),
7589 "failed to resume printer");
7591 return true;
7594 static bool test_print_test_extended(struct torture_context *tctx,
7595 void *private_data)
7597 struct torture_printer_context *t =
7598 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7599 struct dcerpc_pipe *p = t->spoolss_pipe;
7600 struct dcerpc_binding_handle *b = p->binding_handle;
7601 bool ret = true;
7603 torture_assert(tctx,
7604 test_PausePrinter(tctx, b, &t->handle),
7605 "failed to pause printer");
7607 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7608 if (ret == false) {
7609 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7610 if (torture_setting_bool(tctx, "samba3", false)) {
7611 torture_comment(tctx, "non-critical for samba3\n");
7612 ret = true;
7613 tctx->last_result = TORTURE_SKIP;
7617 torture_assert(tctx,
7618 test_ResumePrinter(tctx, b, &t->handle),
7619 "failed to resume printer");
7621 return ret;
7624 static bool test_printer_sd(struct torture_context *tctx,
7625 void *private_data)
7627 struct torture_printer_context *t =
7628 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7629 struct dcerpc_pipe *p = t->spoolss_pipe;
7630 struct dcerpc_binding_handle *b = p->binding_handle;
7632 torture_assert(tctx,
7633 test_PrinterInfo_SD(tctx, b, &t->handle),
7634 "failed to test security descriptors");
7636 return true;
7639 static bool test_printer_dm(struct torture_context *tctx,
7640 void *private_data)
7642 struct torture_printer_context *t =
7643 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7644 struct dcerpc_pipe *p = t->spoolss_pipe;
7646 torture_assert(tctx,
7647 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7648 "failed to test devicemodes");
7650 return true;
7653 static bool test_printer_info_winreg(struct torture_context *tctx,
7654 void *private_data)
7656 struct torture_printer_context *t =
7657 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7658 struct dcerpc_pipe *p = t->spoolss_pipe;
7660 torture_assert(tctx,
7661 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7662 "failed to test printer info winreg");
7664 return true;
7667 static bool test_printer_change_id(struct torture_context *tctx,
7668 void *private_data)
7670 struct torture_printer_context *t =
7671 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7672 struct dcerpc_pipe *p = t->spoolss_pipe;
7674 torture_assert(tctx,
7675 test_ChangeID(tctx, p, &t->handle),
7676 "failed to test change id");
7678 return true;
7681 static bool test_printer_keys(struct torture_context *tctx,
7682 void *private_data)
7684 struct torture_printer_context *t =
7685 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7686 struct dcerpc_pipe *p = t->spoolss_pipe;
7687 struct dcerpc_binding_handle *b = p->binding_handle;
7689 torture_assert(tctx,
7690 test_printer_all_keys(tctx, b, &t->handle),
7691 "failed to test printer keys");
7693 return true;
7696 static bool test_printer_data_consistency(struct torture_context *tctx,
7697 void *private_data)
7699 struct torture_printer_context *t =
7700 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7701 struct dcerpc_pipe *p = t->spoolss_pipe;
7703 torture_assert(tctx,
7704 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7705 "failed to test printer data consistency");
7707 return true;
7710 static bool test_printer_data_keys(struct torture_context *tctx,
7711 void *private_data)
7713 struct torture_printer_context *t =
7714 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7715 struct dcerpc_pipe *p = t->spoolss_pipe;
7717 torture_assert(tctx,
7718 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7719 "failed to test printer data keys");
7721 return true;
7724 static bool test_printer_data_values(struct torture_context *tctx,
7725 void *private_data)
7727 struct torture_printer_context *t =
7728 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7729 struct dcerpc_pipe *p = t->spoolss_pipe;
7731 torture_assert(tctx,
7732 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7733 "failed to test printer data values");
7735 return true;
7738 static bool test_printer_data_set(struct torture_context *tctx,
7739 void *private_data)
7741 struct torture_printer_context *t =
7742 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7743 struct dcerpc_pipe *p = t->spoolss_pipe;
7745 torture_assert(tctx,
7746 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7747 "failed to test printer data set");
7749 return true;
7752 static bool test_printer_data_winreg(struct torture_context *tctx,
7753 void *private_data)
7755 struct torture_printer_context *t =
7756 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7757 struct dcerpc_pipe *p = t->spoolss_pipe;
7759 torture_assert(tctx,
7760 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7761 "failed to test printer data winreg");
7763 return true;
7766 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7767 void *private_data)
7769 struct torture_printer_context *t =
7770 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7771 struct dcerpc_pipe *p = t->spoolss_pipe;
7773 torture_assert(tctx,
7774 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7775 "failed to test printer data winreg dsspooler");
7777 return true;
7780 static bool test_driver_info_winreg(struct torture_context *tctx,
7781 void *private_data)
7783 struct torture_printer_context *t =
7784 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7785 struct dcerpc_pipe *p = t->spoolss_pipe;
7786 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7788 if (!t->have_driver) {
7789 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7792 torture_assert(tctx,
7793 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
7794 "failed to test driver info winreg");
7796 return true;
7799 void torture_tcase_printer(struct torture_tcase *tcase)
7801 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7802 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7803 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7804 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7805 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7806 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7807 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7808 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7809 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7810 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7811 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7812 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7813 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7814 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7815 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7816 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7817 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7818 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7821 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7823 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7824 struct torture_tcase *tcase;
7826 tcase = torture_suite_add_tcase(suite, "addprinter");
7828 torture_tcase_set_fixture(tcase,
7829 torture_rpc_spoolss_printer_setup,
7830 torture_rpc_spoolss_printer_teardown);
7832 torture_tcase_printer(tcase);
7834 tcase = torture_suite_add_tcase(suite, "addprinterex");
7836 torture_tcase_set_fixture(tcase,
7837 torture_rpc_spoolss_printerex_setup,
7838 torture_rpc_spoolss_printer_teardown);
7840 torture_tcase_printer(tcase);
7842 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7844 torture_tcase_set_fixture(tcase,
7845 torture_rpc_spoolss_printerwkn_setup,
7846 torture_rpc_spoolss_printer_teardown);
7848 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7850 torture_tcase_set_fixture(tcase,
7851 torture_rpc_spoolss_printerexwkn_setup,
7852 torture_rpc_spoolss_printer_teardown);
7854 #if 0
7855 /* test is not correct */
7856 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7858 torture_tcase_set_fixture(tcase,
7859 torture_rpc_spoolss_printerdm_setup,
7860 torture_rpc_spoolss_printer_teardown);
7862 torture_tcase_printer(tcase);
7863 #endif
7864 return suite;
7867 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7869 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7870 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7872 torture_tcase_set_fixture(tcase,
7873 torture_rpc_spoolss_setup,
7874 torture_rpc_spoolss_teardown);
7876 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7877 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7878 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7879 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7880 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7881 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7882 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7883 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7884 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7885 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7886 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7887 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7888 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7889 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7890 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7891 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7892 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7893 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7894 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7895 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7897 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7899 return suite;
7902 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7903 struct dcerpc_binding_handle *b,
7904 const char *server,
7905 const char *environment,
7906 const char **dir_p)
7908 struct spoolss_GetPrinterDriverDirectory r;
7909 uint32_t needed;
7911 r.in.server = server;
7912 r.in.environment = environment;
7913 r.in.level = 1;
7914 r.in.buffer = NULL;
7915 r.in.offered = 0;
7916 r.out.needed = &needed;
7918 torture_assert_ntstatus_ok(tctx,
7919 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7920 "failed to query driver directory");
7922 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7923 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7924 r.in.buffer = &blob;
7925 r.in.offered = needed;
7927 torture_assert_ntstatus_ok(tctx,
7928 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7929 "failed to query driver directory");
7932 torture_assert_werr_ok(tctx, r.out.result,
7933 "failed to query driver directory");
7935 if (dir_p) {
7936 *dir_p = r.out.info->info1.directory_name;
7939 return true;
7942 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7944 if (info_ctr == NULL) {
7945 return NULL;
7948 switch (info_ctr->level) {
7949 case 1:
7950 return info_ctr->info.info1->driver_name;
7951 case 2:
7952 return info_ctr->info.info2->driver_name;
7953 case 3:
7954 return info_ctr->info.info3->driver_name;
7955 case 4:
7956 return info_ctr->info.info4->driver_name;
7957 case 6:
7958 return info_ctr->info.info6->driver_name;
7959 case 8:
7960 return info_ctr->info.info8->driver_name;
7961 default:
7962 return NULL;
7966 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7968 if (info_ctr == NULL) {
7969 return NULL;
7972 switch (info_ctr->level) {
7973 case 2:
7974 return info_ctr->info.info2->architecture;
7975 case 3:
7976 return info_ctr->info.info3->architecture;
7977 case 4:
7978 return info_ctr->info.info4->architecture;
7979 case 6:
7980 return info_ctr->info.info6->architecture;
7981 case 8:
7982 return info_ctr->info.info8->architecture;
7983 default:
7984 return NULL;
7989 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7990 struct dcerpc_binding_handle *b,
7991 const char *servername,
7992 struct spoolss_AddDriverInfoCtr *info_ctr,
7993 WERROR expected_result)
7995 struct spoolss_AddPrinterDriver r;
7996 const char *drivername = get_driver_from_info(info_ctr);
7997 const char *environment = get_environment_from_info(info_ctr);
7999 r.in.servername = servername;
8000 r.in.info_ctr = info_ctr;
8002 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8003 drivername, info_ctr->level, environment);
8005 torture_assert_ntstatus_ok(tctx,
8006 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8007 "spoolss_AddPrinterDriver failed");
8008 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8009 "spoolss_AddPrinterDriver failed with unexpected result");
8011 return true;
8015 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8016 struct dcerpc_binding_handle *b,
8017 const char *servername,
8018 struct spoolss_AddDriverInfoCtr *info_ctr,
8019 uint32_t flags,
8020 WERROR expected_result)
8022 struct spoolss_AddPrinterDriverEx r;
8023 const char *drivername = get_driver_from_info(info_ctr);
8024 const char *environment = get_environment_from_info(info_ctr);
8026 r.in.servername = servername;
8027 r.in.info_ctr = info_ctr;
8028 r.in.flags = flags;
8030 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8031 drivername, info_ctr->level, environment);
8033 torture_assert_ntstatus_ok(tctx,
8034 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8035 "AddPrinterDriverEx failed");
8036 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8037 "AddPrinterDriverEx failed with unexpected result");
8039 return true;
8042 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8043 struct dcerpc_binding_handle *b,
8044 const char *server_name,
8045 struct spoolss_AddDriverInfo8 *r,
8046 uint32_t flags,
8047 bool ex)
8049 struct spoolss_AddDriverInfoCtr info_ctr;
8050 struct spoolss_AddDriverInfo1 info1;
8052 ZERO_STRUCT(info1);
8054 info_ctr.level = 1;
8055 info_ctr.info.info1 = &info1;
8057 if (ex) {
8058 torture_assert(tctx,
8059 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8060 "failed to test AddPrinterDriverEx level 1");
8061 } else {
8062 torture_assert(tctx,
8063 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8064 "failed to test AddPrinterDriver level 1");
8067 info1.driver_name = r->driver_name;
8069 if (ex) {
8070 torture_assert(tctx,
8071 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8072 "failed to test AddPrinterDriverEx level 1");
8073 } else {
8074 torture_assert(tctx,
8075 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8076 "failed to test AddPrinterDriver level 1");
8079 return true;
8082 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8083 struct dcerpc_binding_handle *b,
8084 const char *server_name,
8085 struct spoolss_AddDriverInfo8 *r,
8086 uint32_t flags,
8087 bool ex)
8089 struct spoolss_AddDriverInfoCtr info_ctr;
8090 struct spoolss_AddDriverInfo2 info2;
8092 ZERO_STRUCT(info2);
8094 info_ctr.level = 2;
8095 info_ctr.info.info2 = &info2;
8097 if (ex) {
8098 torture_assert(tctx,
8099 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8100 "failed to test AddPrinterDriverEx level 2");
8101 } else {
8102 torture_assert(tctx,
8103 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8104 "failed to test AddPrinterDriver level 2");
8107 info2.driver_name = r->driver_name;
8109 if (ex) {
8110 torture_assert(tctx,
8111 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8112 "failed to test AddPrinterDriverEx level 2");
8113 } else {
8114 torture_assert(tctx,
8115 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8116 "failed to test AddPrinterDriver level 2");
8119 info2.version = r->version;
8121 if (ex) {
8122 torture_assert(tctx,
8123 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8124 "failed to test AddPrinterDriverEx level 2");
8125 } else {
8126 torture_assert(tctx,
8127 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8128 "failed to test AddPrinterDriver level 2");
8131 info2.architecture = r->architecture;
8133 if (ex) {
8134 torture_assert(tctx,
8135 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8136 "failed to test AddPrinterDriverEx level 2");
8137 } else {
8138 torture_assert(tctx,
8139 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8140 "failed to test AddPrinterDriver level 2");
8143 info2.driver_path = r->driver_path;
8145 if (ex) {
8146 torture_assert(tctx,
8147 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8148 "failed to test AddPrinterDriverEx level 2");
8149 } else {
8150 torture_assert(tctx,
8151 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8152 "failed to test AddPrinterDriver level 2");
8155 info2.data_file = r->data_file;
8157 if (ex) {
8158 torture_assert(tctx,
8159 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8160 "failed to test AddPrinterDriverEx level 2");
8161 } else {
8162 torture_assert(tctx,
8163 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8164 "failed to test AddPrinterDriver level 2");
8167 info2.config_file = r->config_file;
8169 if (ex) {
8170 torture_assert(tctx,
8171 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8172 "failed to test AddPrinterDriverEx");
8175 if (ex) {
8176 torture_assert(tctx,
8177 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8178 "failed to test AddPrinterDriverEx level 2");
8179 } else {
8180 torture_assert(tctx,
8181 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8182 "failed to test AddPrinterDriver level 2");
8185 torture_assert(tctx,
8186 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
8187 "failed to find added printer driver");
8189 return true;
8192 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8193 struct dcerpc_binding_handle *b,
8194 const char *server_name,
8195 struct spoolss_AddDriverInfo8 *r,
8196 uint32_t flags,
8197 bool ex)
8199 struct spoolss_AddDriverInfoCtr info_ctr;
8200 struct spoolss_AddDriverInfo3 info3;
8202 info3.driver_name = r->driver_name;
8203 info3.version = r->version;
8204 info3.architecture = r->architecture;
8205 info3.driver_path = r->driver_path;
8206 info3.data_file = r->data_file;
8207 info3.config_file = r->config_file;
8208 info3.help_file = r->help_file;
8209 info3.monitor_name = r->monitor_name;
8210 info3.default_datatype = r->default_datatype;
8211 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8212 info3.dependent_files = r->dependent_files;
8214 info_ctr.level = 3;
8215 info_ctr.info.info3 = &info3;
8217 if (ex) {
8218 torture_assert(tctx,
8219 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8220 "failed to test AddPrinterDriverEx level 3");
8221 } else {
8222 torture_assert(tctx,
8223 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8224 "failed to test AddPrinterDriver level 3");
8227 torture_assert(tctx,
8228 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
8229 "failed to find added printer driver");
8231 return true;
8234 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8235 struct dcerpc_binding_handle *b,
8236 const char *server_name,
8237 struct spoolss_AddDriverInfo8 *r,
8238 uint32_t flags,
8239 bool ex)
8241 struct spoolss_AddDriverInfoCtr info_ctr;
8242 struct spoolss_AddDriverInfo4 info4;
8244 info4.version = r->version;
8245 info4.driver_name = r->driver_name;
8246 info4.architecture = r->architecture;
8247 info4.driver_path = r->driver_path;
8248 info4.data_file = r->data_file;
8249 info4.config_file = r->config_file;
8250 info4.help_file = r->help_file;
8251 info4.monitor_name = r->monitor_name;
8252 info4.default_datatype = r->default_datatype;
8253 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8254 info4.dependent_files = r->dependent_files;
8255 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8256 info4.previous_names = r->previous_names;
8258 info_ctr.level = 4;
8259 info_ctr.info.info4 = &info4;
8261 if (ex) {
8262 torture_assert(tctx,
8263 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8264 "failed to test AddPrinterDriverEx level 4");
8265 } else {
8266 torture_assert(tctx,
8267 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8268 "failed to test AddPrinterDriver level 4");
8271 torture_assert(tctx,
8272 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
8273 "failed to find added printer driver");
8275 return true;
8278 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8279 struct dcerpc_binding_handle *b,
8280 const char *server_name,
8281 struct spoolss_AddDriverInfo8 *r,
8282 uint32_t flags,
8283 bool ex)
8285 struct spoolss_AddDriverInfoCtr info_ctr;
8286 struct spoolss_AddDriverInfo6 info6;
8288 info6.version = r->version;
8289 info6.driver_name = r->driver_name;
8290 info6.architecture = r->architecture;
8291 info6.driver_path = r->driver_path;
8292 info6.data_file = r->data_file;
8293 info6.config_file = r->config_file;
8294 info6.help_file = r->help_file;
8295 info6.monitor_name = r->monitor_name;
8296 info6.default_datatype = r->default_datatype;
8297 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8298 info6.dependent_files = r->dependent_files;
8299 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8300 info6.previous_names = r->previous_names;
8301 info6.driver_date = r->driver_date;
8302 info6.driver_version = r->driver_version;
8303 info6.manufacturer_name = r->manufacturer_name;
8304 info6.manufacturer_url = r->manufacturer_url;
8305 info6.hardware_id = r->hardware_id;
8306 info6.provider = r->provider;
8308 info_ctr.level = 6;
8309 info_ctr.info.info6 = &info6;
8311 if (ex) {
8312 torture_assert(tctx,
8313 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8314 "failed to test AddPrinterDriverEx level 6");
8315 } else {
8316 torture_assert(tctx,
8317 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8318 "failed to test AddPrinterDriver level 6");
8321 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8323 if (!ex) {
8324 return true;
8327 torture_assert(tctx,
8328 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
8329 "failed to find added printer driver");
8331 return true;
8334 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8335 struct dcerpc_binding_handle *b,
8336 const char *server_name,
8337 struct spoolss_AddDriverInfo8 *r,
8338 uint32_t flags,
8339 bool ex)
8341 struct spoolss_AddDriverInfoCtr info_ctr;
8343 info_ctr.level = 8;
8344 info_ctr.info.info8 = r;
8346 if (ex) {
8347 torture_assert(tctx,
8348 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8349 "failed to test AddPrinterDriverEx level 8");
8350 } else {
8351 torture_assert(tctx,
8352 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8353 "failed to test AddPrinterDriver level 8");
8356 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8358 if (!ex) {
8359 return true;
8362 torture_assert(tctx,
8363 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
8364 "failed to find added printer driver");
8366 return true;
8369 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8370 struct dcerpc_binding_handle *b,
8371 const char *server,
8372 const char *driver,
8373 const char *environment,
8374 WERROR expected_result)
8376 struct spoolss_DeletePrinterDriver r;
8378 r.in.server = server;
8379 r.in.architecture = environment;
8380 r.in.driver = driver;
8382 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8384 torture_assert_ntstatus_ok(tctx,
8385 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8386 "DeletePrinterDriver failed");
8387 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8388 "DeletePrinterDriver failed with unexpected result");
8390 return true;
8393 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8394 struct dcerpc_binding_handle *b,
8395 const char *server,
8396 const char *driver,
8397 const char *environment,
8398 uint32_t delete_flags,
8399 uint32_t version,
8400 WERROR expected_result)
8402 struct spoolss_DeletePrinterDriverEx r;
8404 r.in.server = server;
8405 r.in.architecture = environment;
8406 r.in.driver = driver;
8407 r.in.delete_flags = delete_flags;
8408 r.in.version = version;
8410 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8412 torture_assert_ntstatus_ok(tctx,
8413 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8414 "DeletePrinterDriverEx failed");
8415 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8416 "DeletePrinterDriverEx failed with unexpected result");
8418 return true;
8421 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8422 struct dcerpc_binding_handle *b,
8423 const char *server_name,
8424 const char *driver,
8425 const char *environment)
8427 torture_assert(tctx,
8428 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8429 "failed to delete driver");
8431 torture_assert(tctx,
8432 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8433 "failed to delete driver");
8435 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8436 torture_fail(tctx, "deleted driver still enumerated");
8439 torture_assert(tctx,
8440 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8441 "2nd delete failed");
8443 return true;
8446 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8447 struct dcerpc_binding_handle *b,
8448 const char *server_name,
8449 const char *driver,
8450 const char *environment,
8451 uint32_t delete_flags,
8452 uint32_t version)
8454 torture_assert(tctx,
8455 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8456 "failed to delete driver");
8458 torture_assert(tctx,
8459 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8460 "failed to delete driver");
8462 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
8463 torture_fail(tctx, "deleted driver still enumerated");
8466 torture_assert(tctx,
8467 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8468 "2nd delete failed");
8470 return true;
8473 static bool test_PrinterDriver_args(struct torture_context *tctx,
8474 struct dcerpc_binding_handle *b,
8475 const char *server_name,
8476 uint32_t level,
8477 struct spoolss_AddDriverInfo8 *r,
8478 uint32_t add_flags,
8479 uint32_t delete_flags,
8480 uint32_t delete_version,
8481 bool ex)
8483 bool ret = true;
8485 switch (level) {
8486 case 1:
8487 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
8488 break;
8489 case 2:
8490 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
8491 break;
8492 case 3:
8493 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
8494 break;
8495 case 4:
8496 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
8497 break;
8498 case 6:
8499 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
8500 break;
8501 case 8:
8502 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
8503 break;
8504 default:
8505 return false;
8508 if (ret == false) {
8509 return ret;
8512 if (level == 1) {
8513 return ret;
8516 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8518 if (!ex && (level == 6 || level == 8)) {
8519 return ret;
8522 if (ex) {
8523 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8524 } else {
8525 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8529 static bool fillup_printserver_info(struct torture_context *tctx,
8530 struct dcerpc_pipe *p,
8531 struct torture_driver_context *d)
8533 struct policy_handle server_handle;
8534 struct dcerpc_binding_handle *b = p->binding_handle;
8535 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8537 torture_assert(tctx,
8538 test_OpenPrinter_server(tctx, p, &server_handle),
8539 "failed to open printserver");
8540 torture_assert(tctx,
8541 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8542 "failed to get environment");
8543 torture_assert(tctx,
8544 test_ClosePrinter(tctx, b, &server_handle),
8545 "failed to close printserver");
8547 torture_assert(tctx,
8548 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8549 d->local.environment ? d->local.environment : d->remote.environment,
8550 &d->remote.driver_directory),
8551 "failed to get driver directory");
8553 return true;
8556 static const char *driver_directory_dir(const char *driver_directory)
8558 char *p;
8560 p = strrchr(driver_directory, '\\');
8561 if (p) {
8562 return p+1;
8565 return NULL;
8568 static const char *driver_directory_share(struct torture_context *tctx,
8569 const char *driver_directory)
8571 const char *p;
8572 char *tok;
8574 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8575 driver_directory += 2;
8578 p = talloc_strdup(tctx, driver_directory);
8580 torture_assert(tctx,
8581 next_token_talloc(tctx, &p, &tok, "\\"),
8582 "cannot explode uri");
8583 torture_assert(tctx,
8584 next_token_talloc(tctx, &p, &tok, "\\"),
8585 "cannot explode uri");
8587 return tok;
8590 static bool upload_printer_driver_file(struct torture_context *tctx,
8591 struct smbcli_state *cli,
8592 struct torture_driver_context *d,
8593 const char *file_name)
8595 XFILE *f;
8596 int fnum;
8597 uint8_t *buf;
8598 int maxwrite = 64512;
8599 off_t nread = 0;
8600 size_t start = 0;
8601 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8602 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8603 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8605 if (!file_name || strlen(file_name) == 0) {
8606 return true;
8609 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8611 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8612 if (fnum == -1) {
8613 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8616 f = x_fopen(local_name, O_RDONLY, 0);
8617 if (f == NULL) {
8618 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8621 buf = talloc_array(tctx, uint8_t, maxwrite);
8622 if (!buf) {
8623 return false;
8626 while (!x_feof(f)) {
8627 int n = maxwrite;
8628 int ret;
8630 if ((n = x_fread(buf, 1, n, f)) < 1) {
8631 if((n == 0) && x_feof(f))
8632 break; /* Empty local file. */
8634 torture_warning(tctx,
8635 "failed to read file: %s\n", strerror(errno));
8636 break;
8639 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8641 if (n != ret) {
8642 torture_warning(tctx,
8643 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8644 break;
8647 nread += n;
8650 x_fclose(f);
8652 torture_assert_ntstatus_ok(tctx,
8653 smbcli_close(cli->tree, fnum),
8654 "failed to close file");
8656 return true;
8659 static bool connect_printer_driver_share(struct torture_context *tctx,
8660 const char *server_name,
8661 const char *share_name,
8662 struct smbcli_state **cli)
8664 struct smbcli_options smb_options;
8665 struct smbcli_session_options smb_session_options;
8667 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8668 share_name, server_name);
8670 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8671 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8673 torture_assert_ntstatus_ok(tctx,
8674 smbcli_full_connection(tctx, cli, server_name,
8675 lpcfg_smb_ports(tctx->lp_ctx),
8676 share_name, NULL,
8677 lpcfg_socket_options(tctx->lp_ctx),
8678 cmdline_credentials,
8679 lpcfg_resolve_context(tctx->lp_ctx),
8680 tctx->ev,
8681 &smb_options,
8682 &smb_session_options,
8683 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8684 "failed to open driver share");
8686 return true;
8689 static bool upload_printer_driver(struct torture_context *tctx,
8690 const char *server_name,
8691 struct torture_driver_context *d)
8693 struct smbcli_state *cli;
8694 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8695 int i;
8697 torture_assert(tctx,
8698 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8699 "failed to connect to driver share");
8701 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8702 server_name, share_name);
8704 torture_assert(tctx,
8705 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8706 "failed to upload driver_path");
8707 torture_assert(tctx,
8708 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8709 "failed to upload data_file");
8710 torture_assert(tctx,
8711 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8712 "failed to upload config_file");
8713 torture_assert(tctx,
8714 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8715 "failed to upload help_file");
8716 if (d->info8.dependent_files) {
8717 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8718 torture_assert(tctx,
8719 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8720 "failed to upload dependent_files");
8724 talloc_free(cli);
8726 return true;
8729 static bool remove_printer_driver_file(struct torture_context *tctx,
8730 struct smbcli_state *cli,
8731 struct torture_driver_context *d,
8732 const char *file_name)
8734 const char *remote_name;
8735 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8737 if (!file_name || strlen(file_name) == 0) {
8738 return true;
8741 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8743 torture_comment(tctx, "Removing %s\n", remote_name);
8745 torture_assert_ntstatus_ok(tctx,
8746 smbcli_unlink(cli->tree, remote_name),
8747 "failed to unlink");
8749 return true;
8752 static bool remove_printer_driver(struct torture_context *tctx,
8753 const char *server_name,
8754 struct torture_driver_context *d)
8756 struct smbcli_state *cli;
8757 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8758 int i;
8760 torture_assert(tctx,
8761 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8762 "failed to connect to driver share");
8764 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8765 server_name, share_name);
8767 torture_assert(tctx,
8768 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8769 "failed to remove driver_path");
8770 torture_assert(tctx,
8771 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8772 "failed to remove data_file");
8773 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
8774 torture_assert(tctx,
8775 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8776 "failed to remove config_file");
8778 torture_assert(tctx,
8779 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8780 "failed to remove help_file");
8781 if (d->info8.dependent_files) {
8782 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8783 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8784 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8785 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8786 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8787 continue;
8789 torture_assert(tctx,
8790 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8791 "failed to remove dependent_files");
8795 talloc_free(cli);
8797 return true;
8801 static bool test_add_driver_arg(struct torture_context *tctx,
8802 struct dcerpc_pipe *p,
8803 struct torture_driver_context *d)
8805 bool ret = true;
8806 struct dcerpc_binding_handle *b = p->binding_handle;
8807 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8808 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8809 int i;
8810 struct spoolss_AddDriverInfo8 info8;
8811 uint32_t add_flags = APD_COPY_NEW_FILES;
8812 uint32_t delete_flags = 0;
8814 ZERO_STRUCT(info8);
8816 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8817 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8819 torture_assert(tctx,
8820 fillup_printserver_info(tctx, p, d),
8821 "failed to fillup printserver info");
8823 if (!directory_exist(d->local.driver_directory)) {
8824 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8827 torture_assert(tctx,
8828 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8829 "failed to upload printer driver");
8831 info8.version = d->info8.version;
8832 info8.driver_name = d->info8.driver_name;
8833 info8.architecture = d->local.environment;
8834 info8.driver_path = d->info8.driver_path;
8835 info8.data_file = d->info8.data_file;
8836 info8.config_file = d->info8.config_file;
8838 for (i=0; i < ARRAY_SIZE(levels); i++) {
8840 if (torture_setting_bool(tctx, "samba3", false)) {
8841 switch (levels[i]) {
8842 case 2:
8843 case 4:
8844 case 8:
8845 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8846 continue;
8847 default:
8848 break;
8852 torture_comment(tctx,
8853 "Testing PrinterDriver%s '%s' add & delete level %d\n",
8854 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8856 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8859 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8860 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8861 if (d->info8.config_file) {
8862 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8865 for (i=0; i < ARRAY_SIZE(levels); i++) {
8867 if (torture_setting_bool(tctx, "samba3", false)) {
8868 switch (levels[i]) {
8869 case 2:
8870 case 4:
8871 case 8:
8872 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8873 continue;
8874 default:
8875 break;
8880 torture_comment(tctx,
8881 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8882 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8884 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8887 torture_assert(tctx,
8888 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8889 "failed to remove printer driver");
8891 torture_comment(tctx, "\n");
8893 return ret;
8896 static bool test_add_driver_ex_64(struct torture_context *tctx,
8897 struct dcerpc_pipe *p)
8899 struct torture_driver_context *d;
8901 d = talloc_zero(tctx, struct torture_driver_context);
8903 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
8904 d->info8.driver_name = TORTURE_DRIVER_EX;
8905 d->info8.architecture = NULL;
8906 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
8907 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
8908 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
8909 d->local.environment = talloc_strdup(d, "Windows x64");
8910 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8911 d->ex = true;
8913 return test_add_driver_arg(tctx, p, d);
8916 static bool test_add_driver_ex_32(struct torture_context *tctx,
8917 struct dcerpc_pipe *p)
8919 struct torture_driver_context *d;
8921 d = talloc_zero(tctx, struct torture_driver_context);
8923 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
8924 d->info8.driver_name = TORTURE_DRIVER_EX;
8925 d->info8.architecture = NULL;
8926 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
8927 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
8928 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
8929 d->local.environment = talloc_strdup(d, "Windows NT x86");
8930 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8931 d->ex = true;
8933 return test_add_driver_arg(tctx, p, d);
8936 static bool test_add_driver_64(struct torture_context *tctx,
8937 struct dcerpc_pipe *p)
8939 struct torture_driver_context *d;
8941 d = talloc_zero(tctx, struct torture_driver_context);
8943 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
8944 d->info8.driver_name = TORTURE_DRIVER;
8945 d->info8.architecture = NULL;
8946 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
8947 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
8948 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
8949 d->local.environment = talloc_strdup(d, "Windows x64");
8950 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8951 d->ex = false;
8953 return test_add_driver_arg(tctx, p, d);
8956 static bool test_add_driver_32(struct torture_context *tctx,
8957 struct dcerpc_pipe *p)
8959 struct torture_driver_context *d;
8961 d = talloc_zero(tctx, struct torture_driver_context);
8963 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
8964 d->info8.driver_name = TORTURE_DRIVER;
8965 d->info8.architecture = NULL;
8966 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
8967 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
8968 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
8969 d->local.environment = talloc_strdup(d, "Windows NT x86");
8970 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8971 d->ex = false;
8973 return test_add_driver_arg(tctx, p, d);
8976 static bool test_add_driver_adobe(struct torture_context *tctx,
8977 struct dcerpc_pipe *p)
8979 struct torture_driver_context *d;
8981 d = talloc_zero(tctx, struct torture_driver_context);
8983 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
8984 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
8985 d->info8.architecture = NULL;
8986 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
8987 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
8988 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
8989 #if 0
8990 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
8991 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
8992 #endif
8993 d->local.environment = talloc_strdup(d, "Windows 4.0");
8994 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
8995 d->ex = false;
8997 return test_add_driver_arg(tctx, p, d);
9000 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9001 struct dcerpc_pipe *p)
9003 struct torture_driver_context *d;
9004 struct spoolss_StringArray *a;
9006 if (!torture_setting_bool(tctx, "samba3", false)) {
9007 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9010 d = talloc_zero(tctx, struct torture_driver_context);
9012 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9013 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9014 d->info8.architecture = NULL;
9015 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9016 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9017 d->info8.config_file = NULL;
9018 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9019 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9020 d->info8.default_datatype = talloc_strdup(d, "RAW");
9022 a = talloc_zero(d, struct spoolss_StringArray);
9023 a->string = talloc_zero_array(a, const char *, 7);
9024 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9025 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9026 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9027 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9028 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9029 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9031 d->info8.dependent_files = a;
9032 d->local.environment = talloc_strdup(d, "Windows 4.0");
9033 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9034 d->ex = false;
9036 return test_add_driver_arg(tctx, p, d);
9039 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9041 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9043 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9044 "driver", &ndr_table_spoolss);
9045 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9046 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9048 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9049 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9051 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9053 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9055 return suite;