samba-spoolss: use spoolss_StringArray2 in spoolss_EnumPrinterKey.
[Samba/bb.git] / source4 / torture / rpc / spoolss.c
blobe341b71307221477eee5bda0dca3895fdfa1643a
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[7];
46 union spoolss_DriverInfo *drivers[7];
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_STRING_ARRAY(tctx, c,r,e)
85 static bool test_OpenPrinter_server(struct torture_context *tctx,
86 struct dcerpc_pipe *p,
87 struct policy_handle *server_handle)
89 NTSTATUS status;
90 struct spoolss_OpenPrinter op;
92 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
93 op.in.datatype = NULL;
94 op.in.devmode_ctr.devmode= NULL;
95 op.in.access_mask = 0;
96 op.out.handle = server_handle;
98 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
100 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
101 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
102 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
104 return true;
107 static bool test_EnumPorts(struct torture_context *tctx,
108 struct dcerpc_pipe *p,
109 struct test_spoolss_context *ctx)
111 NTSTATUS status;
112 struct spoolss_EnumPorts r;
113 uint16_t levels[] = { 1, 2 };
114 int i, j;
116 for (i=0;i<ARRAY_SIZE(levels);i++) {
117 int level = levels[i];
118 DATA_BLOB blob;
119 uint32_t needed;
120 uint32_t count;
121 union spoolss_PortInfo *info;
123 r.in.servername = "";
124 r.in.level = level;
125 r.in.buffer = NULL;
126 r.in.offered = 0;
127 r.out.needed = &needed;
128 r.out.count = &count;
129 r.out.info = &info;
131 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
133 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
134 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
135 if (W_ERROR_IS_OK(r.out.result)) {
136 /* TODO: do some more checks here */
137 continue;
139 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
140 "EnumPorts unexpected return code");
142 blob = data_blob_talloc(ctx, NULL, needed);
143 data_blob_clear(&blob);
144 r.in.buffer = &blob;
145 r.in.offered = needed;
147 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
148 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
150 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
152 torture_assert(tctx, info, "EnumPorts returned no info");
154 ctx->port_count[level] = count;
155 ctx->ports[level] = info;
158 for (i=1;i<ARRAY_SIZE(levels);i++) {
159 int level = levels[i];
160 int old_level = levels[i-1];
161 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
162 "EnumPorts invalid value");
164 /* if the array sizes are not the same we would maybe segfault in the following code */
166 for (i=0;i<ARRAY_SIZE(levels);i++) {
167 int level = levels[i];
168 for (j=0;j<ctx->port_count[level];j++) {
169 union spoolss_PortInfo *cur = &ctx->ports[level][j];
170 union spoolss_PortInfo *ref = &ctx->ports[2][j];
171 switch (level) {
172 case 1:
173 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
174 break;
175 case 2:
176 /* level 2 is our reference, and it makes no sense to compare it to itself */
177 break;
182 return true;
185 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
186 struct dcerpc_pipe *p,
187 struct test_spoolss_context *ctx)
189 NTSTATUS status;
190 struct spoolss_GetPrintProcessorDirectory r;
191 struct {
192 uint16_t level;
193 const char *server;
194 } levels[] = {{
195 .level = 1,
196 .server = NULL
198 .level = 1,
199 .server = ""
201 .level = 78,
202 .server = ""
204 .level = 1,
205 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
207 .level = 1024,
208 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
211 int i;
212 uint32_t needed;
214 for (i=0;i<ARRAY_SIZE(levels);i++) {
215 int level = levels[i].level;
216 DATA_BLOB blob;
218 r.in.server = levels[i].server;
219 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
220 r.in.level = level;
221 r.in.buffer = NULL;
222 r.in.offered = 0;
223 r.out.needed = &needed;
225 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
227 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
228 torture_assert_ntstatus_ok(tctx, status,
229 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
230 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
231 "GetPrintProcessorDirectory unexpected return code");
233 blob = data_blob_talloc(ctx, NULL, needed);
234 data_blob_clear(&blob);
235 r.in.buffer = &blob;
236 r.in.offered = needed;
238 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
239 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
241 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
244 return true;
248 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
249 struct dcerpc_pipe *p,
250 struct test_spoolss_context *ctx)
252 NTSTATUS status;
253 struct spoolss_GetPrinterDriverDirectory r;
254 struct {
255 uint16_t level;
256 const char *server;
257 } levels[] = {{
258 .level = 1,
259 .server = NULL
261 .level = 1,
262 .server = ""
264 .level = 78,
265 .server = ""
267 .level = 1,
268 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
270 .level = 1024,
271 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
274 int i;
275 uint32_t needed;
277 for (i=0;i<ARRAY_SIZE(levels);i++) {
278 int level = levels[i].level;
279 DATA_BLOB blob;
281 r.in.server = levels[i].server;
282 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
283 r.in.level = level;
284 r.in.buffer = NULL;
285 r.in.offered = 0;
286 r.out.needed = &needed;
288 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
290 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
291 torture_assert_ntstatus_ok(tctx, status,
292 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
293 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
294 "GetPrinterDriverDirectory unexpected return code");
296 blob = data_blob_talloc(ctx, NULL, needed);
297 data_blob_clear(&blob);
298 r.in.buffer = &blob;
299 r.in.offered = needed;
301 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
302 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
304 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
307 return true;
310 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
311 struct dcerpc_pipe *p,
312 struct test_spoolss_context *ctx)
314 NTSTATUS status;
315 struct spoolss_EnumPrinterDrivers r;
316 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
317 int i, j, a;
318 const char *architectures[] = {
319 SPOOLSS_ARCHITECTURE_NT_X86,
320 SPOOLSS_ARCHITECTURE_ALL
323 for (i=0;i<ARRAY_SIZE(levels);i++) {
324 for (a=0;a<ARRAY_SIZE(architectures);a++) {
325 int level = levels[i];
326 DATA_BLOB blob;
327 uint32_t needed;
328 uint32_t count;
329 union spoolss_DriverInfo *info;
331 /* FIXME: gd, come back and fix "" as server, and handle
332 * priority of returned error codes in torture test and samba 3
333 * server */
335 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
336 r.in.environment = architectures[a];
337 r.in.level = level;
338 r.in.buffer = NULL;
339 r.in.offered = 0;
340 r.out.needed = &needed;
341 r.out.count = &count;
342 r.out.info = &info;
344 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
346 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
347 torture_assert_ntstatus_ok(tctx, status,
348 "dcerpc_spoolss_EnumPrinterDrivers failed");
349 if (W_ERROR_IS_OK(r.out.result)) {
350 /* TODO: do some more checks here */
351 continue;
353 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
354 blob = data_blob_talloc(ctx, NULL, needed);
355 data_blob_clear(&blob);
356 r.in.buffer = &blob;
357 r.in.offered = needed;
359 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
360 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
363 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
365 /* don't do cross-architecture comparison */
366 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
367 continue;
370 ctx->driver_count[level] = count;
371 ctx->drivers[level] = info;
375 for (i=1;i<ARRAY_SIZE(levels);i++) {
376 int level = levels[i];
377 int old_level = levels[i-1];
379 /* don't do cross-architecture comparison */
380 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
381 continue;
384 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
385 "EnumPrinterDrivers invalid value");
388 for (i=0;i<ARRAY_SIZE(levels);i++) {
389 int level = levels[i];
391 /* don't do cross-architecture comparison */
392 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
393 continue;
396 for (j=0;j<ctx->driver_count[level];j++) {
397 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
398 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
399 switch (level) {
400 case 1:
401 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
402 break;
403 case 2:
404 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
405 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
406 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
407 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
408 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
409 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
410 break;
411 case 3:
412 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
413 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
414 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
415 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
416 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
417 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
418 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
419 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
420 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
421 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
422 break;
423 case 4:
424 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
425 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
426 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
427 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
428 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
429 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
430 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
431 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
432 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
433 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
434 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
435 break;
436 case 5:
437 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
438 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
439 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
440 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
441 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
442 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
443 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
444 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
445 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
446 break;
447 case 6:
448 /* level 6 is our reference, and it makes no sense to compare it to itself */
449 break;
454 return true;
457 static bool test_EnumMonitors(struct torture_context *tctx,
458 struct dcerpc_pipe *p,
459 struct test_spoolss_context *ctx)
461 NTSTATUS status;
462 struct spoolss_EnumMonitors r;
463 uint16_t levels[] = { 1, 2 };
464 int i, j;
466 for (i=0;i<ARRAY_SIZE(levels);i++) {
467 int level = levels[i];
468 DATA_BLOB blob;
469 uint32_t needed;
470 uint32_t count;
471 union spoolss_MonitorInfo *info;
473 r.in.servername = "";
474 r.in.level = level;
475 r.in.buffer = NULL;
476 r.in.offered = 0;
477 r.out.needed = &needed;
478 r.out.count = &count;
479 r.out.info = &info;
481 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
483 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
484 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
485 if (W_ERROR_IS_OK(r.out.result)) {
486 /* TODO: do some more checks here */
487 continue;
489 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
490 "EnumMonitors failed");
492 blob = data_blob_talloc(ctx, NULL, needed);
493 data_blob_clear(&blob);
494 r.in.buffer = &blob;
495 r.in.offered = needed;
497 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
498 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
500 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
502 ctx->monitor_count[level] = count;
503 ctx->monitors[level] = info;
506 for (i=1;i<ARRAY_SIZE(levels);i++) {
507 int level = levels[i];
508 int old_level = levels[i-1];
509 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
510 "EnumMonitors invalid value");
513 for (i=0;i<ARRAY_SIZE(levels);i++) {
514 int level = levels[i];
515 for (j=0;j<ctx->monitor_count[level];j++) {
516 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
517 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
518 switch (level) {
519 case 1:
520 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
521 break;
522 case 2:
523 /* level 2 is our reference, and it makes no sense to compare it to itself */
524 break;
529 return true;
532 static bool test_EnumPrintProcessors(struct torture_context *tctx,
533 struct dcerpc_pipe *p,
534 struct test_spoolss_context *ctx)
536 NTSTATUS status;
537 struct spoolss_EnumPrintProcessors r;
538 uint16_t levels[] = { 1 };
539 int i, j;
541 for (i=0;i<ARRAY_SIZE(levels);i++) {
542 int level = levels[i];
543 DATA_BLOB blob;
544 uint32_t needed;
545 uint32_t count;
546 union spoolss_PrintProcessorInfo *info;
548 r.in.servername = "";
549 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
550 r.in.level = level;
551 r.in.buffer = NULL;
552 r.in.offered = 0;
553 r.out.needed = &needed;
554 r.out.count = &count;
555 r.out.info = &info;
557 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
559 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
560 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
561 if (W_ERROR_IS_OK(r.out.result)) {
562 /* TODO: do some more checks here */
563 continue;
565 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
566 "EnumPrintProcessors unexpected return code");
568 blob = data_blob_talloc(ctx, NULL, needed);
569 data_blob_clear(&blob);
570 r.in.buffer = &blob;
571 r.in.offered = needed;
573 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
574 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
576 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
578 ctx->print_processor_count[level] = count;
579 ctx->print_processors[level] = info;
582 for (i=1;i<ARRAY_SIZE(levels);i++) {
583 int level = levels[i];
584 int old_level = levels[i-1];
585 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
586 "EnumPrintProcessors failed");
589 for (i=0;i<ARRAY_SIZE(levels);i++) {
590 int level = levels[i];
591 for (j=0;j<ctx->print_processor_count[level];j++) {
592 #if 0
593 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
594 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
595 #endif
596 switch (level) {
597 case 1:
598 /* level 1 is our reference, and it makes no sense to compare it to itself */
599 break;
604 return true;
607 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
608 struct dcerpc_pipe *p,
609 struct test_spoolss_context *ctx)
611 NTSTATUS status;
612 struct spoolss_EnumPrintProcDataTypes r;
613 uint16_t levels[] = { 1 };
614 int i;
616 for (i=0;i<ARRAY_SIZE(levels);i++) {
617 int level = levels[i];
618 DATA_BLOB blob;
619 uint32_t needed;
620 uint32_t count;
621 union spoolss_PrintProcDataTypesInfo *info;
623 r.in.servername = "";
624 r.in.print_processor_name = "winprint";
625 r.in.level = level;
626 r.in.buffer = NULL;
627 r.in.offered = 0;
628 r.out.needed = &needed;
629 r.out.count = &count;
630 r.out.info = &info;
632 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
634 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
635 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
636 if (W_ERROR_IS_OK(r.out.result)) {
637 /* TODO: do some more checks here */
638 continue;
640 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
641 "EnumPrintProcDataTypes unexpected return code");
643 blob = data_blob_talloc(ctx, NULL, needed);
644 data_blob_clear(&blob);
645 r.in.buffer = &blob;
646 r.in.offered = needed;
648 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
649 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
651 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
654 return true;
658 static bool test_EnumPrinters(struct torture_context *tctx,
659 struct dcerpc_pipe *p,
660 struct test_spoolss_context *ctx)
662 struct spoolss_EnumPrinters r;
663 NTSTATUS status;
664 uint16_t levels[] = { 0, 1, 2, 4, 5 };
665 int i, j;
667 for (i=0;i<ARRAY_SIZE(levels);i++) {
668 int level = levels[i];
669 DATA_BLOB blob;
670 uint32_t needed;
671 uint32_t count;
672 union spoolss_PrinterInfo *info;
674 r.in.flags = PRINTER_ENUM_LOCAL;
675 r.in.server = "";
676 r.in.level = level;
677 r.in.buffer = NULL;
678 r.in.offered = 0;
679 r.out.needed = &needed;
680 r.out.count = &count;
681 r.out.info = &info;
683 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
685 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
686 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
687 if (W_ERROR_IS_OK(r.out.result)) {
688 /* TODO: do some more checks here */
689 continue;
691 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
692 "EnumPrinters unexpected return code");
694 blob = data_blob_talloc(ctx, NULL, needed);
695 data_blob_clear(&blob);
696 r.in.buffer = &blob;
697 r.in.offered = needed;
699 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
700 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
702 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
704 ctx->printer_count[level] = count;
705 ctx->printers[level] = info;
708 for (i=1;i<ARRAY_SIZE(levels);i++) {
709 int level = levels[i];
710 int old_level = levels[i-1];
711 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
712 "EnumPrinters invalid value");
715 for (i=0;i<ARRAY_SIZE(levels);i++) {
716 int level = levels[i];
717 for (j=0;j<ctx->printer_count[level];j++) {
718 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
719 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
720 switch (level) {
721 case 0:
722 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
723 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
725 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
727 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
737 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
739 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
740 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
742 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
743 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
744 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
745 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
746 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
747 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
748 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
749 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
750 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
751 break;
752 case 1:
753 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
754 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
755 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
756 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
757 break;
758 case 2:
759 /* level 2 is our reference, and it makes no sense to compare it to itself */
760 break;
761 case 4:
762 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
763 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
764 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
765 break;
766 case 5:
767 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
768 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
769 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
770 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
771 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
772 break;
777 /* TODO:
778 * - verify that the port of a printer was in the list returned by EnumPorts
781 return true;
784 static bool test_GetPrinter(struct torture_context *tctx,
785 struct dcerpc_pipe *p,
786 struct policy_handle *handle)
788 NTSTATUS status;
789 struct spoolss_GetPrinter r;
790 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
791 int i;
792 uint32_t needed;
794 for (i=0;i<ARRAY_SIZE(levels);i++) {
795 r.in.handle = handle;
796 r.in.level = levels[i];
797 r.in.buffer = NULL;
798 r.in.offered = 0;
799 r.out.needed = &needed;
801 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
803 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
804 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
806 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
807 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
808 data_blob_clear(&blob);
809 r.in.buffer = &blob;
810 r.in.offered = needed;
811 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
814 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
816 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
819 return true;
822 static bool test_SetPrinter_errors(struct torture_context *tctx,
823 struct dcerpc_pipe *p,
824 struct policy_handle *handle)
826 struct spoolss_SetPrinter r;
827 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
828 int i;
830 struct spoolss_SetPrinterInfoCtr info_ctr;
831 struct spoolss_DevmodeContainer devmode_ctr;
832 struct sec_desc_buf secdesc_ctr;
834 info_ctr.level = 0;
835 info_ctr.info.info0 = NULL;
837 ZERO_STRUCT(devmode_ctr);
838 ZERO_STRUCT(secdesc_ctr);
840 r.in.handle = handle;
841 r.in.info_ctr = &info_ctr;
842 r.in.devmode_ctr = &devmode_ctr;
843 r.in.secdesc_ctr = &secdesc_ctr;
844 r.in.command = 0;
846 torture_comment(tctx, "Testing SetPrinter all zero\n");
848 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
849 "failed to call SetPrinter");
850 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
851 "failed to call SetPrinter");
853 again:
854 for (i=0; i < ARRAY_SIZE(levels); i++) {
856 struct spoolss_SetPrinterInfo0 info0;
857 struct spoolss_SetPrinterInfo1 info1;
858 struct spoolss_SetPrinterInfo2 info2;
859 struct spoolss_SetPrinterInfo3 info3;
860 struct spoolss_SetPrinterInfo4 info4;
861 struct spoolss_SetPrinterInfo5 info5;
862 struct spoolss_SetPrinterInfo6 info6;
863 struct spoolss_SetPrinterInfo7 info7;
864 struct spoolss_DeviceModeInfo info8;
865 struct spoolss_DeviceModeInfo info9;
868 info_ctr.level = levels[i];
869 switch (levels[i]) {
870 case 0:
871 ZERO_STRUCT(info0);
872 info_ctr.info.info0 = &info0;
873 break;
874 case 1:
875 ZERO_STRUCT(info1);
876 info_ctr.info.info1 = &info1;
877 break;
878 case 2:
879 ZERO_STRUCT(info2);
880 info_ctr.info.info2 = &info2;
881 break;
882 case 3:
883 ZERO_STRUCT(info3);
884 info_ctr.info.info3 = &info3;
885 break;
886 case 4:
887 ZERO_STRUCT(info4);
888 info_ctr.info.info4 = &info4;
889 break;
890 case 5:
891 ZERO_STRUCT(info5);
892 info_ctr.info.info5 = &info5;
893 break;
894 case 6:
895 ZERO_STRUCT(info6);
896 info_ctr.info.info6 = &info6;
897 break;
898 case 7:
899 ZERO_STRUCT(info7);
900 info_ctr.info.info7 = &info7;
901 break;
902 case 8:
903 ZERO_STRUCT(info8);
904 info_ctr.info.info8 = &info8;
905 break;
906 case 9:
907 ZERO_STRUCT(info9);
908 info_ctr.info.info9 = &info9;
909 break;
912 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
913 info_ctr.level, r.in.command);
915 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
916 "failed to call SetPrinter");
918 switch (r.in.command) {
919 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
920 /* is ignored for all levels other then 0 */
921 if (info_ctr.level > 0) {
922 /* ignored then */
923 break;
925 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
926 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
927 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
928 if (info_ctr.level > 0) {
929 /* is invalid for all levels other then 0 */
930 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
931 "unexpected error code returned");
932 continue;
933 } else {
934 torture_assert_werr_ok(tctx, r.out.result,
935 "failed to call SetPrinter with non 0 command");
936 continue;
938 break;
940 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
941 /* FIXME: gd needs further investigation */
942 default:
943 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
944 "unexpected error code returned");
945 continue;
948 switch (info_ctr.level) {
949 case 1:
950 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
951 "unexpected error code returned");
952 break;
953 case 2:
954 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
955 "unexpected error code returned");
956 break;
957 case 3:
958 case 4:
959 case 5:
960 case 7:
961 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
962 "unexpected error code returned");
963 break;
964 case 9:
965 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
966 "unexpected error code returned");
967 break;
968 default:
969 torture_assert_werr_ok(tctx, r.out.result,
970 "failed to call SetPrinter");
971 break;
975 if (r.in.command < 5) {
976 r.in.command++;
977 goto again;
980 return true;
983 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
985 if ((r->level == 2) && (r->info.info2)) {
986 r->info.info2->secdesc = NULL;
987 r->info.info2->devmode = NULL;
991 static bool test_PrinterInfo(struct torture_context *tctx,
992 struct dcerpc_pipe *p,
993 struct policy_handle *handle)
995 NTSTATUS status;
996 struct spoolss_SetPrinter s;
997 struct spoolss_GetPrinter q;
998 struct spoolss_GetPrinter q0;
999 struct spoolss_SetPrinterInfoCtr info_ctr;
1000 union spoolss_PrinterInfo info;
1001 struct spoolss_DevmodeContainer devmode_ctr;
1002 struct sec_desc_buf secdesc_ctr;
1003 uint32_t needed;
1004 bool ret = true;
1005 int i;
1007 uint32_t status_list[] = {
1008 /* these do not stick
1009 PRINTER_STATUS_PAUSED,
1010 PRINTER_STATUS_ERROR,
1011 PRINTER_STATUS_PENDING_DELETION, */
1012 PRINTER_STATUS_PAPER_JAM,
1013 PRINTER_STATUS_PAPER_OUT,
1014 PRINTER_STATUS_MANUAL_FEED,
1015 PRINTER_STATUS_PAPER_PROBLEM,
1016 PRINTER_STATUS_OFFLINE,
1017 PRINTER_STATUS_IO_ACTIVE,
1018 PRINTER_STATUS_BUSY,
1019 PRINTER_STATUS_PRINTING,
1020 PRINTER_STATUS_OUTPUT_BIN_FULL,
1021 PRINTER_STATUS_NOT_AVAILABLE,
1022 PRINTER_STATUS_WAITING,
1023 PRINTER_STATUS_PROCESSING,
1024 PRINTER_STATUS_INITIALIZING,
1025 PRINTER_STATUS_WARMING_UP,
1026 PRINTER_STATUS_TONER_LOW,
1027 PRINTER_STATUS_NO_TONER,
1028 PRINTER_STATUS_PAGE_PUNT,
1029 PRINTER_STATUS_USER_INTERVENTION,
1030 PRINTER_STATUS_OUT_OF_MEMORY,
1031 PRINTER_STATUS_DOOR_OPEN,
1032 PRINTER_STATUS_SERVER_UNKNOWN,
1033 PRINTER_STATUS_POWER_SAVE,
1034 /* these do not stick
1035 0x02000000,
1036 0x04000000,
1037 0x08000000,
1038 0x10000000,
1039 0x20000000,
1040 0x40000000,
1041 0x80000000 */
1043 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1044 uint32_t attribute_list[] = {
1045 PRINTER_ATTRIBUTE_QUEUED,
1046 /* fails with WERR_INVALID_DATATYPE:
1047 PRINTER_ATTRIBUTE_DIRECT, */
1048 /* does not stick
1049 PRINTER_ATTRIBUTE_DEFAULT, */
1050 PRINTER_ATTRIBUTE_SHARED,
1051 /* does not stick
1052 PRINTER_ATTRIBUTE_NETWORK, */
1053 PRINTER_ATTRIBUTE_HIDDEN,
1054 PRINTER_ATTRIBUTE_LOCAL,
1055 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1056 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1057 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1058 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1059 /* does not stick
1060 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1061 /* fails with WERR_INVALID_DATATYPE:
1062 PRINTER_ATTRIBUTE_RAW_ONLY, */
1063 /* these do not stick
1064 PRINTER_ATTRIBUTE_PUBLISHED,
1065 PRINTER_ATTRIBUTE_FAX,
1066 PRINTER_ATTRIBUTE_TS,
1067 0x00010000,
1068 0x00020000,
1069 0x00040000,
1070 0x00080000,
1071 0x00100000,
1072 0x00200000,
1073 0x00400000,
1074 0x00800000,
1075 0x01000000,
1076 0x02000000,
1077 0x04000000,
1078 0x08000000,
1079 0x10000000,
1080 0x20000000,
1081 0x40000000,
1082 0x80000000 */
1085 ZERO_STRUCT(devmode_ctr);
1086 ZERO_STRUCT(secdesc_ctr);
1088 s.in.handle = handle;
1089 s.in.command = 0;
1090 s.in.info_ctr = &info_ctr;
1091 s.in.devmode_ctr = &devmode_ctr;
1092 s.in.secdesc_ctr = &secdesc_ctr;
1094 q.in.handle = handle;
1095 q.out.info = &info;
1096 q0 = q;
1098 #define TESTGETCALL(call, r) \
1099 r.in.buffer = NULL; \
1100 r.in.offered = 0;\
1101 r.out.needed = &needed; \
1102 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1103 if (!NT_STATUS_IS_OK(status)) { \
1104 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1105 r.in.level, nt_errstr(status), __location__); \
1106 ret = false; \
1107 break; \
1109 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1110 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1111 data_blob_clear(&blob); \
1112 r.in.buffer = &blob; \
1113 r.in.offered = needed; \
1115 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1116 if (!NT_STATUS_IS_OK(status)) { \
1117 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1118 r.in.level, nt_errstr(status), __location__); \
1119 ret = false; \
1120 break; \
1122 if (!W_ERROR_IS_OK(r.out.result)) { \
1123 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1124 r.in.level, win_errstr(r.out.result), __location__); \
1125 ret = false; \
1126 break; \
1130 #define TESTSETCALL_EXP(call, r, err) \
1131 clear_info2(&info_ctr);\
1132 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1133 if (!NT_STATUS_IS_OK(status)) { \
1134 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1135 r.in.info_ctr->level, nt_errstr(status), __location__); \
1136 ret = false; \
1137 break; \
1139 if (!W_ERROR_IS_OK(err)) { \
1140 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1141 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1142 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1143 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.info_ctr->level, win_errstr(r.out.result), __location__); \
1150 ret = false; \
1151 break; \
1154 #define TESTSETCALL(call, r) \
1155 TESTSETCALL_EXP(call, r, WERR_OK)
1157 #define STRING_EQUAL(s1, s2, field) \
1158 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1159 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1160 #field, s2, __location__); \
1161 ret = false; \
1162 break; \
1165 #define MEM_EQUAL(s1, s2, length, field) \
1166 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1167 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1168 #field, (const char *)s2, __location__); \
1169 ret = false; \
1170 break; \
1173 #define INT_EQUAL(i1, i2, field) \
1174 if (i1 != i2) { \
1175 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1176 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1177 ret = false; \
1178 break; \
1181 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1182 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1183 q.in.level = lvl1; \
1184 TESTGETCALL(GetPrinter, q) \
1185 info_ctr.level = lvl1; \
1186 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1187 info_ctr.info.info ## lvl1->field1 = value;\
1188 TESTSETCALL_EXP(SetPrinter, s, err) \
1189 info_ctr.info.info ## lvl1->field1 = ""; \
1190 TESTGETCALL(GetPrinter, q) \
1191 info_ctr.info.info ## lvl1->field1 = value; \
1192 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1193 q.in.level = lvl2; \
1194 TESTGETCALL(GetPrinter, q) \
1195 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1196 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1197 } while (0)
1199 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1200 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1201 } while (0);
1203 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1204 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1205 q.in.level = lvl1; \
1206 TESTGETCALL(GetPrinter, q) \
1207 info_ctr.level = lvl1; \
1208 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1209 info_ctr.info.info ## lvl1->field1 = value; \
1210 TESTSETCALL(SetPrinter, s) \
1211 info_ctr.info.info ## lvl1->field1 = 0; \
1212 TESTGETCALL(GetPrinter, q) \
1213 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1214 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1215 q.in.level = lvl2; \
1216 TESTGETCALL(GetPrinter, q) \
1217 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1218 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1219 } while (0)
1221 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1222 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1223 } while (0)
1225 q0.in.level = 0;
1226 do { TESTGETCALL(GetPrinter, q0) } while (0);
1228 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1229 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1231 /* level 0 printername does not stick */
1232 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1233 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1234 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1235 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1236 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1237 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1238 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1239 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1240 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1241 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1242 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1243 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1244 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1245 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1246 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1248 /* servername can be set but does not stick
1249 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1250 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1251 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1254 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1255 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1256 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1257 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1258 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1260 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1261 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1262 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1263 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1264 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1265 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1266 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1267 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1268 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1269 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1271 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1272 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1273 attribute_list[i],
1274 (attribute_list[i] | default_attribute)
1275 ); */
1276 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1277 attribute_list[i],
1278 (attribute_list[i] | default_attribute)
1280 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1281 attribute_list[i],
1282 (attribute_list[i] | default_attribute)
1284 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1285 attribute_list[i],
1286 (attribute_list[i] | default_attribute)
1288 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1289 attribute_list[i],
1290 (attribute_list[i] | default_attribute)
1291 ); */
1292 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1293 attribute_list[i],
1294 (attribute_list[i] | default_attribute)
1296 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1297 attribute_list[i],
1298 (attribute_list[i] | default_attribute)
1300 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1301 attribute_list[i],
1302 (attribute_list[i] | default_attribute)
1304 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1305 attribute_list[i],
1306 (attribute_list[i] | default_attribute)
1307 ); */
1308 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1309 attribute_list[i],
1310 (attribute_list[i] | default_attribute)
1312 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1313 attribute_list[i],
1314 (attribute_list[i] | default_attribute)
1316 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1317 attribute_list[i],
1318 (attribute_list[i] | default_attribute)
1322 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1323 /* level 2 sets do not stick
1324 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1325 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1326 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1327 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1328 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1329 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1332 /* priorities need to be between 0 and 99
1333 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1334 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1335 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1336 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1337 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1338 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1339 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1340 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1341 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1343 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1344 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1346 /* does not stick
1347 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1348 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1350 /* does not stick
1351 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1352 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1354 /* FIXME: gd also test devmode and secdesc behavior */
1357 /* verify composition of level 1 description field */
1358 const char *description;
1359 const char *tmp;
1361 q0.in.level = 1;
1362 do { TESTGETCALL(GetPrinter, q0) } while (0);
1364 description = talloc_strdup(tctx, q0.out.info->info1.description);
1366 q0.in.level = 2;
1367 do { TESTGETCALL(GetPrinter, q0) } while (0);
1369 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1370 q0.out.info->info2.printername,
1371 q0.out.info->info2.drivername,
1372 q0.out.info->info2.location);
1374 do { STRING_EQUAL(description, tmp, "description")} while (0);
1377 return ret;
1381 static bool test_ClosePrinter(struct torture_context *tctx,
1382 struct dcerpc_pipe *p,
1383 struct policy_handle *handle)
1385 NTSTATUS status;
1386 struct spoolss_ClosePrinter r;
1388 r.in.handle = handle;
1389 r.out.handle = handle;
1391 torture_comment(tctx, "Testing ClosePrinter\n");
1393 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1394 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1396 return true;
1399 static bool test_GetForm(struct torture_context *tctx,
1400 struct dcerpc_pipe *p,
1401 struct policy_handle *handle,
1402 const char *form_name,
1403 uint32_t level)
1405 NTSTATUS status;
1406 struct spoolss_GetForm r;
1407 uint32_t needed;
1409 r.in.handle = handle;
1410 r.in.form_name = form_name;
1411 r.in.level = level;
1412 r.in.buffer = NULL;
1413 r.in.offered = 0;
1414 r.out.needed = &needed;
1416 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1418 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1419 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1421 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1422 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1423 data_blob_clear(&blob);
1424 r.in.buffer = &blob;
1425 r.in.offered = needed;
1426 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1427 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1429 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1431 torture_assert(tctx, r.out.info, "No form info returned");
1434 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1436 return true;
1439 static bool test_EnumForms(struct torture_context *tctx,
1440 struct dcerpc_pipe *p,
1441 struct policy_handle *handle, bool print_server)
1443 NTSTATUS status;
1444 struct spoolss_EnumForms r;
1445 bool ret = true;
1446 uint32_t needed;
1447 uint32_t count;
1448 uint32_t levels[] = { 1, 2 };
1449 int i;
1451 for (i=0; i<ARRAY_SIZE(levels); i++) {
1453 union spoolss_FormInfo *info;
1455 r.in.handle = handle;
1456 r.in.level = levels[i];
1457 r.in.buffer = NULL;
1458 r.in.offered = 0;
1459 r.out.needed = &needed;
1460 r.out.count = &count;
1461 r.out.info = &info;
1463 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1465 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1466 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1468 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1469 break;
1472 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1473 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1475 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1476 int j;
1477 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1478 data_blob_clear(&blob);
1479 r.in.buffer = &blob;
1480 r.in.offered = needed;
1482 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1484 torture_assert(tctx, info, "No forms returned");
1486 for (j = 0; j < count; j++) {
1487 if (!print_server)
1488 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1492 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1494 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1497 return true;
1500 static bool test_DeleteForm(struct torture_context *tctx,
1501 struct dcerpc_pipe *p,
1502 struct policy_handle *handle,
1503 const char *form_name)
1505 NTSTATUS status;
1506 struct spoolss_DeleteForm r;
1508 r.in.handle = handle;
1509 r.in.form_name = form_name;
1511 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1513 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1515 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1517 return true;
1520 static bool test_AddForm(struct torture_context *tctx,
1521 struct dcerpc_pipe *p,
1522 struct policy_handle *handle, bool print_server)
1524 struct spoolss_AddForm r;
1525 struct spoolss_AddFormInfo1 addform;
1526 const char *form_name = "testform3";
1527 NTSTATUS status;
1528 bool ret = true;
1530 r.in.handle = handle;
1531 r.in.level = 1;
1532 r.in.info.info1 = &addform;
1533 addform.flags = SPOOLSS_FORM_USER;
1534 addform.form_name = form_name;
1535 addform.size.width = 50;
1536 addform.size.height = 25;
1537 addform.area.left = 5;
1538 addform.area.top = 10;
1539 addform.area.right = 45;
1540 addform.area.bottom = 15;
1542 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1544 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1546 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1548 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1551 struct spoolss_SetForm sf;
1552 struct spoolss_AddFormInfo1 setform;
1554 sf.in.handle = handle;
1555 sf.in.form_name = form_name;
1556 sf.in.level = 1;
1557 sf.in.info.info1= &setform;
1558 setform.flags = addform.flags;
1559 setform.form_name = addform.form_name;
1560 setform.size = addform.size;
1561 setform.area = addform.area;
1563 setform.size.width = 1234;
1565 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1567 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1569 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1572 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1575 struct spoolss_EnumForms e;
1576 union spoolss_FormInfo *info;
1577 uint32_t needed;
1578 uint32_t count;
1579 bool found = false;
1581 e.in.handle = handle;
1582 e.in.level = 1;
1583 e.in.buffer = NULL;
1584 e.in.offered = 0;
1585 e.out.needed = &needed;
1586 e.out.count = &count;
1587 e.out.info = &info;
1589 torture_comment(tctx, "Testing EnumForms level 1\n");
1591 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1592 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1594 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1595 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1597 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1598 int j;
1599 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1600 data_blob_clear(&blob);
1601 e.in.buffer = &blob;
1602 e.in.offered = needed;
1604 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1606 torture_assert(tctx, info, "No forms returned");
1608 for (j = 0; j < count; j++) {
1609 if (strequal(form_name, info[j].info1.form_name)) {
1610 found = true;
1611 break;
1615 torture_assert(tctx, found, "Newly added form not found in enum call");
1618 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1619 ret = false;
1622 return ret;
1625 static bool test_EnumPorts_old(struct torture_context *tctx,
1626 struct dcerpc_pipe *p)
1628 NTSTATUS status;
1629 struct spoolss_EnumPorts r;
1630 uint32_t needed;
1631 uint32_t count;
1632 union spoolss_PortInfo *info;
1634 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1635 dcerpc_server_name(p));
1636 r.in.level = 2;
1637 r.in.buffer = NULL;
1638 r.in.offered = 0;
1639 r.out.needed = &needed;
1640 r.out.count = &count;
1641 r.out.info = &info;
1643 torture_comment(tctx, "Testing EnumPorts\n");
1645 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1647 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1649 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1650 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1651 data_blob_clear(&blob);
1652 r.in.buffer = &blob;
1653 r.in.offered = needed;
1655 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1656 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1658 torture_assert(tctx, info, "No ports returned");
1661 return true;
1664 static bool test_AddPort(struct torture_context *tctx,
1665 struct dcerpc_pipe *p)
1667 NTSTATUS status;
1668 struct spoolss_AddPort r;
1670 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1671 dcerpc_server_name(p));
1672 r.in.unknown = 0;
1673 r.in.monitor_name = "foo";
1675 torture_comment(tctx, "Testing AddPort\n");
1677 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1679 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1681 /* win2k3 returns WERR_NOT_SUPPORTED */
1683 #if 0
1685 if (!W_ERROR_IS_OK(r.out.result)) {
1686 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1687 return false;
1690 #endif
1692 return true;
1695 static bool test_GetJob(struct torture_context *tctx,
1696 struct dcerpc_pipe *p,
1697 struct policy_handle *handle, uint32_t job_id)
1699 NTSTATUS status;
1700 struct spoolss_GetJob r;
1701 union spoolss_JobInfo info;
1702 uint32_t needed;
1703 uint32_t levels[] = {1, 2 /* 3, 4 */};
1704 uint32_t i;
1706 r.in.handle = handle;
1707 r.in.job_id = job_id;
1708 r.in.level = 0;
1709 r.in.buffer = NULL;
1710 r.in.offered = 0;
1711 r.out.needed = &needed;
1712 r.out.info = &info;
1714 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1716 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1717 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1719 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1721 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1723 needed = 0;
1725 r.in.level = levels[i];
1726 r.in.offered = 0;
1727 r.in.buffer = NULL;
1729 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1730 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1732 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1733 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1734 data_blob_clear(&blob);
1735 r.in.buffer = &blob;
1736 r.in.offered = needed;
1738 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1739 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1742 torture_assert(tctx, r.out.info, "No job info returned");
1743 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1746 return true;
1749 static bool test_SetJob(struct torture_context *tctx,
1750 struct dcerpc_pipe *p,
1751 struct policy_handle *handle, uint32_t job_id,
1752 enum spoolss_JobControl command)
1754 NTSTATUS status;
1755 struct spoolss_SetJob r;
1757 r.in.handle = handle;
1758 r.in.job_id = job_id;
1759 r.in.ctr = NULL;
1760 r.in.command = command;
1762 switch (command) {
1763 case SPOOLSS_JOB_CONTROL_PAUSE:
1764 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1765 break;
1766 case SPOOLSS_JOB_CONTROL_RESUME:
1767 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1768 break;
1769 case SPOOLSS_JOB_CONTROL_CANCEL:
1770 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1771 break;
1772 case SPOOLSS_JOB_CONTROL_RESTART:
1773 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1774 break;
1775 case SPOOLSS_JOB_CONTROL_DELETE:
1776 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1777 break;
1778 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1779 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1780 break;
1781 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1782 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1783 break;
1784 case SPOOLSS_JOB_CONTROL_RETAIN:
1785 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1786 break;
1787 case SPOOLSS_JOB_CONTROL_RELEASE:
1788 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1789 break;
1790 default:
1791 torture_comment(tctx, "Testing SetJob\n");
1792 break;
1795 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1796 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1797 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1799 return true;
1802 static bool test_AddJob(struct torture_context *tctx,
1803 struct dcerpc_pipe *p,
1804 struct policy_handle *handle)
1806 NTSTATUS status;
1807 struct spoolss_AddJob r;
1808 uint32_t needed;
1810 r.in.level = 0;
1811 r.in.handle = handle;
1812 r.in.offered = 0;
1813 r.out.needed = &needed;
1814 r.in.buffer = r.out.buffer = NULL;
1816 torture_comment(tctx, "Testing AddJob\n");
1818 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1819 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1821 r.in.level = 1;
1823 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1824 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1826 return true;
1830 static bool test_EnumJobs(struct torture_context *tctx,
1831 struct dcerpc_pipe *p,
1832 struct policy_handle *handle)
1834 NTSTATUS status;
1835 struct spoolss_EnumJobs r;
1836 uint32_t needed;
1837 uint32_t count;
1838 union spoolss_JobInfo *info;
1840 r.in.handle = handle;
1841 r.in.firstjob = 0;
1842 r.in.numjobs = 0xffffffff;
1843 r.in.level = 1;
1844 r.in.buffer = NULL;
1845 r.in.offered = 0;
1846 r.out.needed = &needed;
1847 r.out.count = &count;
1848 r.out.info = &info;
1850 torture_comment(tctx, "Testing EnumJobs\n");
1852 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1854 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1856 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1857 int j;
1858 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1859 data_blob_clear(&blob);
1860 r.in.buffer = &blob;
1861 r.in.offered = needed;
1863 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1865 torture_assert(tctx, info, "No jobs returned");
1867 for (j = 0; j < count; j++) {
1869 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1871 /* FIXME - gd */
1872 if (!torture_setting_bool(tctx, "samba3", false)) {
1873 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1874 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1878 } else {
1879 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1882 return true;
1885 static bool test_DoPrintTest(struct torture_context *tctx,
1886 struct dcerpc_pipe *p,
1887 struct policy_handle *handle)
1889 bool ret = true;
1890 NTSTATUS status;
1891 struct spoolss_StartDocPrinter s;
1892 struct spoolss_DocumentInfo1 info1;
1893 struct spoolss_StartPagePrinter sp;
1894 struct spoolss_WritePrinter w;
1895 struct spoolss_EndPagePrinter ep;
1896 struct spoolss_EndDocPrinter e;
1897 int i;
1898 uint32_t job_id;
1899 uint32_t num_written;
1901 torture_comment(tctx, "Testing StartDocPrinter\n");
1903 s.in.handle = handle;
1904 s.in.level = 1;
1905 s.in.info.info1 = &info1;
1906 s.out.job_id = &job_id;
1907 info1.document_name = "TorturePrintJob";
1908 info1.output_file = NULL;
1909 info1.datatype = "RAW";
1911 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1912 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1913 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1915 for (i=1; i < 4; i++) {
1916 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1918 sp.in.handle = handle;
1920 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1921 torture_assert_ntstatus_ok(tctx, status,
1922 "dcerpc_spoolss_StartPagePrinter failed");
1923 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1925 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1927 w.in.handle = handle;
1928 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1929 w.out.num_written = &num_written;
1931 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1932 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1933 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1935 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1937 ep.in.handle = handle;
1939 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1940 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1941 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1944 torture_comment(tctx, "Testing EndDocPrinter\n");
1946 e.in.handle = handle;
1948 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1949 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1950 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1952 ret &= test_AddJob(tctx, p, handle);
1953 ret &= test_EnumJobs(tctx, p, handle);
1955 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1957 return ret;
1960 static bool test_PausePrinter(struct torture_context *tctx,
1961 struct dcerpc_pipe *p,
1962 struct policy_handle *handle)
1964 NTSTATUS status;
1965 struct spoolss_SetPrinter r;
1966 struct spoolss_SetPrinterInfoCtr info_ctr;
1967 struct spoolss_DevmodeContainer devmode_ctr;
1968 struct sec_desc_buf secdesc_ctr;
1970 info_ctr.level = 0;
1971 info_ctr.info.info0 = NULL;
1973 ZERO_STRUCT(devmode_ctr);
1974 ZERO_STRUCT(secdesc_ctr);
1976 r.in.handle = handle;
1977 r.in.info_ctr = &info_ctr;
1978 r.in.devmode_ctr = &devmode_ctr;
1979 r.in.secdesc_ctr = &secdesc_ctr;
1980 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1982 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1984 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1986 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1988 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1990 return true;
1993 static bool test_ResumePrinter(struct torture_context *tctx,
1994 struct dcerpc_pipe *p,
1995 struct policy_handle *handle)
1997 NTSTATUS status;
1998 struct spoolss_SetPrinter r;
1999 struct spoolss_SetPrinterInfoCtr info_ctr;
2000 struct spoolss_DevmodeContainer devmode_ctr;
2001 struct sec_desc_buf secdesc_ctr;
2003 info_ctr.level = 0;
2004 info_ctr.info.info0 = NULL;
2006 ZERO_STRUCT(devmode_ctr);
2007 ZERO_STRUCT(secdesc_ctr);
2009 r.in.handle = handle;
2010 r.in.info_ctr = &info_ctr;
2011 r.in.devmode_ctr = &devmode_ctr;
2012 r.in.secdesc_ctr = &secdesc_ctr;
2013 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2015 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2017 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2019 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2021 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2023 return true;
2026 static bool test_GetPrinterData(struct torture_context *tctx,
2027 struct dcerpc_pipe *p,
2028 struct policy_handle *handle,
2029 const char *value_name)
2031 NTSTATUS status;
2032 struct spoolss_GetPrinterData r;
2033 uint32_t needed;
2034 enum winreg_Type type;
2035 union spoolss_PrinterData data;
2037 r.in.handle = handle;
2038 r.in.value_name = value_name;
2039 r.in.offered = 0;
2040 r.out.needed = &needed;
2041 r.out.type = &type;
2042 r.out.data = &data;
2044 torture_comment(tctx, "Testing GetPrinterData\n");
2046 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2047 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2049 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2050 r.in.offered = needed;
2052 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2053 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2055 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2058 return true;
2061 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2062 struct dcerpc_pipe *p,
2063 struct policy_handle *handle,
2064 const char *key_name,
2065 const char *value_name)
2067 NTSTATUS status;
2068 struct spoolss_GetPrinterDataEx r;
2069 enum winreg_Type type;
2070 uint32_t needed;
2072 r.in.handle = handle;
2073 r.in.key_name = key_name;
2074 r.in.value_name = value_name;
2075 r.in.offered = 0;
2076 r.out.type = &type;
2077 r.out.needed = &needed;
2078 r.out.buffer = NULL;
2080 torture_comment(tctx, "Testing GetPrinterDataEx\n");
2082 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2083 if (!NT_STATUS_IS_OK(status)) {
2084 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2085 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2086 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2088 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2091 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2092 r.in.offered = needed;
2093 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2095 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2096 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2098 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
2101 return true;
2104 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2105 struct policy_handle *handle)
2107 NTSTATUS status;
2108 struct spoolss_EnumPrinterData r;
2110 ZERO_STRUCT(r);
2111 r.in.handle = handle;
2112 r.in.enum_index = 0;
2114 do {
2115 uint32_t value_size = 0;
2116 uint32_t data_size = 0;
2117 enum winreg_Type type = 0;
2119 r.in.value_offered = value_size;
2120 r.out.value_needed = &value_size;
2121 r.in.data_offered = data_size;
2122 r.out.data_needed = &data_size;
2124 r.out.type = &type;
2125 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2127 torture_comment(tctx, "Testing EnumPrinterData\n");
2129 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2131 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2133 r.in.value_offered = value_size;
2134 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2135 r.in.data_offered = data_size;
2136 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2138 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2140 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2142 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name),
2143 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2145 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name),
2146 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2148 r.in.enum_index++;
2150 } while (W_ERROR_IS_OK(r.out.result));
2152 return true;
2155 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2156 struct dcerpc_pipe *p,
2157 struct policy_handle *handle)
2159 NTSTATUS status;
2160 struct spoolss_EnumPrinterDataEx r;
2161 struct spoolss_PrinterEnumValues *info;
2162 uint32_t needed;
2163 uint32_t count;
2165 r.in.handle = handle;
2166 r.in.key_name = "PrinterDriverData";
2167 r.in.offered = 0;
2168 r.out.needed = &needed;
2169 r.out.count = &count;
2170 r.out.info = &info;
2172 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
2174 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2175 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2177 r.in.offered = needed;
2179 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2181 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2183 return true;
2187 static bool test_DeletePrinterData(struct torture_context *tctx,
2188 struct dcerpc_pipe *p,
2189 struct policy_handle *handle,
2190 const char *value_name)
2192 NTSTATUS status;
2193 struct spoolss_DeletePrinterData r;
2195 r.in.handle = handle;
2196 r.in.value_name = value_name;
2198 torture_comment(tctx, "Testing DeletePrinterData\n");
2200 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2202 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2204 return true;
2207 static bool test_SetPrinterData(struct torture_context *tctx,
2208 struct dcerpc_pipe *p,
2209 struct policy_handle *handle)
2211 NTSTATUS status;
2212 struct spoolss_SetPrinterData r;
2213 const char *value_name = "spottyfoot";
2215 r.in.handle = handle;
2216 r.in.value_name = value_name;
2217 r.in.type = REG_SZ;
2218 r.in.data.string = "dog";
2220 torture_comment(tctx, "Testing SetPrinterData\n");
2222 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2224 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2226 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
2227 return false;
2230 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
2231 return false;
2234 return true;
2237 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2238 struct dcerpc_pipe *p,
2239 struct policy_handle *handle)
2241 NTSTATUS status;
2242 struct dcerpc_binding *b;
2243 struct dcerpc_pipe *p2;
2244 struct spoolss_ClosePrinter cp;
2246 /* only makes sense on SMB */
2247 if (p->conn->transport.transport != NCACN_NP) {
2248 return true;
2251 torture_comment(tctx, "testing close on secondary pipe\n");
2253 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2254 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2256 status = dcerpc_secondary_connection(p, &p2, b);
2257 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2259 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2260 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2262 cp.in.handle = handle;
2263 cp.out.handle = handle;
2265 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2266 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2267 "ERROR: Allowed close on secondary connection");
2269 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2270 "Unexpected fault code");
2272 talloc_free(p2);
2274 return true;
2277 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2278 struct dcerpc_pipe *p, const char *name)
2280 NTSTATUS status;
2281 struct spoolss_OpenPrinter op;
2282 struct spoolss_OpenPrinterEx opEx;
2283 struct policy_handle handle;
2284 bool ret = true;
2286 op.in.printername = name;
2287 op.in.datatype = NULL;
2288 op.in.devmode_ctr.devmode= NULL;
2289 op.in.access_mask = 0;
2290 op.out.handle = &handle;
2292 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2294 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2295 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2296 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2297 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2298 name, win_errstr(op.out.result));
2301 if (W_ERROR_IS_OK(op.out.result)) {
2302 ret &=test_ClosePrinter(tctx, p, &handle);
2305 opEx.in.printername = name;
2306 opEx.in.datatype = NULL;
2307 opEx.in.devmode_ctr.devmode = NULL;
2308 opEx.in.access_mask = 0;
2309 opEx.in.level = 1;
2310 opEx.in.userlevel.level1 = NULL;
2311 opEx.out.handle = &handle;
2313 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2315 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2316 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2317 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2318 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2319 name, win_errstr(opEx.out.result));
2322 if (W_ERROR_IS_OK(opEx.out.result)) {
2323 ret &=test_ClosePrinter(tctx, p, &handle);
2326 return ret;
2329 static bool test_OpenPrinter(struct torture_context *tctx,
2330 struct dcerpc_pipe *p,
2331 const char *name)
2333 NTSTATUS status;
2334 struct spoolss_OpenPrinter r;
2335 struct policy_handle handle;
2336 bool ret = true;
2338 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2339 r.in.datatype = NULL;
2340 r.in.devmode_ctr.devmode= NULL;
2341 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2342 r.out.handle = &handle;
2344 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2346 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2348 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2350 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2352 if (!test_GetPrinter(tctx, p, &handle)) {
2353 ret = false;
2356 if (!torture_setting_bool(tctx, "samba3", false)) {
2357 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2358 ret = false;
2362 if (!test_ClosePrinter(tctx, p, &handle)) {
2363 ret = false;
2366 return ret;
2369 static bool call_OpenPrinterEx(struct torture_context *tctx,
2370 struct dcerpc_pipe *p,
2371 const char *name, struct policy_handle *handle)
2373 struct spoolss_OpenPrinterEx r;
2374 struct spoolss_UserLevel1 userlevel1;
2375 NTSTATUS status;
2377 if (name && name[0]) {
2378 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2379 dcerpc_server_name(p), name);
2380 } else {
2381 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2382 dcerpc_server_name(p));
2385 r.in.datatype = NULL;
2386 r.in.devmode_ctr.devmode= NULL;
2387 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2388 r.in.level = 1;
2389 r.in.userlevel.level1 = &userlevel1;
2390 r.out.handle = handle;
2392 userlevel1.size = 1234;
2393 userlevel1.client = "hello";
2394 userlevel1.user = "spottyfoot!";
2395 userlevel1.build = 1;
2396 userlevel1.major = 2;
2397 userlevel1.minor = 3;
2398 userlevel1.processor = 4;
2400 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2402 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2404 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2406 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2408 return true;
2411 static bool test_OpenPrinterEx(struct torture_context *tctx,
2412 struct dcerpc_pipe *p,
2413 const char *name)
2415 struct policy_handle handle;
2416 bool ret = true;
2418 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2419 return false;
2422 if (!test_GetPrinter(tctx, p, &handle)) {
2423 ret = false;
2426 if (!test_EnumForms(tctx, p, &handle, false)) {
2427 ret = false;
2430 if (!test_AddForm(tctx, p, &handle, false)) {
2431 ret = false;
2434 if (!test_EnumPrinterData(tctx, p, &handle)) {
2435 ret = false;
2438 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
2439 ret = false;
2442 if (!test_printer_keys(tctx, p, &handle)) {
2443 ret = false;
2446 if (!test_PausePrinter(tctx, p, &handle)) {
2447 ret = false;
2450 if (!test_DoPrintTest(tctx, p, &handle)) {
2451 ret = false;
2454 if (!test_ResumePrinter(tctx, p, &handle)) {
2455 ret = false;
2458 if (!test_SetPrinterData(tctx, p, &handle)) {
2459 ret = false;
2462 if (!torture_setting_bool(tctx, "samba3", false)) {
2463 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2464 ret = false;
2468 if (!test_ClosePrinter(tctx, p, &handle)) {
2469 ret = false;
2472 return ret;
2475 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2477 struct spoolss_EnumPrinters r;
2478 NTSTATUS status;
2479 uint16_t levels[] = {1, 2, 4, 5};
2480 int i;
2481 bool ret = true;
2483 for (i=0;i<ARRAY_SIZE(levels);i++) {
2484 union spoolss_PrinterInfo *info;
2485 int j;
2486 uint32_t needed;
2487 uint32_t count;
2489 r.in.flags = PRINTER_ENUM_LOCAL;
2490 r.in.server = "";
2491 r.in.level = levels[i];
2492 r.in.buffer = NULL;
2493 r.in.offered = 0;
2494 r.out.needed = &needed;
2495 r.out.count = &count;
2496 r.out.info = &info;
2498 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2500 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2501 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2503 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2504 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2505 data_blob_clear(&blob);
2506 r.in.buffer = &blob;
2507 r.in.offered = needed;
2508 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2511 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2513 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2515 if (!info) {
2516 torture_comment(tctx, "No printers returned\n");
2517 return true;
2520 for (j=0;j<count;j++) {
2521 if (r.in.level == 1) {
2522 char *unc = talloc_strdup(tctx, info[j].info1.name);
2523 char *slash, *name;
2524 name = unc;
2525 if (unc[0] == '\\' && unc[1] == '\\') {
2526 unc +=2;
2528 slash = strchr(unc, '\\');
2529 if (slash) {
2530 slash++;
2531 name = slash;
2533 if (!test_OpenPrinter(tctx, p, name)) {
2534 ret = false;
2536 if (!test_OpenPrinterEx(tctx, p, name)) {
2537 ret = false;
2543 return ret;
2546 static bool test_GetPrinterDriver(struct torture_context *tctx,
2547 struct dcerpc_pipe *p,
2548 struct policy_handle *handle,
2549 const char *driver_name)
2551 struct spoolss_GetPrinterDriver r;
2552 uint32_t needed;
2554 r.in.handle = handle;
2555 r.in.architecture = "W32X86";
2556 r.in.level = 1;
2557 r.in.buffer = NULL;
2558 r.in.offered = 0;
2559 r.out.needed = &needed;
2561 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2563 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2564 "failed to call GetPrinterDriver");
2565 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2566 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2567 data_blob_clear(&blob);
2568 r.in.buffer = &blob;
2569 r.in.offered = needed;
2570 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2571 "failed to call GetPrinterDriver");
2574 torture_assert_werr_ok(tctx, r.out.result,
2575 "failed to call GetPrinterDriver");
2577 return true;
2580 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2581 struct dcerpc_pipe *p,
2582 struct policy_handle *handle,
2583 const char *driver_name)
2585 struct spoolss_GetPrinterDriver2 r;
2586 uint32_t needed;
2587 uint32_t server_major_version;
2588 uint32_t server_minor_version;
2590 r.in.handle = handle;
2591 r.in.architecture = "W32X86";
2592 r.in.level = 1;
2593 r.in.buffer = NULL;
2594 r.in.offered = 0;
2595 r.in.client_major_version = 0;
2596 r.in.client_minor_version = 0;
2597 r.out.needed = &needed;
2598 r.out.server_major_version = &server_major_version;
2599 r.out.server_minor_version = &server_minor_version;
2601 torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2603 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2604 "failed to call GetPrinterDriver2");
2605 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2606 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2607 data_blob_clear(&blob);
2608 r.in.buffer = &blob;
2609 r.in.offered = needed;
2610 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2611 "failed to call GetPrinterDriver2");
2614 torture_assert_werr_ok(tctx, r.out.result,
2615 "failed to call GetPrinterDriver2");
2617 return true;
2620 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2621 struct dcerpc_pipe *p)
2623 struct spoolss_EnumPrinterDrivers r;
2624 NTSTATUS status;
2625 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2626 int i;
2628 for (i=0;i<ARRAY_SIZE(levels);i++) {
2630 uint32_t needed;
2631 uint32_t count;
2632 union spoolss_DriverInfo *info;
2634 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2635 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2636 r.in.level = levels[i];
2637 r.in.buffer = NULL;
2638 r.in.offered = 0;
2639 r.out.needed = &needed;
2640 r.out.count = &count;
2641 r.out.info = &info;
2643 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2645 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2647 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2649 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2650 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2651 data_blob_clear(&blob);
2652 r.in.buffer = &blob;
2653 r.in.offered = needed;
2654 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2657 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2659 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2661 if (!info) {
2662 torture_comment(tctx, "No printer drivers returned\n");
2663 break;
2667 return true;
2670 static bool test_DeletePrinter(struct torture_context *tctx,
2671 struct dcerpc_pipe *p,
2672 struct policy_handle *handle)
2674 struct spoolss_DeletePrinter r;
2676 torture_comment(tctx, "Testing DeletePrinter\n");
2678 r.in.handle = handle;
2680 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2681 "failed to delete printer");
2682 torture_assert_werr_ok(tctx, r.out.result,
2683 "failed to delete printer");
2685 return true;
2688 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2689 struct dcerpc_pipe *p,
2690 uint32_t flags,
2691 uint32_t level,
2692 const char *name,
2693 bool *found)
2695 struct spoolss_EnumPrinters e;
2696 uint32_t count;
2697 union spoolss_PrinterInfo *info;
2698 uint32_t needed;
2699 int i;
2701 *found = false;
2703 e.in.flags = flags;
2704 e.in.server = NULL;
2705 e.in.level = level;
2706 e.in.buffer = NULL;
2707 e.in.offered = 0;
2708 e.out.count = &count;
2709 e.out.info = &info;
2710 e.out.needed = &needed;
2712 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2713 "failed to enum printers");
2715 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2716 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2717 data_blob_clear(&blob);
2718 e.in.buffer = &blob;
2719 e.in.offered = needed;
2721 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2722 "failed to enum printers");
2725 torture_assert_werr_ok(tctx, e.out.result,
2726 "failed to enum printers");
2728 for (i=0; i < count; i++) {
2730 const char *current = NULL;
2732 switch (level) {
2733 case 1:
2734 current = info[i].info1.name;
2735 break;
2738 if (strequal(current, name)) {
2739 *found = true;
2740 break;
2744 return true;
2747 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2748 struct dcerpc_pipe *p,
2749 const char *printername,
2750 bool ex)
2752 WERROR result;
2753 struct spoolss_AddPrinter r;
2754 struct spoolss_AddPrinterEx rex;
2755 struct spoolss_SetPrinterInfoCtr info_ctr;
2756 struct spoolss_SetPrinterInfo1 info1;
2757 struct spoolss_DevmodeContainer devmode_ctr;
2758 struct sec_desc_buf secdesc_ctr;
2759 struct spoolss_UserLevelCtr userlevel_ctr;
2760 struct policy_handle handle;
2761 bool found = false;
2763 ZERO_STRUCT(devmode_ctr);
2764 ZERO_STRUCT(secdesc_ctr);
2765 ZERO_STRUCT(userlevel_ctr);
2766 ZERO_STRUCT(info1);
2768 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
2770 /* try to add printer to wellknown printer list (level 1) */
2772 userlevel_ctr.level = 1;
2774 info_ctr.info.info1 = &info1;
2775 info_ctr.level = 1;
2777 rex.in.server = NULL;
2778 rex.in.info_ctr = &info_ctr;
2779 rex.in.devmode_ctr = &devmode_ctr;
2780 rex.in.secdesc_ctr = &secdesc_ctr;
2781 rex.in.userlevel_ctr = &userlevel_ctr;
2782 rex.out.handle = &handle;
2784 r.in.server = NULL;
2785 r.in.info_ctr = &info_ctr;
2786 r.in.devmode_ctr = &devmode_ctr;
2787 r.in.secdesc_ctr = &secdesc_ctr;
2788 r.out.handle = &handle;
2790 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2791 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2792 "failed to add printer");
2793 result = ex ? rex.out.result : r.out.result;
2794 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2795 "unexpected result code");
2797 info1.name = printername;
2798 info1.flags = PRINTER_ATTRIBUTE_SHARED;
2800 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2801 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2802 "failed to add printer");
2803 result = ex ? rex.out.result : r.out.result;
2804 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2805 "unexpected result code");
2807 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2808 better do a real check to see the printer is really there */
2810 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2811 PRINTER_ENUM_NETWORK, 1,
2812 printername,
2813 &found),
2814 "failed to enum printers");
2816 torture_assert(tctx, found, "failed to find newly added printer");
2818 info1.flags = 0;
2820 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2821 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2822 "failed to add printer");
2823 result = ex ? rex.out.result : r.out.result;
2824 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2825 "unexpected result code");
2827 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2828 better do a real check to see the printer has really been removed
2829 from the well known printer list */
2831 found = false;
2833 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2834 PRINTER_ENUM_NETWORK, 1,
2835 printername,
2836 &found),
2837 "failed to enum printers");
2838 #if 0
2839 torture_assert(tctx, !found, "printer still in well known printer list");
2840 #endif
2841 return true;
2844 static bool test_AddPrinter_normal(struct torture_context *tctx,
2845 struct dcerpc_pipe *p,
2846 struct policy_handle *handle_p,
2847 const char *printername,
2848 const char *drivername,
2849 const char *portname,
2850 bool ex)
2852 WERROR result;
2853 struct spoolss_AddPrinter r;
2854 struct spoolss_AddPrinterEx rex;
2855 struct spoolss_SetPrinterInfoCtr info_ctr;
2856 struct spoolss_SetPrinterInfo2 info2;
2857 struct spoolss_DevmodeContainer devmode_ctr;
2858 struct sec_desc_buf secdesc_ctr;
2859 struct spoolss_UserLevelCtr userlevel_ctr;
2860 struct policy_handle handle;
2861 bool found = false;
2863 ZERO_STRUCT(devmode_ctr);
2864 ZERO_STRUCT(secdesc_ctr);
2865 ZERO_STRUCT(userlevel_ctr);
2867 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
2869 userlevel_ctr.level = 1;
2871 rex.in.server = NULL;
2872 rex.in.info_ctr = &info_ctr;
2873 rex.in.devmode_ctr = &devmode_ctr;
2874 rex.in.secdesc_ctr = &secdesc_ctr;
2875 rex.in.userlevel_ctr = &userlevel_ctr;
2876 rex.out.handle = &handle;
2878 r.in.server = NULL;
2879 r.in.info_ctr = &info_ctr;
2880 r.in.devmode_ctr = &devmode_ctr;
2881 r.in.secdesc_ctr = &secdesc_ctr;
2882 r.out.handle = &handle;
2884 again:
2886 /* try to add printer to printer list (level 2) */
2888 ZERO_STRUCT(info2);
2890 info_ctr.info.info2 = &info2;
2891 info_ctr.level = 2;
2893 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2894 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2895 "failed to add printer");
2896 result = ex ? rex.out.result : r.out.result;
2897 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2898 "unexpected result code");
2900 info2.printername = printername;
2902 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2903 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2904 "failed to add printer");
2905 result = ex ? rex.out.result : r.out.result;
2907 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
2908 struct policy_handle printer_handle;
2910 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
2911 "failed to open printer handle");
2913 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
2914 "failed to delete printer");
2916 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
2917 "failed to close server handle");
2919 goto again;
2922 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
2923 "unexpected result code");
2925 info2.portname = portname;
2927 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2928 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2929 "failed to add printer");
2930 result = ex ? rex.out.result : r.out.result;
2931 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
2932 "unexpected result code");
2934 info2.drivername = drivername;
2936 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2937 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2938 "failed to add printer");
2939 result = ex ? rex.out.result : r.out.result;
2940 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
2941 "unexpected result code");
2943 info2.printprocessor = "winprint";
2945 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2946 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2947 "failed to add printer");
2948 result = ex ? rex.out.result : r.out.result;
2949 torture_assert_werr_ok(tctx, result,
2950 "failed to add printer");
2952 *handle_p = handle;
2954 /* we are paranoid, really check if the printer is there now */
2956 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2957 PRINTER_ENUM_LOCAL, 1,
2958 printername,
2959 &found),
2960 "failed to enum printers");
2961 torture_assert(tctx, found, "failed to find newly added printer");
2963 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2964 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2965 "failed to add printer");
2966 result = ex ? rex.out.result : r.out.result;
2967 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2968 "unexpected result code");
2970 return true;
2973 static bool test_AddPrinterEx(struct torture_context *tctx,
2974 struct dcerpc_pipe *p,
2975 struct policy_handle *handle_p,
2976 const char *printername,
2977 const char *drivername,
2978 const char *portname)
2980 bool ret = true;
2982 if (!torture_setting_bool(tctx, "samba3", false)) {
2983 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
2984 torture_comment(tctx, "failed to add printer to well known list\n");
2985 ret = false;
2989 if (!test_AddPrinter_normal(tctx, p, handle_p,
2990 printername, drivername, portname,
2991 true)) {
2992 torture_comment(tctx, "failed to add printer to printer list\n");
2993 ret = false;
2996 return ret;
2999 static bool test_AddPrinter(struct torture_context *tctx,
3000 struct dcerpc_pipe *p,
3001 struct policy_handle *handle_p,
3002 const char *printername,
3003 const char *drivername,
3004 const char *portname)
3006 bool ret = true;
3008 if (!torture_setting_bool(tctx, "samba3", false)) {
3009 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3010 torture_comment(tctx, "failed to add printer to well known list\n");
3011 ret = false;
3015 if (!test_AddPrinter_normal(tctx, p, handle_p,
3016 printername, drivername, portname,
3017 false)) {
3018 torture_comment(tctx, "failed to add printer to printer list\n");
3019 ret = false;
3022 return ret;
3025 static bool test_printer_info(struct torture_context *tctx,
3026 struct dcerpc_pipe *p,
3027 struct policy_handle *handle)
3029 bool ret = true;
3031 if (!test_PrinterInfo(tctx, p, handle)) {
3032 ret = false;
3035 if (!test_SetPrinter_errors(tctx, p, handle)) {
3036 ret = false;
3039 return ret;
3042 bool test_printer_keys(struct torture_context *tctx,
3043 struct dcerpc_pipe *p,
3044 struct policy_handle *handle)
3046 const char **key_array = NULL;
3047 int i;
3050 struct spoolss_EnumPrinterKey r;
3051 uint32_t needed;
3052 struct spoolss_StringArray2 key_buffer;
3054 r.in.handle = handle;
3055 r.in.key_name = "";
3056 r.in.offered = 0;
3057 r.out.key_buffer = &key_buffer;
3058 r.out.needed = &needed;
3060 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3061 "failed to call EnumPrinterKey");
3062 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3063 r.in.offered = needed;
3064 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3065 "failed to call EnumPrinterKey");
3067 torture_assert_werr_ok(tctx, r.out.result,
3068 "failed to call EnumPrinterKey");
3070 key_array = key_buffer.string;
3073 for (i=0; key_array[i]; i++) {
3074 struct spoolss_EnumPrinterDataEx r;
3075 uint32_t count;
3076 struct spoolss_PrinterEnumValues *info;
3077 uint32_t needed;
3079 r.in.handle = handle;
3080 r.in.key_name = key_array[i];
3081 r.in.offered = 0;
3082 r.out.count = &count;
3083 r.out.info = &info;
3084 r.out.needed = &needed;
3086 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3087 "failed to call EnumPrinterDataEx");
3088 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3089 r.in.offered = needed;
3090 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3091 "failed to call EnumPrinterDataEx");
3093 torture_assert_werr_ok(tctx, r.out.result,
3094 "failed to call EnumPrinterDataEx");
3097 return true;
3100 static bool test_printer(struct torture_context *tctx,
3101 struct dcerpc_pipe *p)
3103 bool ret = true;
3104 struct policy_handle handle[2];
3105 bool found = false;
3106 const char *drivername = "Microsoft XPS Document Writer";
3107 const char *portname = "LPT1:";
3109 /* test printer created via AddPrinter */
3111 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3112 return false;
3115 if (!test_printer_info(tctx, p, &handle[0])) {
3116 ret = false;
3119 if (!test_printer_keys(tctx, p, &handle[0])) {
3120 ret = false;
3123 if (!test_DeletePrinter(tctx, p, &handle[0])) {
3124 ret = false;
3127 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3128 TORTURE_PRINTER, &found)) {
3129 ret = false;
3132 torture_assert(tctx, !found, "deleted printer still there");
3134 /* test printer created via AddPrinterEx */
3136 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3137 return false;
3140 if (!test_printer_info(tctx, p, &handle[1])) {
3141 ret = false;
3144 if (!test_printer_keys(tctx, p, &handle[1])) {
3145 ret = false;
3148 if (!test_DeletePrinter(tctx, p, &handle[1])) {
3149 ret = false;
3152 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3153 TORTURE_PRINTER_EX, &found)) {
3154 ret = false;
3157 torture_assert(tctx, !found, "deleted printer still there");
3159 return ret;
3162 bool torture_rpc_spoolss(struct torture_context *torture)
3164 NTSTATUS status;
3165 struct dcerpc_pipe *p;
3166 bool ret = true;
3167 struct test_spoolss_context *ctx;
3169 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3170 if (!NT_STATUS_IS_OK(status)) {
3171 return false;
3174 ctx = talloc_zero(torture, struct test_spoolss_context);
3176 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3178 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
3179 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
3180 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
3181 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
3182 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
3183 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
3184 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
3185 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
3186 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
3187 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
3188 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
3189 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
3190 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
3191 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3192 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3193 ret &= test_EnumPorts(torture, p, ctx);
3194 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3195 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3196 ret &= test_EnumPrinterDrivers(torture, p, ctx);
3197 ret &= test_EnumMonitors(torture, p, ctx);
3198 ret &= test_EnumPrintProcessors(torture, p, ctx);
3199 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3200 ret &= test_EnumPrinters(torture, p, ctx);
3201 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3202 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3203 ret &= test_OpenPrinter_badname(torture, p, "");
3204 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3205 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3206 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3207 ret &= test_OpenPrinter_badname(torture, p,
3208 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3211 ret &= test_AddPort(torture, p);
3212 ret &= test_EnumPorts_old(torture, p);
3213 ret &= test_EnumPrinters_old(torture, p);
3214 ret &= test_EnumPrinterDrivers_old(torture, p);
3216 return ret;
3219 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3221 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3223 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3224 "printer", &ndr_table_spoolss);
3226 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3228 return suite;