s4-smbtorture: enhance spoolss_EnumPrinterKey torture test.
[Samba/bb.git] / source4 / torture / rpc / spoolss.c
blob7468278e08e2f93704934e1b9cc2406a4baebe68
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
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 "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "param/param.h"
31 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
32 #define TORTURE_PRINTER "torture_printer"
33 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
34 #define TORTURE_PRINTER_EX "torture_printer_ex"
36 struct test_spoolss_context {
37 /* print server handle */
38 struct policy_handle server_handle;
40 /* for EnumPorts */
41 uint32_t port_count[3];
42 union spoolss_PortInfo *ports[3];
44 /* for EnumPrinterDrivers */
45 uint32_t driver_count[8];
46 union spoolss_DriverInfo *drivers[8];
48 /* for EnumMonitors */
49 uint32_t monitor_count[3];
50 union spoolss_MonitorInfo *monitors[3];
52 /* for EnumPrintProcessors */
53 uint32_t print_processor_count[2];
54 union spoolss_PrintProcessorInfo *print_processors[2];
56 /* for EnumPrinters */
57 uint32_t printer_count[6];
58 union spoolss_PrinterInfo *printers[6];
61 #define COMPARE_STRING(tctx, c,r,e) \
62 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
64 /* not every compiler supports __typeof__() */
65 #if (__GNUC__ >= 3)
66 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
67 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
68 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
70 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
71 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
73 } while(0)
74 #else
75 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
76 #endif
78 #define COMPARE_UINT32(tctx, c, r, e) do {\
79 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
80 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
81 } while(0)
83 #define COMPARE_UINT64(tctx, c, r, e) do {\
84 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
85 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
86 } while(0)
89 #define COMPARE_NTTIME(tctx, c, r, e) do {\
90 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
91 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
92 } while(0)
94 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
95 int __i; \
96 if (!c.e && !r.e) { \
97 break; \
98 } \
99 if (c.e && !r.e) { \
100 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
102 if (!c.e && r.e) { \
103 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
105 for (__i=0;c.e[__i] != NULL; __i++) { \
106 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
108 } while(0)
110 static bool test_OpenPrinter_server(struct torture_context *tctx,
111 struct dcerpc_pipe *p,
112 struct policy_handle *server_handle)
114 NTSTATUS status;
115 struct spoolss_OpenPrinter op;
117 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
118 op.in.datatype = NULL;
119 op.in.devmode_ctr.devmode= NULL;
120 op.in.access_mask = 0;
121 op.out.handle = server_handle;
123 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
125 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
126 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
127 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
129 return true;
132 static bool test_EnumPorts(struct torture_context *tctx,
133 struct dcerpc_pipe *p,
134 struct test_spoolss_context *ctx)
136 NTSTATUS status;
137 struct spoolss_EnumPorts r;
138 uint16_t levels[] = { 1, 2 };
139 int i, j;
141 for (i=0;i<ARRAY_SIZE(levels);i++) {
142 int level = levels[i];
143 DATA_BLOB blob;
144 uint32_t needed;
145 uint32_t count;
146 union spoolss_PortInfo *info;
148 r.in.servername = "";
149 r.in.level = level;
150 r.in.buffer = NULL;
151 r.in.offered = 0;
152 r.out.needed = &needed;
153 r.out.count = &count;
154 r.out.info = &info;
156 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
158 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
159 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
160 if (W_ERROR_IS_OK(r.out.result)) {
161 /* TODO: do some more checks here */
162 continue;
164 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
165 "EnumPorts unexpected return code");
167 blob = data_blob_talloc(ctx, NULL, needed);
168 data_blob_clear(&blob);
169 r.in.buffer = &blob;
170 r.in.offered = needed;
172 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
173 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
175 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
177 torture_assert(tctx, info, "EnumPorts returned no info");
179 ctx->port_count[level] = count;
180 ctx->ports[level] = info;
183 for (i=1;i<ARRAY_SIZE(levels);i++) {
184 int level = levels[i];
185 int old_level = levels[i-1];
186 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
187 "EnumPorts invalid value");
189 /* if the array sizes are not the same we would maybe segfault in the following code */
191 for (i=0;i<ARRAY_SIZE(levels);i++) {
192 int level = levels[i];
193 for (j=0;j<ctx->port_count[level];j++) {
194 union spoolss_PortInfo *cur = &ctx->ports[level][j];
195 union spoolss_PortInfo *ref = &ctx->ports[2][j];
196 switch (level) {
197 case 1:
198 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
199 break;
200 case 2:
201 /* level 2 is our reference, and it makes no sense to compare it to itself */
202 break;
207 return true;
210 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
211 struct dcerpc_pipe *p,
212 struct test_spoolss_context *ctx)
214 NTSTATUS status;
215 struct spoolss_GetPrintProcessorDirectory r;
216 struct {
217 uint16_t level;
218 const char *server;
219 } levels[] = {{
220 .level = 1,
221 .server = NULL
223 .level = 1,
224 .server = ""
226 .level = 78,
227 .server = ""
229 .level = 1,
230 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
232 .level = 1024,
233 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
236 int i;
237 uint32_t needed;
239 for (i=0;i<ARRAY_SIZE(levels);i++) {
240 int level = levels[i].level;
241 DATA_BLOB blob;
243 r.in.server = levels[i].server;
244 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
245 r.in.level = level;
246 r.in.buffer = NULL;
247 r.in.offered = 0;
248 r.out.needed = &needed;
250 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
252 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
253 torture_assert_ntstatus_ok(tctx, status,
254 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
255 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
256 "GetPrintProcessorDirectory unexpected return code");
258 blob = data_blob_talloc(ctx, NULL, needed);
259 data_blob_clear(&blob);
260 r.in.buffer = &blob;
261 r.in.offered = needed;
263 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
264 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
266 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
269 return true;
273 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
274 struct dcerpc_pipe *p,
275 struct test_spoolss_context *ctx)
277 NTSTATUS status;
278 struct spoolss_GetPrinterDriverDirectory r;
279 struct {
280 uint16_t level;
281 const char *server;
282 } levels[] = {{
283 .level = 1,
284 .server = NULL
286 .level = 1,
287 .server = ""
289 .level = 78,
290 .server = ""
292 .level = 1,
293 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
295 .level = 1024,
296 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
299 int i;
300 uint32_t needed;
302 for (i=0;i<ARRAY_SIZE(levels);i++) {
303 int level = levels[i].level;
304 DATA_BLOB blob;
306 r.in.server = levels[i].server;
307 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
308 r.in.level = level;
309 r.in.buffer = NULL;
310 r.in.offered = 0;
311 r.out.needed = &needed;
313 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
315 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
316 torture_assert_ntstatus_ok(tctx, status,
317 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
318 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
319 "GetPrinterDriverDirectory unexpected return code");
321 blob = data_blob_talloc(ctx, NULL, needed);
322 data_blob_clear(&blob);
323 r.in.buffer = &blob;
324 r.in.offered = needed;
326 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
327 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
329 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
332 return true;
335 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
336 struct dcerpc_pipe *p,
337 struct test_spoolss_context *ctx,
338 const char *architecture)
340 NTSTATUS status;
341 struct spoolss_EnumPrinterDrivers r;
342 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
343 int i, j;
345 for (i=0;i<ARRAY_SIZE(levels);i++) {
346 int level = levels[i];
347 DATA_BLOB blob;
348 uint32_t needed;
349 uint32_t count;
350 union spoolss_DriverInfo *info;
352 /* FIXME: gd, come back and fix "" as server, and handle
353 * priority of returned error codes in torture test and samba 3
354 * server */
356 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
357 r.in.environment = architecture;
358 r.in.level = level;
359 r.in.buffer = NULL;
360 r.in.offered = 0;
361 r.out.needed = &needed;
362 r.out.count = &count;
363 r.out.info = &info;
365 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
367 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
368 torture_assert_ntstatus_ok(tctx, status,
369 "dcerpc_spoolss_EnumPrinterDrivers failed");
370 if (W_ERROR_IS_OK(r.out.result)) {
371 /* TODO: do some more checks here */
372 continue;
374 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
375 blob = data_blob_talloc(ctx, NULL, needed);
376 data_blob_clear(&blob);
377 r.in.buffer = &blob;
378 r.in.offered = needed;
380 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
381 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
384 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
386 ctx->driver_count[level] = count;
387 ctx->drivers[level] = info;
390 for (i=1;i<ARRAY_SIZE(levels);i++) {
391 int level = levels[i];
392 int old_level = levels[i-1];
394 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
395 "EnumPrinterDrivers invalid value");
398 for (i=0;i<ARRAY_SIZE(levels);i++) {
399 int level = levels[i];
401 for (j=0;j<ctx->driver_count[level];j++) {
402 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
403 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
405 switch (level) {
406 case 1:
407 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
408 break;
409 case 2:
410 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
411 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
412 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
413 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
414 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
415 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
416 break;
417 case 3:
418 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
419 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
420 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
421 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
422 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
423 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
424 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
425 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
426 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
427 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
428 break;
429 case 4:
430 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
431 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
432 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
433 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
434 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
435 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
436 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
437 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
438 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
439 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
440 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
441 break;
442 case 5:
443 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
444 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
445 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
446 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
447 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
448 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
449 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
450 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
451 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
452 break;
453 case 6:
454 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
455 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
456 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
457 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
458 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
459 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
460 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
461 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
462 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
463 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
464 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
465 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
466 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
467 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
468 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
469 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
470 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
471 break;
472 case 8:
473 /* level 8 is our reference, and it makes no sense to compare it to itself */
474 break;
479 return true;
482 static bool test_EnumMonitors(struct torture_context *tctx,
483 struct dcerpc_pipe *p,
484 struct test_spoolss_context *ctx)
486 NTSTATUS status;
487 struct spoolss_EnumMonitors r;
488 uint16_t levels[] = { 1, 2 };
489 int i, j;
491 for (i=0;i<ARRAY_SIZE(levels);i++) {
492 int level = levels[i];
493 DATA_BLOB blob;
494 uint32_t needed;
495 uint32_t count;
496 union spoolss_MonitorInfo *info;
498 r.in.servername = "";
499 r.in.level = level;
500 r.in.buffer = NULL;
501 r.in.offered = 0;
502 r.out.needed = &needed;
503 r.out.count = &count;
504 r.out.info = &info;
506 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
508 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
509 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
510 if (W_ERROR_IS_OK(r.out.result)) {
511 /* TODO: do some more checks here */
512 continue;
514 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
515 "EnumMonitors failed");
517 blob = data_blob_talloc(ctx, NULL, needed);
518 data_blob_clear(&blob);
519 r.in.buffer = &blob;
520 r.in.offered = needed;
522 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
523 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
525 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
527 ctx->monitor_count[level] = count;
528 ctx->monitors[level] = info;
531 for (i=1;i<ARRAY_SIZE(levels);i++) {
532 int level = levels[i];
533 int old_level = levels[i-1];
534 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
535 "EnumMonitors invalid value");
538 for (i=0;i<ARRAY_SIZE(levels);i++) {
539 int level = levels[i];
540 for (j=0;j<ctx->monitor_count[level];j++) {
541 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
542 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
543 switch (level) {
544 case 1:
545 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
546 break;
547 case 2:
548 /* level 2 is our reference, and it makes no sense to compare it to itself */
549 break;
554 return true;
557 static bool test_EnumPrintProcessors(struct torture_context *tctx,
558 struct dcerpc_pipe *p,
559 struct test_spoolss_context *ctx)
561 NTSTATUS status;
562 struct spoolss_EnumPrintProcessors r;
563 uint16_t levels[] = { 1 };
564 int i, j;
566 for (i=0;i<ARRAY_SIZE(levels);i++) {
567 int level = levels[i];
568 DATA_BLOB blob;
569 uint32_t needed;
570 uint32_t count;
571 union spoolss_PrintProcessorInfo *info;
573 r.in.servername = "";
574 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
575 r.in.level = level;
576 r.in.buffer = NULL;
577 r.in.offered = 0;
578 r.out.needed = &needed;
579 r.out.count = &count;
580 r.out.info = &info;
582 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
584 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
585 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
586 if (W_ERROR_IS_OK(r.out.result)) {
587 /* TODO: do some more checks here */
588 continue;
590 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
591 "EnumPrintProcessors unexpected return code");
593 blob = data_blob_talloc(ctx, NULL, needed);
594 data_blob_clear(&blob);
595 r.in.buffer = &blob;
596 r.in.offered = needed;
598 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
599 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
601 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
603 ctx->print_processor_count[level] = count;
604 ctx->print_processors[level] = info;
607 for (i=1;i<ARRAY_SIZE(levels);i++) {
608 int level = levels[i];
609 int old_level = levels[i-1];
610 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
611 "EnumPrintProcessors failed");
614 for (i=0;i<ARRAY_SIZE(levels);i++) {
615 int level = levels[i];
616 for (j=0;j<ctx->print_processor_count[level];j++) {
617 #if 0
618 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
619 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
620 #endif
621 switch (level) {
622 case 1:
623 /* level 1 is our reference, and it makes no sense to compare it to itself */
624 break;
629 return true;
632 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
633 struct dcerpc_pipe *p,
634 struct test_spoolss_context *ctx)
636 NTSTATUS status;
637 struct spoolss_EnumPrintProcDataTypes r;
638 uint16_t levels[] = { 1 };
639 int i;
641 for (i=0;i<ARRAY_SIZE(levels);i++) {
642 int level = levels[i];
643 DATA_BLOB blob;
644 uint32_t needed;
645 uint32_t count;
646 union spoolss_PrintProcDataTypesInfo *info;
648 r.in.servername = "";
649 r.in.print_processor_name = "winprint";
650 r.in.level = level;
651 r.in.buffer = NULL;
652 r.in.offered = 0;
653 r.out.needed = &needed;
654 r.out.count = &count;
655 r.out.info = &info;
657 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
659 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
660 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
661 if (W_ERROR_IS_OK(r.out.result)) {
662 /* TODO: do some more checks here */
663 continue;
665 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
666 "EnumPrintProcDataTypes unexpected return code");
668 blob = data_blob_talloc(ctx, NULL, needed);
669 data_blob_clear(&blob);
670 r.in.buffer = &blob;
671 r.in.offered = needed;
673 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
674 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
676 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
679 return true;
683 static bool test_EnumPrinters(struct torture_context *tctx,
684 struct dcerpc_pipe *p,
685 struct test_spoolss_context *ctx)
687 struct spoolss_EnumPrinters r;
688 NTSTATUS status;
689 uint16_t levels[] = { 0, 1, 2, 4, 5 };
690 int i, j;
692 for (i=0;i<ARRAY_SIZE(levels);i++) {
693 int level = levels[i];
694 DATA_BLOB blob;
695 uint32_t needed;
696 uint32_t count;
697 union spoolss_PrinterInfo *info;
699 r.in.flags = PRINTER_ENUM_LOCAL;
700 r.in.server = "";
701 r.in.level = level;
702 r.in.buffer = NULL;
703 r.in.offered = 0;
704 r.out.needed = &needed;
705 r.out.count = &count;
706 r.out.info = &info;
708 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
710 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
711 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
712 if (W_ERROR_IS_OK(r.out.result)) {
713 /* TODO: do some more checks here */
714 continue;
716 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
717 "EnumPrinters unexpected return code");
719 blob = data_blob_talloc(ctx, NULL, needed);
720 data_blob_clear(&blob);
721 r.in.buffer = &blob;
722 r.in.offered = needed;
724 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
725 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
727 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
729 ctx->printer_count[level] = count;
730 ctx->printers[level] = info;
733 for (i=1;i<ARRAY_SIZE(levels);i++) {
734 int level = levels[i];
735 int old_level = levels[i-1];
736 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
737 "EnumPrinters invalid value");
740 for (i=0;i<ARRAY_SIZE(levels);i++) {
741 int level = levels[i];
742 for (j=0;j<ctx->printer_count[level];j++) {
743 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
744 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
745 switch (level) {
746 case 0:
747 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
748 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
749 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
750 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
751 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
752 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
753 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
754 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
755 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
756 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
757 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
758 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
759 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
760 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
761 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
762 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
763 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
764 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
765 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
766 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
767 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
768 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
769 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
770 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
771 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
772 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
773 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
774 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
775 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
776 break;
777 case 1:
778 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
779 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
780 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
781 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
782 break;
783 case 2:
784 /* level 2 is our reference, and it makes no sense to compare it to itself */
785 break;
786 case 4:
787 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
788 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
789 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
790 break;
791 case 5:
792 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
793 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
794 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
795 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
796 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
797 break;
802 /* TODO:
803 * - verify that the port of a printer was in the list returned by EnumPorts
806 return true;
809 static bool test_GetPrinter(struct torture_context *tctx,
810 struct dcerpc_pipe *p,
811 struct policy_handle *handle)
813 NTSTATUS status;
814 struct spoolss_GetPrinter r;
815 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
816 int i;
817 uint32_t needed;
819 for (i=0;i<ARRAY_SIZE(levels);i++) {
820 r.in.handle = handle;
821 r.in.level = levels[i];
822 r.in.buffer = NULL;
823 r.in.offered = 0;
824 r.out.needed = &needed;
826 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
828 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
829 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
831 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
832 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
833 data_blob_clear(&blob);
834 r.in.buffer = &blob;
835 r.in.offered = needed;
836 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
839 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
841 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
844 return true;
847 static bool test_SetPrinter_errors(struct torture_context *tctx,
848 struct dcerpc_pipe *p,
849 struct policy_handle *handle)
851 struct spoolss_SetPrinter r;
852 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
853 int i;
855 struct spoolss_SetPrinterInfoCtr info_ctr;
856 struct spoolss_DevmodeContainer devmode_ctr;
857 struct sec_desc_buf secdesc_ctr;
859 info_ctr.level = 0;
860 info_ctr.info.info0 = NULL;
862 ZERO_STRUCT(devmode_ctr);
863 ZERO_STRUCT(secdesc_ctr);
865 r.in.handle = handle;
866 r.in.info_ctr = &info_ctr;
867 r.in.devmode_ctr = &devmode_ctr;
868 r.in.secdesc_ctr = &secdesc_ctr;
869 r.in.command = 0;
871 torture_comment(tctx, "Testing SetPrinter all zero\n");
873 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
874 "failed to call SetPrinter");
875 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
876 "failed to call SetPrinter");
878 again:
879 for (i=0; i < ARRAY_SIZE(levels); i++) {
881 struct spoolss_SetPrinterInfo0 info0;
882 struct spoolss_SetPrinterInfo1 info1;
883 struct spoolss_SetPrinterInfo2 info2;
884 struct spoolss_SetPrinterInfo3 info3;
885 struct spoolss_SetPrinterInfo4 info4;
886 struct spoolss_SetPrinterInfo5 info5;
887 struct spoolss_SetPrinterInfo6 info6;
888 struct spoolss_SetPrinterInfo7 info7;
889 struct spoolss_DeviceModeInfo info8;
890 struct spoolss_DeviceModeInfo info9;
893 info_ctr.level = levels[i];
894 switch (levels[i]) {
895 case 0:
896 ZERO_STRUCT(info0);
897 info_ctr.info.info0 = &info0;
898 break;
899 case 1:
900 ZERO_STRUCT(info1);
901 info_ctr.info.info1 = &info1;
902 break;
903 case 2:
904 ZERO_STRUCT(info2);
905 info_ctr.info.info2 = &info2;
906 break;
907 case 3:
908 ZERO_STRUCT(info3);
909 info_ctr.info.info3 = &info3;
910 break;
911 case 4:
912 ZERO_STRUCT(info4);
913 info_ctr.info.info4 = &info4;
914 break;
915 case 5:
916 ZERO_STRUCT(info5);
917 info_ctr.info.info5 = &info5;
918 break;
919 case 6:
920 ZERO_STRUCT(info6);
921 info_ctr.info.info6 = &info6;
922 break;
923 case 7:
924 ZERO_STRUCT(info7);
925 info_ctr.info.info7 = &info7;
926 break;
927 case 8:
928 ZERO_STRUCT(info8);
929 info_ctr.info.info8 = &info8;
930 break;
931 case 9:
932 ZERO_STRUCT(info9);
933 info_ctr.info.info9 = &info9;
934 break;
937 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
938 info_ctr.level, r.in.command);
940 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
941 "failed to call SetPrinter");
943 switch (r.in.command) {
944 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
945 /* is ignored for all levels other then 0 */
946 if (info_ctr.level > 0) {
947 /* ignored then */
948 break;
950 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
951 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
952 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
953 if (info_ctr.level > 0) {
954 /* is invalid for all levels other then 0 */
955 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
956 "unexpected error code returned");
957 continue;
958 } else {
959 torture_assert_werr_ok(tctx, r.out.result,
960 "failed to call SetPrinter with non 0 command");
961 continue;
963 break;
965 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
966 /* FIXME: gd needs further investigation */
967 default:
968 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
969 "unexpected error code returned");
970 continue;
973 switch (info_ctr.level) {
974 case 1:
975 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
976 "unexpected error code returned");
977 break;
978 case 2:
979 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
980 "unexpected error code returned");
981 break;
982 case 3:
983 case 4:
984 case 5:
985 case 7:
986 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
987 "unexpected error code returned");
988 break;
989 case 9:
990 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
991 "unexpected error code returned");
992 break;
993 default:
994 torture_assert_werr_ok(tctx, r.out.result,
995 "failed to call SetPrinter");
996 break;
1000 if (r.in.command < 5) {
1001 r.in.command++;
1002 goto again;
1005 return true;
1008 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1010 if ((r->level == 2) && (r->info.info2)) {
1011 r->info.info2->secdesc = NULL;
1012 r->info.info2->devmode = NULL;
1016 static bool test_PrinterInfo(struct torture_context *tctx,
1017 struct dcerpc_pipe *p,
1018 struct policy_handle *handle)
1020 NTSTATUS status;
1021 struct spoolss_SetPrinter s;
1022 struct spoolss_GetPrinter q;
1023 struct spoolss_GetPrinter q0;
1024 struct spoolss_SetPrinterInfoCtr info_ctr;
1025 union spoolss_PrinterInfo info;
1026 struct spoolss_DevmodeContainer devmode_ctr;
1027 struct sec_desc_buf secdesc_ctr;
1028 uint32_t needed;
1029 bool ret = true;
1030 int i;
1032 uint32_t status_list[] = {
1033 /* these do not stick
1034 PRINTER_STATUS_PAUSED,
1035 PRINTER_STATUS_ERROR,
1036 PRINTER_STATUS_PENDING_DELETION, */
1037 PRINTER_STATUS_PAPER_JAM,
1038 PRINTER_STATUS_PAPER_OUT,
1039 PRINTER_STATUS_MANUAL_FEED,
1040 PRINTER_STATUS_PAPER_PROBLEM,
1041 PRINTER_STATUS_OFFLINE,
1042 PRINTER_STATUS_IO_ACTIVE,
1043 PRINTER_STATUS_BUSY,
1044 PRINTER_STATUS_PRINTING,
1045 PRINTER_STATUS_OUTPUT_BIN_FULL,
1046 PRINTER_STATUS_NOT_AVAILABLE,
1047 PRINTER_STATUS_WAITING,
1048 PRINTER_STATUS_PROCESSING,
1049 PRINTER_STATUS_INITIALIZING,
1050 PRINTER_STATUS_WARMING_UP,
1051 PRINTER_STATUS_TONER_LOW,
1052 PRINTER_STATUS_NO_TONER,
1053 PRINTER_STATUS_PAGE_PUNT,
1054 PRINTER_STATUS_USER_INTERVENTION,
1055 PRINTER_STATUS_OUT_OF_MEMORY,
1056 PRINTER_STATUS_DOOR_OPEN,
1057 PRINTER_STATUS_SERVER_UNKNOWN,
1058 PRINTER_STATUS_POWER_SAVE,
1059 /* these do not stick
1060 0x02000000,
1061 0x04000000,
1062 0x08000000,
1063 0x10000000,
1064 0x20000000,
1065 0x40000000,
1066 0x80000000 */
1068 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1069 uint32_t attribute_list[] = {
1070 PRINTER_ATTRIBUTE_QUEUED,
1071 /* fails with WERR_INVALID_DATATYPE:
1072 PRINTER_ATTRIBUTE_DIRECT, */
1073 /* does not stick
1074 PRINTER_ATTRIBUTE_DEFAULT, */
1075 PRINTER_ATTRIBUTE_SHARED,
1076 /* does not stick
1077 PRINTER_ATTRIBUTE_NETWORK, */
1078 PRINTER_ATTRIBUTE_HIDDEN,
1079 PRINTER_ATTRIBUTE_LOCAL,
1080 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1081 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1082 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1083 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1084 /* does not stick
1085 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1086 /* fails with WERR_INVALID_DATATYPE:
1087 PRINTER_ATTRIBUTE_RAW_ONLY, */
1088 /* these do not stick
1089 PRINTER_ATTRIBUTE_PUBLISHED,
1090 PRINTER_ATTRIBUTE_FAX,
1091 PRINTER_ATTRIBUTE_TS,
1092 0x00010000,
1093 0x00020000,
1094 0x00040000,
1095 0x00080000,
1096 0x00100000,
1097 0x00200000,
1098 0x00400000,
1099 0x00800000,
1100 0x01000000,
1101 0x02000000,
1102 0x04000000,
1103 0x08000000,
1104 0x10000000,
1105 0x20000000,
1106 0x40000000,
1107 0x80000000 */
1110 ZERO_STRUCT(devmode_ctr);
1111 ZERO_STRUCT(secdesc_ctr);
1113 s.in.handle = handle;
1114 s.in.command = 0;
1115 s.in.info_ctr = &info_ctr;
1116 s.in.devmode_ctr = &devmode_ctr;
1117 s.in.secdesc_ctr = &secdesc_ctr;
1119 q.in.handle = handle;
1120 q.out.info = &info;
1121 q0 = q;
1123 #define TESTGETCALL(call, r) \
1124 r.in.buffer = NULL; \
1125 r.in.offered = 0;\
1126 r.out.needed = &needed; \
1127 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1128 if (!NT_STATUS_IS_OK(status)) { \
1129 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1130 r.in.level, nt_errstr(status), __location__); \
1131 ret = false; \
1132 break; \
1134 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1135 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1136 data_blob_clear(&blob); \
1137 r.in.buffer = &blob; \
1138 r.in.offered = needed; \
1140 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1141 if (!NT_STATUS_IS_OK(status)) { \
1142 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1143 r.in.level, nt_errstr(status), __location__); \
1144 ret = false; \
1145 break; \
1147 if (!W_ERROR_IS_OK(r.out.result)) { \
1148 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1149 r.in.level, win_errstr(r.out.result), __location__); \
1150 ret = false; \
1151 break; \
1155 #define TESTSETCALL_EXP(call, r, err) \
1156 clear_info2(&info_ctr);\
1157 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1158 if (!NT_STATUS_IS_OK(status)) { \
1159 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1160 r.in.info_ctr->level, nt_errstr(status), __location__); \
1161 ret = false; \
1162 break; \
1164 if (!W_ERROR_IS_OK(err)) { \
1165 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1166 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1167 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1168 ret = false; \
1170 break; \
1172 if (!W_ERROR_IS_OK(r.out.result)) { \
1173 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1174 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1175 ret = false; \
1176 break; \
1179 #define TESTSETCALL(call, r) \
1180 TESTSETCALL_EXP(call, r, WERR_OK)
1182 #define STRING_EQUAL(s1, s2, field) \
1183 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1184 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1185 #field, s2, __location__); \
1186 ret = false; \
1187 break; \
1190 #define MEM_EQUAL(s1, s2, length, field) \
1191 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1192 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1193 #field, (const char *)s2, __location__); \
1194 ret = false; \
1195 break; \
1198 #define INT_EQUAL(i1, i2, field) \
1199 if (i1 != i2) { \
1200 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1201 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1202 ret = false; \
1203 break; \
1206 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1207 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1208 q.in.level = lvl1; \
1209 TESTGETCALL(GetPrinter, q) \
1210 info_ctr.level = lvl1; \
1211 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1212 info_ctr.info.info ## lvl1->field1 = value;\
1213 TESTSETCALL_EXP(SetPrinter, s, err) \
1214 info_ctr.info.info ## lvl1->field1 = ""; \
1215 TESTGETCALL(GetPrinter, q) \
1216 info_ctr.info.info ## lvl1->field1 = value; \
1217 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1218 q.in.level = lvl2; \
1219 TESTGETCALL(GetPrinter, q) \
1220 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1221 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1222 } while (0)
1224 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1225 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1226 } while (0);
1228 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1229 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1230 q.in.level = lvl1; \
1231 TESTGETCALL(GetPrinter, q) \
1232 info_ctr.level = lvl1; \
1233 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1234 info_ctr.info.info ## lvl1->field1 = value; \
1235 TESTSETCALL(SetPrinter, s) \
1236 info_ctr.info.info ## lvl1->field1 = 0; \
1237 TESTGETCALL(GetPrinter, q) \
1238 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1239 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1240 q.in.level = lvl2; \
1241 TESTGETCALL(GetPrinter, q) \
1242 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1243 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1244 } while (0)
1246 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1247 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1248 } while (0)
1250 q0.in.level = 0;
1251 do { TESTGETCALL(GetPrinter, q0) } while (0);
1253 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1254 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1256 /* level 0 printername does not stick */
1257 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1258 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1259 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1260 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1261 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1262 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1263 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1264 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1265 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1266 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1267 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1268 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1269 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1270 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1271 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1273 /* servername can be set but does not stick
1274 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1275 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1276 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1279 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1280 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1281 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1282 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1283 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1285 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1286 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1287 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1288 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1289 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1290 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1291 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1292 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1293 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1294 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1296 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1297 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1298 attribute_list[i],
1299 (attribute_list[i] | default_attribute)
1300 ); */
1301 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1302 attribute_list[i],
1303 (attribute_list[i] | default_attribute)
1305 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1306 attribute_list[i],
1307 (attribute_list[i] | default_attribute)
1309 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1310 attribute_list[i],
1311 (attribute_list[i] | default_attribute)
1313 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1314 attribute_list[i],
1315 (attribute_list[i] | default_attribute)
1316 ); */
1317 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1318 attribute_list[i],
1319 (attribute_list[i] | default_attribute)
1321 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1322 attribute_list[i],
1323 (attribute_list[i] | default_attribute)
1325 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1326 attribute_list[i],
1327 (attribute_list[i] | default_attribute)
1329 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1330 attribute_list[i],
1331 (attribute_list[i] | default_attribute)
1332 ); */
1333 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1334 attribute_list[i],
1335 (attribute_list[i] | default_attribute)
1337 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1338 attribute_list[i],
1339 (attribute_list[i] | default_attribute)
1341 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1342 attribute_list[i],
1343 (attribute_list[i] | default_attribute)
1347 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1348 /* level 2 sets do not stick
1349 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1350 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1351 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1352 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1353 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1354 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1357 /* priorities need to be between 0 and 99
1358 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1359 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1360 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1361 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1362 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1363 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1364 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1365 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1366 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1368 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1369 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1371 /* does not stick
1372 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1373 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1375 /* does not stick
1376 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1377 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1379 /* FIXME: gd also test devmode and secdesc behavior */
1382 /* verify composition of level 1 description field */
1383 const char *description;
1384 const char *tmp;
1386 q0.in.level = 1;
1387 do { TESTGETCALL(GetPrinter, q0) } while (0);
1389 description = talloc_strdup(tctx, q0.out.info->info1.description);
1391 q0.in.level = 2;
1392 do { TESTGETCALL(GetPrinter, q0) } while (0);
1394 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1395 q0.out.info->info2.printername,
1396 q0.out.info->info2.drivername,
1397 q0.out.info->info2.location);
1399 do { STRING_EQUAL(description, tmp, "description")} while (0);
1402 return ret;
1406 static bool test_ClosePrinter(struct torture_context *tctx,
1407 struct dcerpc_pipe *p,
1408 struct policy_handle *handle)
1410 NTSTATUS status;
1411 struct spoolss_ClosePrinter r;
1413 r.in.handle = handle;
1414 r.out.handle = handle;
1416 torture_comment(tctx, "Testing ClosePrinter\n");
1418 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1419 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1420 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1422 return true;
1425 static bool test_GetForm(struct torture_context *tctx,
1426 struct dcerpc_pipe *p,
1427 struct policy_handle *handle,
1428 const char *form_name,
1429 uint32_t level)
1431 NTSTATUS status;
1432 struct spoolss_GetForm r;
1433 uint32_t needed;
1435 r.in.handle = handle;
1436 r.in.form_name = form_name;
1437 r.in.level = level;
1438 r.in.buffer = NULL;
1439 r.in.offered = 0;
1440 r.out.needed = &needed;
1442 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1444 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1445 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1447 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1448 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1449 data_blob_clear(&blob);
1450 r.in.buffer = &blob;
1451 r.in.offered = needed;
1452 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1453 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1455 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1457 torture_assert(tctx, r.out.info, "No form info returned");
1460 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1462 return true;
1465 static bool test_EnumForms(struct torture_context *tctx,
1466 struct dcerpc_pipe *p,
1467 struct policy_handle *handle, bool print_server)
1469 NTSTATUS status;
1470 struct spoolss_EnumForms r;
1471 bool ret = true;
1472 uint32_t needed;
1473 uint32_t count;
1474 uint32_t levels[] = { 1, 2 };
1475 int i;
1477 for (i=0; i<ARRAY_SIZE(levels); i++) {
1479 union spoolss_FormInfo *info;
1481 r.in.handle = handle;
1482 r.in.level = levels[i];
1483 r.in.buffer = NULL;
1484 r.in.offered = 0;
1485 r.out.needed = &needed;
1486 r.out.count = &count;
1487 r.out.info = &info;
1489 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1491 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1492 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1494 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1495 break;
1498 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1499 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1501 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1502 int j;
1503 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1504 data_blob_clear(&blob);
1505 r.in.buffer = &blob;
1506 r.in.offered = needed;
1508 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1510 torture_assert(tctx, info, "No forms returned");
1512 for (j = 0; j < count; j++) {
1513 if (!print_server)
1514 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1518 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1520 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1523 return true;
1526 static bool test_DeleteForm(struct torture_context *tctx,
1527 struct dcerpc_pipe *p,
1528 struct policy_handle *handle,
1529 const char *form_name)
1531 NTSTATUS status;
1532 struct spoolss_DeleteForm r;
1534 r.in.handle = handle;
1535 r.in.form_name = form_name;
1537 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1539 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1541 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1543 return true;
1546 static bool test_AddForm(struct torture_context *tctx,
1547 struct dcerpc_pipe *p,
1548 struct policy_handle *handle, bool print_server)
1550 struct spoolss_AddForm r;
1551 struct spoolss_AddFormInfo1 addform;
1552 const char *form_name = "testform3";
1553 NTSTATUS status;
1554 bool ret = true;
1556 r.in.handle = handle;
1557 r.in.level = 1;
1558 r.in.info.info1 = &addform;
1559 addform.flags = SPOOLSS_FORM_USER;
1560 addform.form_name = form_name;
1561 addform.size.width = 50;
1562 addform.size.height = 25;
1563 addform.area.left = 5;
1564 addform.area.top = 10;
1565 addform.area.right = 45;
1566 addform.area.bottom = 15;
1568 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1570 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1572 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1574 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1577 struct spoolss_SetForm sf;
1578 struct spoolss_AddFormInfo1 setform;
1580 sf.in.handle = handle;
1581 sf.in.form_name = form_name;
1582 sf.in.level = 1;
1583 sf.in.info.info1= &setform;
1584 setform.flags = addform.flags;
1585 setform.form_name = addform.form_name;
1586 setform.size = addform.size;
1587 setform.area = addform.area;
1589 setform.size.width = 1234;
1591 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1593 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1595 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1598 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1601 struct spoolss_EnumForms e;
1602 union spoolss_FormInfo *info;
1603 uint32_t needed;
1604 uint32_t count;
1605 bool found = false;
1607 e.in.handle = handle;
1608 e.in.level = 1;
1609 e.in.buffer = NULL;
1610 e.in.offered = 0;
1611 e.out.needed = &needed;
1612 e.out.count = &count;
1613 e.out.info = &info;
1615 torture_comment(tctx, "Testing EnumForms level 1\n");
1617 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1618 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1620 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1621 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1623 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1624 int j;
1625 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1626 data_blob_clear(&blob);
1627 e.in.buffer = &blob;
1628 e.in.offered = needed;
1630 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1632 torture_assert(tctx, info, "No forms returned");
1634 for (j = 0; j < count; j++) {
1635 if (strequal(form_name, info[j].info1.form_name)) {
1636 found = true;
1637 break;
1641 torture_assert(tctx, found, "Newly added form not found in enum call");
1644 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1645 ret = false;
1648 return ret;
1651 static bool test_EnumPorts_old(struct torture_context *tctx,
1652 struct dcerpc_pipe *p)
1654 NTSTATUS status;
1655 struct spoolss_EnumPorts r;
1656 uint32_t needed;
1657 uint32_t count;
1658 union spoolss_PortInfo *info;
1660 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1661 dcerpc_server_name(p));
1662 r.in.level = 2;
1663 r.in.buffer = NULL;
1664 r.in.offered = 0;
1665 r.out.needed = &needed;
1666 r.out.count = &count;
1667 r.out.info = &info;
1669 torture_comment(tctx, "Testing EnumPorts\n");
1671 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1673 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1675 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1676 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1677 data_blob_clear(&blob);
1678 r.in.buffer = &blob;
1679 r.in.offered = needed;
1681 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1682 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1683 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1685 torture_assert(tctx, info, "No ports returned");
1688 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1690 return true;
1693 static bool test_AddPort(struct torture_context *tctx,
1694 struct dcerpc_pipe *p)
1696 NTSTATUS status;
1697 struct spoolss_AddPort r;
1699 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1700 dcerpc_server_name(p));
1701 r.in.unknown = 0;
1702 r.in.monitor_name = "foo";
1704 torture_comment(tctx, "Testing AddPort\n");
1706 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1708 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1710 /* win2k3 returns WERR_NOT_SUPPORTED */
1712 #if 0
1714 if (!W_ERROR_IS_OK(r.out.result)) {
1715 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1716 return false;
1719 #endif
1721 return true;
1724 static bool test_GetJob(struct torture_context *tctx,
1725 struct dcerpc_pipe *p,
1726 struct policy_handle *handle, uint32_t job_id)
1728 NTSTATUS status;
1729 struct spoolss_GetJob r;
1730 union spoolss_JobInfo info;
1731 uint32_t needed;
1732 uint32_t levels[] = {1, 2 /* 3, 4 */};
1733 uint32_t i;
1735 r.in.handle = handle;
1736 r.in.job_id = job_id;
1737 r.in.level = 0;
1738 r.in.buffer = NULL;
1739 r.in.offered = 0;
1740 r.out.needed = &needed;
1741 r.out.info = &info;
1743 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1745 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1746 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1748 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1750 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1752 needed = 0;
1754 r.in.level = levels[i];
1755 r.in.offered = 0;
1756 r.in.buffer = NULL;
1758 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1759 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1761 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1762 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1763 data_blob_clear(&blob);
1764 r.in.buffer = &blob;
1765 r.in.offered = needed;
1767 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1768 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1771 torture_assert(tctx, r.out.info, "No job info returned");
1772 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1775 return true;
1778 static bool test_SetJob(struct torture_context *tctx,
1779 struct dcerpc_pipe *p,
1780 struct policy_handle *handle, uint32_t job_id,
1781 enum spoolss_JobControl command)
1783 NTSTATUS status;
1784 struct spoolss_SetJob r;
1786 r.in.handle = handle;
1787 r.in.job_id = job_id;
1788 r.in.ctr = NULL;
1789 r.in.command = command;
1791 switch (command) {
1792 case SPOOLSS_JOB_CONTROL_PAUSE:
1793 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1794 break;
1795 case SPOOLSS_JOB_CONTROL_RESUME:
1796 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1797 break;
1798 case SPOOLSS_JOB_CONTROL_CANCEL:
1799 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1800 break;
1801 case SPOOLSS_JOB_CONTROL_RESTART:
1802 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1803 break;
1804 case SPOOLSS_JOB_CONTROL_DELETE:
1805 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1806 break;
1807 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1808 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1809 break;
1810 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1811 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1812 break;
1813 case SPOOLSS_JOB_CONTROL_RETAIN:
1814 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1815 break;
1816 case SPOOLSS_JOB_CONTROL_RELEASE:
1817 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1818 break;
1819 default:
1820 torture_comment(tctx, "Testing SetJob\n");
1821 break;
1824 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1825 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1826 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1828 return true;
1831 static bool test_AddJob(struct torture_context *tctx,
1832 struct dcerpc_pipe *p,
1833 struct policy_handle *handle)
1835 NTSTATUS status;
1836 struct spoolss_AddJob r;
1837 uint32_t needed;
1839 r.in.level = 0;
1840 r.in.handle = handle;
1841 r.in.offered = 0;
1842 r.out.needed = &needed;
1843 r.in.buffer = r.out.buffer = NULL;
1845 torture_comment(tctx, "Testing AddJob\n");
1847 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1848 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1850 r.in.level = 1;
1852 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1853 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1855 return true;
1859 static bool test_EnumJobs(struct torture_context *tctx,
1860 struct dcerpc_pipe *p,
1861 struct policy_handle *handle)
1863 NTSTATUS status;
1864 struct spoolss_EnumJobs r;
1865 uint32_t needed;
1866 uint32_t count;
1867 union spoolss_JobInfo *info;
1869 r.in.handle = handle;
1870 r.in.firstjob = 0;
1871 r.in.numjobs = 0xffffffff;
1872 r.in.level = 1;
1873 r.in.buffer = NULL;
1874 r.in.offered = 0;
1875 r.out.needed = &needed;
1876 r.out.count = &count;
1877 r.out.info = &info;
1879 torture_comment(tctx, "Testing EnumJobs\n");
1881 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1883 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1885 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1886 int j;
1887 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1888 data_blob_clear(&blob);
1889 r.in.buffer = &blob;
1890 r.in.offered = needed;
1892 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1894 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1895 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1896 torture_assert(tctx, info, "No jobs returned");
1898 for (j = 0; j < count; j++) {
1900 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
1901 "failed to call test_GetJob");
1903 /* FIXME - gd */
1904 if (!torture_setting_bool(tctx, "samba3", false)) {
1905 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1906 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1910 } else {
1911 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1914 return true;
1917 static bool test_DoPrintTest(struct torture_context *tctx,
1918 struct dcerpc_pipe *p,
1919 struct policy_handle *handle)
1921 bool ret = true;
1922 NTSTATUS status;
1923 struct spoolss_StartDocPrinter s;
1924 struct spoolss_DocumentInfo1 info1;
1925 struct spoolss_StartPagePrinter sp;
1926 struct spoolss_WritePrinter w;
1927 struct spoolss_EndPagePrinter ep;
1928 struct spoolss_EndDocPrinter e;
1929 int i;
1930 uint32_t job_id;
1931 uint32_t num_written;
1933 torture_comment(tctx, "Testing StartDocPrinter\n");
1935 s.in.handle = handle;
1936 s.in.level = 1;
1937 s.in.info.info1 = &info1;
1938 s.out.job_id = &job_id;
1939 info1.document_name = "TorturePrintJob";
1940 info1.output_file = NULL;
1941 info1.datatype = "RAW";
1943 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1944 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1945 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1947 for (i=1; i < 4; i++) {
1948 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1950 sp.in.handle = handle;
1952 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1953 torture_assert_ntstatus_ok(tctx, status,
1954 "dcerpc_spoolss_StartPagePrinter failed");
1955 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1957 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1959 w.in.handle = handle;
1960 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1961 w.out.num_written = &num_written;
1963 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1964 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1965 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1967 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1969 ep.in.handle = handle;
1971 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1972 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1973 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1976 torture_comment(tctx, "Testing EndDocPrinter\n");
1978 e.in.handle = handle;
1980 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1981 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1982 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1984 ret &= test_AddJob(tctx, p, handle);
1985 ret &= test_EnumJobs(tctx, p, handle);
1987 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1989 return ret;
1992 static bool test_PausePrinter(struct torture_context *tctx,
1993 struct dcerpc_pipe *p,
1994 struct policy_handle *handle)
1996 NTSTATUS status;
1997 struct spoolss_SetPrinter r;
1998 struct spoolss_SetPrinterInfoCtr info_ctr;
1999 struct spoolss_DevmodeContainer devmode_ctr;
2000 struct sec_desc_buf secdesc_ctr;
2002 info_ctr.level = 0;
2003 info_ctr.info.info0 = NULL;
2005 ZERO_STRUCT(devmode_ctr);
2006 ZERO_STRUCT(secdesc_ctr);
2008 r.in.handle = handle;
2009 r.in.info_ctr = &info_ctr;
2010 r.in.devmode_ctr = &devmode_ctr;
2011 r.in.secdesc_ctr = &secdesc_ctr;
2012 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2014 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2016 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2018 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2020 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2022 return true;
2025 static bool test_ResumePrinter(struct torture_context *tctx,
2026 struct dcerpc_pipe *p,
2027 struct policy_handle *handle)
2029 NTSTATUS status;
2030 struct spoolss_SetPrinter r;
2031 struct spoolss_SetPrinterInfoCtr info_ctr;
2032 struct spoolss_DevmodeContainer devmode_ctr;
2033 struct sec_desc_buf secdesc_ctr;
2035 info_ctr.level = 0;
2036 info_ctr.info.info0 = NULL;
2038 ZERO_STRUCT(devmode_ctr);
2039 ZERO_STRUCT(secdesc_ctr);
2041 r.in.handle = handle;
2042 r.in.info_ctr = &info_ctr;
2043 r.in.devmode_ctr = &devmode_ctr;
2044 r.in.secdesc_ctr = &secdesc_ctr;
2045 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2047 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2049 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2051 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2053 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2055 return true;
2058 static bool test_GetPrinterData(struct torture_context *tctx,
2059 struct dcerpc_pipe *p,
2060 struct policy_handle *handle,
2061 const char *value_name,
2062 enum winreg_Type *type_p,
2063 union spoolss_PrinterData *data_p)
2065 NTSTATUS status;
2066 struct spoolss_GetPrinterData r;
2067 uint32_t needed;
2068 enum winreg_Type type;
2069 union spoolss_PrinterData data;
2071 r.in.handle = handle;
2072 r.in.value_name = value_name;
2073 r.in.offered = 0;
2074 r.out.needed = &needed;
2075 r.out.type = &type;
2076 r.out.data = &data;
2078 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2080 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2081 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2083 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2084 r.in.offered = needed;
2086 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2087 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2090 torture_assert_werr_ok(tctx, r.out.result,
2091 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2093 if (type_p) {
2094 *type_p = type;
2097 if (data_p) {
2098 *data_p = data;
2101 return true;
2104 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2105 struct dcerpc_pipe *p,
2106 struct policy_handle *handle,
2107 const char *key_name,
2108 const char *value_name,
2109 enum winreg_Type *type_p,
2110 union spoolss_PrinterData *data_p)
2112 NTSTATUS status;
2113 struct spoolss_GetPrinterDataEx r;
2114 enum winreg_Type type;
2115 uint32_t needed;
2116 union spoolss_PrinterData data;
2118 r.in.handle = handle;
2119 r.in.key_name = key_name;
2120 r.in.value_name = value_name;
2121 r.in.offered = 0;
2122 r.out.type = &type;
2123 r.out.needed = &needed;
2124 r.out.data = &data;
2126 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2127 r.in.key_name, r.in.value_name);
2129 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2132 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2133 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2135 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2138 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2139 r.in.offered = needed;
2140 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2141 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2144 torture_assert_werr_ok(tctx, r.out.result,
2145 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2147 if (type_p) {
2148 *type_p = type;
2151 if (data_p) {
2152 *data_p = data;
2155 return true;
2158 static bool test_GetPrinterData_list(struct torture_context *tctx,
2159 struct dcerpc_pipe *p,
2160 struct policy_handle *handle)
2162 const char *list[] = {
2163 "W3SvcInstalled",
2164 "BeepEnabled",
2165 "EventLog",
2166 /* "NetPopup", not on w2k8 */
2167 /* "NetPopupToComputer", not on w2k8 */
2168 "MajorVersion",
2169 "MinorVersion",
2170 "DefaultSpoolDirectory",
2171 "Architecture",
2172 "DsPresent",
2173 "OSVersion",
2174 /* "OSVersionEx", not on s3 */
2175 "DNSMachineName"
2177 int i;
2179 for (i=0; i < ARRAY_SIZE(list); i++) {
2180 enum winreg_Type type, type_ex;
2181 union spoolss_PrinterData data, data_ex;
2183 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2184 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2185 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2186 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2187 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2188 switch (type) {
2189 case REG_SZ:
2190 torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2191 break;
2192 case REG_DWORD:
2193 torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2194 break;
2195 case REG_BINARY:
2196 torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2197 break;
2198 default:
2199 break;
2203 return true;
2206 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2207 struct policy_handle *handle)
2209 NTSTATUS status;
2210 struct spoolss_EnumPrinterData r;
2212 ZERO_STRUCT(r);
2213 r.in.handle = handle;
2214 r.in.enum_index = 0;
2216 do {
2217 uint32_t value_size = 0;
2218 uint32_t data_size = 0;
2219 enum winreg_Type type = 0;
2221 r.in.value_offered = value_size;
2222 r.out.value_needed = &value_size;
2223 r.in.data_offered = data_size;
2224 r.out.data_needed = &data_size;
2226 r.out.type = &type;
2227 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2229 torture_comment(tctx, "Testing EnumPrinterData\n");
2231 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2233 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2234 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2235 break;
2237 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2239 r.in.value_offered = value_size;
2240 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2241 r.in.data_offered = data_size;
2242 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2244 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2246 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2247 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2248 break;
2251 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2253 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2254 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2256 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2257 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2259 r.in.enum_index++;
2261 } while (W_ERROR_IS_OK(r.out.result));
2263 return true;
2266 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2267 struct dcerpc_pipe *p,
2268 struct policy_handle *handle,
2269 const char *key_name)
2271 struct spoolss_EnumPrinterDataEx r;
2272 struct spoolss_PrinterEnumValues *info;
2273 uint32_t needed;
2274 uint32_t count;
2276 r.in.handle = handle;
2277 r.in.key_name = key_name;
2278 r.in.offered = 0;
2279 r.out.needed = &needed;
2280 r.out.count = &count;
2281 r.out.info = &info;
2283 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2285 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2286 "EnumPrinterDataEx failed");
2287 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2288 r.in.offered = needed;
2289 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2290 "EnumPrinterDataEx failed");
2293 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2295 return true;
2299 static bool test_DeletePrinterData(struct torture_context *tctx,
2300 struct dcerpc_pipe *p,
2301 struct policy_handle *handle,
2302 const char *value_name)
2304 NTSTATUS status;
2305 struct spoolss_DeletePrinterData r;
2307 r.in.handle = handle;
2308 r.in.value_name = value_name;
2310 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2311 r.in.value_name);
2313 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2315 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2316 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2318 return true;
2321 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2322 struct dcerpc_pipe *p,
2323 struct policy_handle *handle,
2324 const char *key_name,
2325 const char *value_name)
2327 struct spoolss_DeletePrinterDataEx r;
2329 r.in.handle = handle;
2330 r.in.key_name = key_name;
2331 r.in.value_name = value_name;
2333 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2334 r.in.key_name, r.in.value_name);
2336 torture_assert_ntstatus_ok(tctx,
2337 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2338 "DeletePrinterDataEx failed");
2339 torture_assert_werr_ok(tctx, r.out.result,
2340 "DeletePrinterDataEx failed");
2342 return true;
2345 static bool test_DeletePrinterKey(struct torture_context *tctx,
2346 struct dcerpc_pipe *p,
2347 struct policy_handle *handle,
2348 const char *key_name)
2350 struct spoolss_DeletePrinterKey r;
2352 r.in.handle = handle;
2353 r.in.key_name = key_name;
2355 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2357 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2358 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2359 return true;
2362 torture_assert_ntstatus_ok(tctx,
2363 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2364 "DeletePrinterKey failed");
2365 torture_assert_werr_ok(tctx, r.out.result,
2366 "DeletePrinterKey failed");
2368 return true;
2371 static bool test_SetPrinterData(struct torture_context *tctx,
2372 struct dcerpc_pipe *p,
2373 struct policy_handle *handle)
2375 NTSTATUS status;
2376 struct spoolss_SetPrinterData r;
2377 const char *values[] = {
2378 "spootyfoot",
2379 "spooty\\foot",
2380 #if 0
2381 /* FIXME: not working with s3 atm. */
2382 "spooty,foot",
2383 "spooty,fo,ot",
2384 #endif
2385 "spooty foot",
2386 #if 0
2387 /* FIXME: not working with s3 atm. */
2388 "spooty\\fo,ot",
2389 "spooty,fo\\ot"
2390 #endif
2392 int i;
2394 for (i=0; i < ARRAY_SIZE(values); i++) {
2396 enum winreg_Type type;
2397 union spoolss_PrinterData data;
2399 r.in.handle = handle;
2400 r.in.value_name = values[i];
2401 r.in.type = REG_SZ;
2402 r.in.data.string = "dog";
2404 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2405 r.in.value_name);
2407 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2409 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2410 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2412 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2413 return false;
2416 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2417 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2419 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2420 return false;
2424 return true;
2427 static bool test_EnumPrinterKey(struct torture_context *tctx,
2428 struct dcerpc_pipe *p,
2429 struct policy_handle *handle,
2430 const char *key_name,
2431 const char ***array);
2433 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2434 struct dcerpc_pipe *p,
2435 struct policy_handle *handle)
2437 NTSTATUS status;
2438 struct spoolss_SetPrinterDataEx r;
2439 const char *value_name = "dog";
2440 const char *keys[] = {
2441 "torturedataex",
2442 "torture data ex",
2443 #if 0
2444 /* FIXME: not working with s3 atm. */
2445 "torturedataex_with_subkey\\subkey",
2446 "torturedataex_with_subkey\\subkey:0",
2447 "torturedataex_with_subkey\\subkey:1",
2448 "torturedataex_with_subkey\\subkey\\subsubkey",
2449 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2450 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2451 #endif
2452 "torture,data",
2453 #if 0
2454 /* FIXME: not working with s3 atm. */
2456 "torture,data,ex",
2457 "torture,data\\ex",
2458 "torture\\data,ex"
2459 #endif
2461 int i;
2462 DATA_BLOB blob = data_blob_string_const("catfoobar");
2465 for (i=0; i < ARRAY_SIZE(keys); i++) {
2467 char *c;
2468 const char *key;
2469 enum winreg_Type type;
2470 const char **subkeys;
2471 union spoolss_PrinterData data;
2473 r.in.handle = handle;
2474 r.in.key_name = keys[i];
2475 r.in.value_name = value_name;
2476 r.in.type = REG_BINARY;
2477 r.in.data.binary = blob;
2479 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2481 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2483 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2484 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2486 key = talloc_strdup(tctx, r.in.key_name);
2488 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
2489 return false;
2492 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2493 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
2495 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2496 return false;
2499 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2500 return false;
2503 c = strchr(key, '\\');
2504 if (c) {
2505 int i;
2507 /* we have subkeys */
2509 *c = 0;
2511 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2512 return false;
2515 for (i=0; subkeys && subkeys[i]; i++) {
2517 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2519 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2520 return false;
2524 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2525 return false;
2528 } else {
2529 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2530 return false;
2535 return true;
2539 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2540 struct dcerpc_pipe *p,
2541 struct policy_handle *handle)
2543 NTSTATUS status;
2544 struct dcerpc_binding *b;
2545 struct dcerpc_pipe *p2;
2546 struct spoolss_ClosePrinter cp;
2548 /* only makes sense on SMB */
2549 if (p->conn->transport.transport != NCACN_NP) {
2550 return true;
2553 torture_comment(tctx, "testing close on secondary pipe\n");
2555 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2556 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2558 status = dcerpc_secondary_connection(p, &p2, b);
2559 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2561 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2562 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2564 cp.in.handle = handle;
2565 cp.out.handle = handle;
2567 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2568 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2569 "ERROR: Allowed close on secondary connection");
2571 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2572 "Unexpected fault code");
2574 talloc_free(p2);
2576 return true;
2579 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2580 struct dcerpc_pipe *p, const char *name)
2582 NTSTATUS status;
2583 struct spoolss_OpenPrinter op;
2584 struct spoolss_OpenPrinterEx opEx;
2585 struct policy_handle handle;
2586 bool ret = true;
2588 op.in.printername = name;
2589 op.in.datatype = NULL;
2590 op.in.devmode_ctr.devmode= NULL;
2591 op.in.access_mask = 0;
2592 op.out.handle = &handle;
2594 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2596 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2597 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2598 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2599 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2600 name, win_errstr(op.out.result));
2603 if (W_ERROR_IS_OK(op.out.result)) {
2604 ret &=test_ClosePrinter(tctx, p, &handle);
2607 opEx.in.printername = name;
2608 opEx.in.datatype = NULL;
2609 opEx.in.devmode_ctr.devmode = NULL;
2610 opEx.in.access_mask = 0;
2611 opEx.in.level = 1;
2612 opEx.in.userlevel.level1 = NULL;
2613 opEx.out.handle = &handle;
2615 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2617 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2618 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2619 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2620 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2621 name, win_errstr(opEx.out.result));
2624 if (W_ERROR_IS_OK(opEx.out.result)) {
2625 ret &=test_ClosePrinter(tctx, p, &handle);
2628 return ret;
2631 static bool test_OpenPrinter(struct torture_context *tctx,
2632 struct dcerpc_pipe *p,
2633 const char *name)
2635 NTSTATUS status;
2636 struct spoolss_OpenPrinter r;
2637 struct policy_handle handle;
2638 bool ret = true;
2640 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2641 r.in.datatype = NULL;
2642 r.in.devmode_ctr.devmode= NULL;
2643 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2644 r.out.handle = &handle;
2646 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2648 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2650 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2652 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2654 if (!test_GetPrinter(tctx, p, &handle)) {
2655 ret = false;
2658 if (!torture_setting_bool(tctx, "samba3", false)) {
2659 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2660 ret = false;
2664 if (!test_ClosePrinter(tctx, p, &handle)) {
2665 ret = false;
2668 return ret;
2671 static bool call_OpenPrinterEx(struct torture_context *tctx,
2672 struct dcerpc_pipe *p,
2673 const char *name, struct policy_handle *handle)
2675 struct spoolss_OpenPrinterEx r;
2676 struct spoolss_UserLevel1 userlevel1;
2677 NTSTATUS status;
2679 if (name && name[0]) {
2680 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2681 dcerpc_server_name(p), name);
2682 } else {
2683 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2684 dcerpc_server_name(p));
2687 r.in.datatype = NULL;
2688 r.in.devmode_ctr.devmode= NULL;
2689 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2690 r.in.level = 1;
2691 r.in.userlevel.level1 = &userlevel1;
2692 r.out.handle = handle;
2694 userlevel1.size = 1234;
2695 userlevel1.client = "hello";
2696 userlevel1.user = "spottyfoot!";
2697 userlevel1.build = 1;
2698 userlevel1.major = 2;
2699 userlevel1.minor = 3;
2700 userlevel1.processor = 4;
2702 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2704 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2706 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2708 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2710 return true;
2713 static bool test_OpenPrinterEx(struct torture_context *tctx,
2714 struct dcerpc_pipe *p,
2715 const char *name)
2717 struct policy_handle handle;
2718 bool ret = true;
2720 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2721 return false;
2724 if (!test_GetPrinter(tctx, p, &handle)) {
2725 ret = false;
2728 if (!test_EnumForms(tctx, p, &handle, false)) {
2729 ret = false;
2732 if (!test_AddForm(tctx, p, &handle, false)) {
2733 ret = false;
2736 if (!test_EnumPrinterData(tctx, p, &handle)) {
2737 ret = false;
2740 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
2741 ret = false;
2744 if (!test_printer_keys(tctx, p, &handle)) {
2745 ret = false;
2748 if (!test_PausePrinter(tctx, p, &handle)) {
2749 ret = false;
2752 if (!test_DoPrintTest(tctx, p, &handle)) {
2753 ret = false;
2756 if (!test_ResumePrinter(tctx, p, &handle)) {
2757 ret = false;
2760 if (!test_SetPrinterData(tctx, p, &handle)) {
2761 ret = false;
2764 if (!test_SetPrinterDataEx(tctx, p, &handle)) {
2765 ret = false;
2768 if (!torture_setting_bool(tctx, "samba3", false)) {
2769 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2770 ret = false;
2774 if (!test_ClosePrinter(tctx, p, &handle)) {
2775 ret = false;
2778 return ret;
2781 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2783 struct spoolss_EnumPrinters r;
2784 NTSTATUS status;
2785 uint16_t levels[] = {1, 2, 4, 5};
2786 int i;
2787 bool ret = true;
2789 for (i=0;i<ARRAY_SIZE(levels);i++) {
2790 union spoolss_PrinterInfo *info;
2791 int j;
2792 uint32_t needed;
2793 uint32_t count;
2795 r.in.flags = PRINTER_ENUM_LOCAL;
2796 r.in.server = "";
2797 r.in.level = levels[i];
2798 r.in.buffer = NULL;
2799 r.in.offered = 0;
2800 r.out.needed = &needed;
2801 r.out.count = &count;
2802 r.out.info = &info;
2804 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2806 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2807 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2809 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2810 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2811 data_blob_clear(&blob);
2812 r.in.buffer = &blob;
2813 r.in.offered = needed;
2814 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2817 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2819 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2821 if (!info) {
2822 torture_comment(tctx, "No printers returned\n");
2823 return true;
2826 for (j=0;j<count;j++) {
2827 if (r.in.level == 1) {
2828 char *unc = talloc_strdup(tctx, info[j].info1.name);
2829 char *slash, *name;
2830 name = unc;
2831 if (unc[0] == '\\' && unc[1] == '\\') {
2832 unc +=2;
2834 slash = strchr(unc, '\\');
2835 if (slash) {
2836 slash++;
2837 name = slash;
2839 if (!test_OpenPrinter(tctx, p, name)) {
2840 ret = false;
2842 if (!test_OpenPrinterEx(tctx, p, name)) {
2843 ret = false;
2849 return ret;
2852 static bool test_GetPrinterDriver(struct torture_context *tctx,
2853 struct dcerpc_pipe *p,
2854 struct policy_handle *handle,
2855 const char *driver_name)
2857 struct spoolss_GetPrinterDriver r;
2858 uint32_t needed;
2860 r.in.handle = handle;
2861 r.in.architecture = "W32X86";
2862 r.in.level = 1;
2863 r.in.buffer = NULL;
2864 r.in.offered = 0;
2865 r.out.needed = &needed;
2867 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2869 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2870 "failed to call GetPrinterDriver");
2871 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2872 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2873 data_blob_clear(&blob);
2874 r.in.buffer = &blob;
2875 r.in.offered = needed;
2876 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2877 "failed to call GetPrinterDriver");
2880 torture_assert_werr_ok(tctx, r.out.result,
2881 "failed to call GetPrinterDriver");
2883 return true;
2886 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2887 struct dcerpc_pipe *p,
2888 struct policy_handle *handle,
2889 const char *driver_name)
2891 struct spoolss_GetPrinterDriver2 r;
2892 uint32_t needed;
2893 uint32_t server_major_version;
2894 uint32_t server_minor_version;
2896 r.in.handle = handle;
2897 r.in.architecture = "W32X86";
2898 r.in.level = 1;
2899 r.in.buffer = NULL;
2900 r.in.offered = 0;
2901 r.in.client_major_version = 0;
2902 r.in.client_minor_version = 0;
2903 r.out.needed = &needed;
2904 r.out.server_major_version = &server_major_version;
2905 r.out.server_minor_version = &server_minor_version;
2907 torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2909 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2910 "failed to call GetPrinterDriver2");
2911 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2912 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2913 data_blob_clear(&blob);
2914 r.in.buffer = &blob;
2915 r.in.offered = needed;
2916 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2917 "failed to call GetPrinterDriver2");
2920 torture_assert_werr_ok(tctx, r.out.result,
2921 "failed to call GetPrinterDriver2");
2923 return true;
2926 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2927 struct dcerpc_pipe *p)
2929 struct spoolss_EnumPrinterDrivers r;
2930 NTSTATUS status;
2931 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2932 int i;
2934 for (i=0;i<ARRAY_SIZE(levels);i++) {
2936 uint32_t needed;
2937 uint32_t count;
2938 union spoolss_DriverInfo *info;
2940 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2941 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2942 r.in.level = levels[i];
2943 r.in.buffer = NULL;
2944 r.in.offered = 0;
2945 r.out.needed = &needed;
2946 r.out.count = &count;
2947 r.out.info = &info;
2949 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2951 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2953 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2955 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2956 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2957 data_blob_clear(&blob);
2958 r.in.buffer = &blob;
2959 r.in.offered = needed;
2960 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2963 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2965 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2967 if (!info) {
2968 torture_comment(tctx, "No printer drivers returned\n");
2969 break;
2973 return true;
2976 static bool test_DeletePrinter(struct torture_context *tctx,
2977 struct dcerpc_pipe *p,
2978 struct policy_handle *handle)
2980 struct spoolss_DeletePrinter r;
2982 torture_comment(tctx, "Testing DeletePrinter\n");
2984 r.in.handle = handle;
2986 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2987 "failed to delete printer");
2988 torture_assert_werr_ok(tctx, r.out.result,
2989 "failed to delete printer");
2991 return true;
2994 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2995 struct dcerpc_pipe *p,
2996 uint32_t flags,
2997 uint32_t level,
2998 const char *name,
2999 bool *found)
3001 struct spoolss_EnumPrinters e;
3002 uint32_t count;
3003 union spoolss_PrinterInfo *info;
3004 uint32_t needed;
3005 int i;
3007 *found = false;
3009 e.in.flags = flags;
3010 e.in.server = NULL;
3011 e.in.level = level;
3012 e.in.buffer = NULL;
3013 e.in.offered = 0;
3014 e.out.count = &count;
3015 e.out.info = &info;
3016 e.out.needed = &needed;
3018 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3019 "failed to enum printers");
3021 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
3022 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3023 data_blob_clear(&blob);
3024 e.in.buffer = &blob;
3025 e.in.offered = needed;
3027 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3028 "failed to enum printers");
3031 torture_assert_werr_ok(tctx, e.out.result,
3032 "failed to enum printers");
3034 for (i=0; i < count; i++) {
3036 const char *current = NULL;
3038 switch (level) {
3039 case 1:
3040 current = info[i].info1.name;
3041 break;
3044 if (strequal(current, name)) {
3045 *found = true;
3046 break;
3050 return true;
3053 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
3054 struct dcerpc_pipe *p,
3055 const char *printername,
3056 bool ex)
3058 WERROR result;
3059 struct spoolss_AddPrinter r;
3060 struct spoolss_AddPrinterEx rex;
3061 struct spoolss_SetPrinterInfoCtr info_ctr;
3062 struct spoolss_SetPrinterInfo1 info1;
3063 struct spoolss_DevmodeContainer devmode_ctr;
3064 struct sec_desc_buf secdesc_ctr;
3065 struct spoolss_UserLevelCtr userlevel_ctr;
3066 struct policy_handle handle;
3067 bool found = false;
3069 ZERO_STRUCT(devmode_ctr);
3070 ZERO_STRUCT(secdesc_ctr);
3071 ZERO_STRUCT(userlevel_ctr);
3072 ZERO_STRUCT(info1);
3074 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3076 /* try to add printer to wellknown printer list (level 1) */
3078 userlevel_ctr.level = 1;
3080 info_ctr.info.info1 = &info1;
3081 info_ctr.level = 1;
3083 rex.in.server = NULL;
3084 rex.in.info_ctr = &info_ctr;
3085 rex.in.devmode_ctr = &devmode_ctr;
3086 rex.in.secdesc_ctr = &secdesc_ctr;
3087 rex.in.userlevel_ctr = &userlevel_ctr;
3088 rex.out.handle = &handle;
3090 r.in.server = NULL;
3091 r.in.info_ctr = &info_ctr;
3092 r.in.devmode_ctr = &devmode_ctr;
3093 r.in.secdesc_ctr = &secdesc_ctr;
3094 r.out.handle = &handle;
3096 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3097 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3098 "failed to add printer");
3099 result = ex ? rex.out.result : r.out.result;
3100 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3101 "unexpected result code");
3103 info1.name = printername;
3104 info1.flags = PRINTER_ATTRIBUTE_SHARED;
3106 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3107 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3108 "failed to add printer");
3109 result = ex ? rex.out.result : r.out.result;
3110 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3111 "unexpected result code");
3113 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3114 better do a real check to see the printer is really there */
3116 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3117 PRINTER_ENUM_NETWORK, 1,
3118 printername,
3119 &found),
3120 "failed to enum printers");
3122 torture_assert(tctx, found, "failed to find newly added printer");
3124 info1.flags = 0;
3126 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3127 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3128 "failed to add printer");
3129 result = ex ? rex.out.result : r.out.result;
3130 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3131 "unexpected result code");
3133 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3134 better do a real check to see the printer has really been removed
3135 from the well known printer list */
3137 found = false;
3139 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3140 PRINTER_ENUM_NETWORK, 1,
3141 printername,
3142 &found),
3143 "failed to enum printers");
3144 #if 0
3145 torture_assert(tctx, !found, "printer still in well known printer list");
3146 #endif
3147 return true;
3150 static bool test_AddPrinter_normal(struct torture_context *tctx,
3151 struct dcerpc_pipe *p,
3152 struct policy_handle *handle_p,
3153 const char *printername,
3154 const char *drivername,
3155 const char *portname,
3156 bool ex)
3158 WERROR result;
3159 struct spoolss_AddPrinter r;
3160 struct spoolss_AddPrinterEx rex;
3161 struct spoolss_SetPrinterInfoCtr info_ctr;
3162 struct spoolss_SetPrinterInfo2 info2;
3163 struct spoolss_DevmodeContainer devmode_ctr;
3164 struct sec_desc_buf secdesc_ctr;
3165 struct spoolss_UserLevelCtr userlevel_ctr;
3166 struct policy_handle handle;
3167 bool found = false;
3169 ZERO_STRUCT(devmode_ctr);
3170 ZERO_STRUCT(secdesc_ctr);
3171 ZERO_STRUCT(userlevel_ctr);
3173 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3175 userlevel_ctr.level = 1;
3177 rex.in.server = NULL;
3178 rex.in.info_ctr = &info_ctr;
3179 rex.in.devmode_ctr = &devmode_ctr;
3180 rex.in.secdesc_ctr = &secdesc_ctr;
3181 rex.in.userlevel_ctr = &userlevel_ctr;
3182 rex.out.handle = &handle;
3184 r.in.server = NULL;
3185 r.in.info_ctr = &info_ctr;
3186 r.in.devmode_ctr = &devmode_ctr;
3187 r.in.secdesc_ctr = &secdesc_ctr;
3188 r.out.handle = &handle;
3190 again:
3192 /* try to add printer to printer list (level 2) */
3194 ZERO_STRUCT(info2);
3196 info_ctr.info.info2 = &info2;
3197 info_ctr.level = 2;
3199 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3200 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3201 "failed to add printer");
3202 result = ex ? rex.out.result : r.out.result;
3203 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3204 "unexpected result code");
3206 info2.printername = printername;
3208 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3209 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3210 "failed to add printer");
3211 result = ex ? rex.out.result : r.out.result;
3213 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3214 struct policy_handle printer_handle;
3216 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3217 "failed to open printer handle");
3219 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3220 "failed to delete printer");
3222 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3223 "failed to close server handle");
3225 goto again;
3228 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3229 "unexpected result code");
3231 info2.portname = portname;
3233 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3234 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3235 "failed to add printer");
3236 result = ex ? rex.out.result : r.out.result;
3237 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3238 "unexpected result code");
3240 info2.drivername = drivername;
3242 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3243 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3244 "failed to add printer");
3245 result = ex ? rex.out.result : r.out.result;
3246 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3247 "unexpected result code");
3249 info2.printprocessor = "winprint";
3251 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3252 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3253 "failed to add printer");
3254 result = ex ? rex.out.result : r.out.result;
3255 torture_assert_werr_ok(tctx, result,
3256 "failed to add printer");
3258 *handle_p = handle;
3260 /* we are paranoid, really check if the printer is there now */
3262 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3263 PRINTER_ENUM_LOCAL, 1,
3264 printername,
3265 &found),
3266 "failed to enum printers");
3267 torture_assert(tctx, found, "failed to find newly added printer");
3269 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3270 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3271 "failed to add printer");
3272 result = ex ? rex.out.result : r.out.result;
3273 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3274 "unexpected result code");
3276 return true;
3279 static bool test_AddPrinterEx(struct torture_context *tctx,
3280 struct dcerpc_pipe *p,
3281 struct policy_handle *handle_p,
3282 const char *printername,
3283 const char *drivername,
3284 const char *portname)
3286 bool ret = true;
3288 if (!torture_setting_bool(tctx, "samba3", false)) {
3289 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3290 torture_comment(tctx, "failed to add printer to well known list\n");
3291 ret = false;
3295 if (!test_AddPrinter_normal(tctx, p, handle_p,
3296 printername, drivername, portname,
3297 true)) {
3298 torture_comment(tctx, "failed to add printer to printer list\n");
3299 ret = false;
3302 return ret;
3305 static bool test_AddPrinter(struct torture_context *tctx,
3306 struct dcerpc_pipe *p,
3307 struct policy_handle *handle_p,
3308 const char *printername,
3309 const char *drivername,
3310 const char *portname)
3312 bool ret = true;
3314 if (!torture_setting_bool(tctx, "samba3", false)) {
3315 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3316 torture_comment(tctx, "failed to add printer to well known list\n");
3317 ret = false;
3321 if (!test_AddPrinter_normal(tctx, p, handle_p,
3322 printername, drivername, portname,
3323 false)) {
3324 torture_comment(tctx, "failed to add printer to printer list\n");
3325 ret = false;
3328 return ret;
3331 static bool test_printer_info(struct torture_context *tctx,
3332 struct dcerpc_pipe *p,
3333 struct policy_handle *handle)
3335 bool ret = true;
3337 if (!test_PrinterInfo(tctx, p, handle)) {
3338 ret = false;
3341 if (!test_SetPrinter_errors(tctx, p, handle)) {
3342 ret = false;
3345 return ret;
3348 static bool test_EnumPrinterKey(struct torture_context *tctx,
3349 struct dcerpc_pipe *p,
3350 struct policy_handle *handle,
3351 const char *key_name,
3352 const char ***array)
3354 struct spoolss_EnumPrinterKey r;
3355 uint32_t needed;
3356 struct spoolss_StringArray2 key_buffer;
3357 uint32_t offered[] = { 0, 512, 1024, 2048 };
3358 int i;
3360 r.in.handle = handle;
3361 r.in.key_name = key_name;
3362 r.out.key_buffer = &key_buffer;
3363 r.out.needed = &needed;
3365 for (i=0; i < ARRAY_SIZE(offered); i++) {
3366 r.in.offered = offered[i];
3368 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
3370 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3371 "failed to call EnumPrinterKey");
3372 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3373 torture_assert(tctx, (key_buffer._ndr_size == 0),
3374 talloc_asprintf(tctx, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer._ndr_size));
3375 r.in.offered = needed;
3376 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3377 "failed to call EnumPrinterKey");
3379 torture_assert_werr_ok(tctx, r.out.result,
3380 "failed to call EnumPrinterKey");
3382 torture_assert(tctx, (key_buffer._ndr_size * 2 == r.in.offered),
3383 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3384 key_buffer._ndr_size, r.in.offered/2));
3386 torture_assert(tctx, (*r.out.needed <= r.in.offered),
3387 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
3389 torture_assert(tctx, (*r.out.needed <= key_buffer._ndr_size * 2),
3390 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, key_buffer._ndr_size));
3394 if (array) {
3395 *array = key_buffer.string;
3398 return true;
3401 bool test_printer_keys(struct torture_context *tctx,
3402 struct dcerpc_pipe *p,
3403 struct policy_handle *handle)
3405 const char **key_array = NULL;
3406 int i;
3408 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
3409 "failed to call test_EnumPrinterKey");
3411 for (i=0; key_array && key_array[i]; i++) {
3412 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
3413 "failed to call test_EnumPrinterKey");
3415 for (i=0; key_array && key_array[i]; i++) {
3416 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3417 "failed to call test_EnumPrinterDataEx");
3420 return true;
3423 static bool test_printer(struct torture_context *tctx,
3424 struct dcerpc_pipe *p)
3426 bool ret = true;
3427 struct policy_handle handle[2];
3428 bool found = false;
3429 const char *drivername = "Microsoft XPS Document Writer";
3430 const char *portname = "LPT1:";
3432 /* test printer created via AddPrinter */
3434 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3435 return false;
3438 if (!test_printer_info(tctx, p, &handle[0])) {
3439 ret = false;
3442 if (!test_printer_keys(tctx, p, &handle[0])) {
3443 ret = false;
3446 if (!test_DeletePrinter(tctx, p, &handle[0])) {
3447 ret = false;
3450 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3451 TORTURE_PRINTER, &found)) {
3452 ret = false;
3455 torture_assert(tctx, !found, "deleted printer still there");
3457 /* test printer created via AddPrinterEx */
3459 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3460 return false;
3463 if (!test_printer_info(tctx, p, &handle[1])) {
3464 ret = false;
3467 if (!test_printer_keys(tctx, p, &handle[1])) {
3468 ret = false;
3471 if (!test_DeletePrinter(tctx, p, &handle[1])) {
3472 ret = false;
3475 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3476 TORTURE_PRINTER_EX, &found)) {
3477 ret = false;
3480 torture_assert(tctx, !found, "deleted printer still there");
3482 return ret;
3485 bool torture_rpc_spoolss(struct torture_context *torture)
3487 NTSTATUS status;
3488 struct dcerpc_pipe *p;
3489 bool ret = true;
3490 struct test_spoolss_context *ctx;
3492 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3493 if (!NT_STATUS_IS_OK(status)) {
3494 return false;
3497 ctx = talloc_zero(torture, struct test_spoolss_context);
3499 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3500 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
3501 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3502 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3503 ret &= test_EnumPorts(torture, p, ctx);
3504 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3505 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3506 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3507 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3508 ret &= test_EnumMonitors(torture, p, ctx);
3509 ret &= test_EnumPrintProcessors(torture, p, ctx);
3510 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3511 ret &= test_EnumPrinters(torture, p, ctx);
3512 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3513 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3514 ret &= test_OpenPrinter_badname(torture, p, "");
3515 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3516 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3517 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3518 ret &= test_OpenPrinter_badname(torture, p,
3519 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3522 ret &= test_AddPort(torture, p);
3523 ret &= test_EnumPorts_old(torture, p);
3524 ret &= test_EnumPrinters_old(torture, p);
3525 ret &= test_EnumPrinterDrivers_old(torture, p);
3527 return ret;
3530 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3532 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3534 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3535 "printer", &ndr_table_spoolss);
3537 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3539 return suite;