s3-schannel: use NL_AUTH_SIGNATURE for schannel sign & seal (client & server).
[Samba/aatanasov.git] / source4 / torture / rpc / spoolss.c
blobddc14f33a2c347c6079e770354238150b25e3f76
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_spoolss_c.h"
29 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
30 #define TORTURE_PRINTER "torture_printer"
31 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
32 #define TORTURE_PRINTER_EX "torture_printer_ex"
34 struct test_spoolss_context {
35 /* print server handle */
36 struct policy_handle server_handle;
38 /* for EnumPorts */
39 uint32_t port_count[3];
40 union spoolss_PortInfo *ports[3];
42 /* for EnumPrinterDrivers */
43 uint32_t driver_count[7];
44 union spoolss_DriverInfo *drivers[7];
46 /* for EnumMonitors */
47 uint32_t monitor_count[3];
48 union spoolss_MonitorInfo *monitors[3];
50 /* for EnumPrintProcessors */
51 uint32_t print_processor_count[2];
52 union spoolss_PrintProcessorInfo *print_processors[2];
54 /* for EnumPrinters */
55 uint32_t printer_count[6];
56 union spoolss_PrinterInfo *printers[6];
59 #define COMPARE_STRING(tctx, c,r,e) \
60 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
62 /* not every compiler supports __typeof__() */
63 #if (__GNUC__ >= 3)
64 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
65 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
66 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
68 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
69 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
71 } while(0)
72 #else
73 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
74 #endif
76 #define COMPARE_UINT32(tctx, c, r, e) do {\
77 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
78 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
79 } while(0)
81 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
83 static bool test_OpenPrinter_server(struct torture_context *tctx,
84 struct dcerpc_pipe *p,
85 struct policy_handle *server_handle)
87 NTSTATUS status;
88 struct spoolss_OpenPrinter op;
90 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
91 op.in.datatype = NULL;
92 op.in.devmode_ctr.devmode= NULL;
93 op.in.access_mask = 0;
94 op.out.handle = server_handle;
96 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
98 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
99 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
100 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
102 return true;
105 static bool test_EnumPorts(struct torture_context *tctx,
106 struct dcerpc_pipe *p,
107 struct test_spoolss_context *ctx)
109 NTSTATUS status;
110 struct spoolss_EnumPorts r;
111 uint16_t levels[] = { 1, 2 };
112 int i, j;
114 for (i=0;i<ARRAY_SIZE(levels);i++) {
115 int level = levels[i];
116 DATA_BLOB blob;
117 uint32_t needed;
118 uint32_t count;
119 union spoolss_PortInfo *info;
121 r.in.servername = "";
122 r.in.level = level;
123 r.in.buffer = NULL;
124 r.in.offered = 0;
125 r.out.needed = &needed;
126 r.out.count = &count;
127 r.out.info = &info;
129 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
131 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
132 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
133 if (W_ERROR_IS_OK(r.out.result)) {
134 /* TODO: do some more checks here */
135 continue;
137 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
138 "EnumPorts unexpected return code");
140 blob = data_blob_talloc(ctx, NULL, needed);
141 data_blob_clear(&blob);
142 r.in.buffer = &blob;
143 r.in.offered = needed;
145 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
146 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
148 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
150 torture_assert(tctx, info, "EnumPorts returned no info");
152 ctx->port_count[level] = count;
153 ctx->ports[level] = info;
156 for (i=1;i<ARRAY_SIZE(levels);i++) {
157 int level = levels[i];
158 int old_level = levels[i-1];
159 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
160 "EnumPorts invalid value");
162 /* if the array sizes are not the same we would maybe segfault in the following code */
164 for (i=0;i<ARRAY_SIZE(levels);i++) {
165 int level = levels[i];
166 for (j=0;j<ctx->port_count[level];j++) {
167 union spoolss_PortInfo *cur = &ctx->ports[level][j];
168 union spoolss_PortInfo *ref = &ctx->ports[2][j];
169 switch (level) {
170 case 1:
171 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
172 break;
173 case 2:
174 /* level 2 is our reference, and it makes no sense to compare it to itself */
175 break;
180 return true;
183 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
184 struct dcerpc_pipe *p,
185 struct test_spoolss_context *ctx)
187 NTSTATUS status;
188 struct spoolss_GetPrintProcessorDirectory r;
189 struct {
190 uint16_t level;
191 const char *server;
192 } levels[] = {{
193 .level = 1,
194 .server = NULL
196 .level = 1,
197 .server = ""
199 .level = 78,
200 .server = ""
202 .level = 1,
203 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
205 .level = 1024,
206 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
209 int i;
210 uint32_t needed;
212 for (i=0;i<ARRAY_SIZE(levels);i++) {
213 int level = levels[i].level;
214 DATA_BLOB blob;
216 r.in.server = levels[i].server;
217 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
218 r.in.level = level;
219 r.in.buffer = NULL;
220 r.in.offered = 0;
221 r.out.needed = &needed;
223 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
225 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
226 torture_assert_ntstatus_ok(tctx, status,
227 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
228 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
229 "GetPrintProcessorDirectory unexpected return code");
231 blob = data_blob_talloc(ctx, NULL, needed);
232 data_blob_clear(&blob);
233 r.in.buffer = &blob;
234 r.in.offered = needed;
236 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
237 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
239 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
242 return true;
246 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
247 struct dcerpc_pipe *p,
248 struct test_spoolss_context *ctx)
250 NTSTATUS status;
251 struct spoolss_GetPrinterDriverDirectory r;
252 struct {
253 uint16_t level;
254 const char *server;
255 } levels[] = {{
256 .level = 1,
257 .server = NULL
259 .level = 1,
260 .server = ""
262 .level = 78,
263 .server = ""
265 .level = 1,
266 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
268 .level = 1024,
269 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
272 int i;
273 uint32_t needed;
275 for (i=0;i<ARRAY_SIZE(levels);i++) {
276 int level = levels[i].level;
277 DATA_BLOB blob;
279 r.in.server = levels[i].server;
280 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
281 r.in.level = level;
282 r.in.buffer = NULL;
283 r.in.offered = 0;
284 r.out.needed = &needed;
286 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
288 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
289 torture_assert_ntstatus_ok(tctx, status,
290 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
291 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
292 "GetPrinterDriverDirectory unexpected return code");
294 blob = data_blob_talloc(ctx, NULL, needed);
295 data_blob_clear(&blob);
296 r.in.buffer = &blob;
297 r.in.offered = needed;
299 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
300 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
302 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
305 return true;
308 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
309 struct dcerpc_pipe *p,
310 struct test_spoolss_context *ctx)
312 NTSTATUS status;
313 struct spoolss_EnumPrinterDrivers r;
314 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
315 int i, j, a;
316 const char *architectures[] = {
317 SPOOLSS_ARCHITECTURE_NT_X86,
318 SPOOLSS_ARCHITECTURE_ALL
321 for (i=0;i<ARRAY_SIZE(levels);i++) {
322 for (a=0;a<ARRAY_SIZE(architectures);a++) {
323 int level = levels[i];
324 DATA_BLOB blob;
325 uint32_t needed;
326 uint32_t count;
327 union spoolss_DriverInfo *info;
329 /* FIXME: gd, come back and fix "" as server, and handle
330 * priority of returned error codes in torture test and samba 3
331 * server */
333 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
334 r.in.environment = architectures[a];
335 r.in.level = level;
336 r.in.buffer = NULL;
337 r.in.offered = 0;
338 r.out.needed = &needed;
339 r.out.count = &count;
340 r.out.info = &info;
342 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
344 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
345 torture_assert_ntstatus_ok(tctx, status,
346 "dcerpc_spoolss_EnumPrinterDrivers failed");
347 if (W_ERROR_IS_OK(r.out.result)) {
348 /* TODO: do some more checks here */
349 continue;
351 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
352 blob = data_blob_talloc(ctx, NULL, needed);
353 data_blob_clear(&blob);
354 r.in.buffer = &blob;
355 r.in.offered = needed;
357 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
358 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
361 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
363 /* don't do cross-architecture comparison */
364 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
365 continue;
368 ctx->driver_count[level] = count;
369 ctx->drivers[level] = info;
373 for (i=1;i<ARRAY_SIZE(levels);i++) {
374 int level = levels[i];
375 int old_level = levels[i-1];
377 /* don't do cross-architecture comparison */
378 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
379 continue;
382 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
383 "EnumPrinterDrivers invalid value");
386 for (i=0;i<ARRAY_SIZE(levels);i++) {
387 int level = levels[i];
389 /* don't do cross-architecture comparison */
390 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
391 continue;
394 for (j=0;j<ctx->driver_count[level];j++) {
395 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
396 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
397 switch (level) {
398 case 1:
399 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
400 break;
401 case 2:
402 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
403 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
404 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
405 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
406 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
407 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
408 break;
409 case 3:
410 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
411 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
412 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
413 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
414 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
415 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
416 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
417 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
418 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
419 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
420 break;
421 case 4:
422 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
423 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
424 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
425 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
426 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
427 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
428 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
429 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
430 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
431 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
432 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
433 break;
434 case 5:
435 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
436 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
437 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
438 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
439 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
440 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
441 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
442 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
443 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
444 break;
445 case 6:
446 /* level 6 is our reference, and it makes no sense to compare it to itself */
447 break;
452 return true;
455 static bool test_EnumMonitors(struct torture_context *tctx,
456 struct dcerpc_pipe *p,
457 struct test_spoolss_context *ctx)
459 NTSTATUS status;
460 struct spoolss_EnumMonitors r;
461 uint16_t levels[] = { 1, 2 };
462 int i, j;
464 for (i=0;i<ARRAY_SIZE(levels);i++) {
465 int level = levels[i];
466 DATA_BLOB blob;
467 uint32_t needed;
468 uint32_t count;
469 union spoolss_MonitorInfo *info;
471 r.in.servername = "";
472 r.in.level = level;
473 r.in.buffer = NULL;
474 r.in.offered = 0;
475 r.out.needed = &needed;
476 r.out.count = &count;
477 r.out.info = &info;
479 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
481 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
482 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
483 if (W_ERROR_IS_OK(r.out.result)) {
484 /* TODO: do some more checks here */
485 continue;
487 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
488 "EnumMonitors failed");
490 blob = data_blob_talloc(ctx, NULL, needed);
491 data_blob_clear(&blob);
492 r.in.buffer = &blob;
493 r.in.offered = needed;
495 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
496 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
498 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
500 ctx->monitor_count[level] = count;
501 ctx->monitors[level] = info;
504 for (i=1;i<ARRAY_SIZE(levels);i++) {
505 int level = levels[i];
506 int old_level = levels[i-1];
507 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
508 "EnumMonitors invalid value");
511 for (i=0;i<ARRAY_SIZE(levels);i++) {
512 int level = levels[i];
513 for (j=0;j<ctx->monitor_count[level];j++) {
514 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
515 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
516 switch (level) {
517 case 1:
518 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
519 break;
520 case 2:
521 /* level 2 is our reference, and it makes no sense to compare it to itself */
522 break;
527 return true;
530 static bool test_EnumPrintProcessors(struct torture_context *tctx,
531 struct dcerpc_pipe *p,
532 struct test_spoolss_context *ctx)
534 NTSTATUS status;
535 struct spoolss_EnumPrintProcessors r;
536 uint16_t levels[] = { 1 };
537 int i, j;
539 for (i=0;i<ARRAY_SIZE(levels);i++) {
540 int level = levels[i];
541 DATA_BLOB blob;
542 uint32_t needed;
543 uint32_t count;
544 union spoolss_PrintProcessorInfo *info;
546 r.in.servername = "";
547 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
548 r.in.level = level;
549 r.in.buffer = NULL;
550 r.in.offered = 0;
551 r.out.needed = &needed;
552 r.out.count = &count;
553 r.out.info = &info;
555 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
557 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
558 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
559 if (W_ERROR_IS_OK(r.out.result)) {
560 /* TODO: do some more checks here */
561 continue;
563 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
564 "EnumPrintProcessors unexpected return code");
566 blob = data_blob_talloc(ctx, NULL, needed);
567 data_blob_clear(&blob);
568 r.in.buffer = &blob;
569 r.in.offered = needed;
571 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
572 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
574 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
576 ctx->print_processor_count[level] = count;
577 ctx->print_processors[level] = info;
580 for (i=1;i<ARRAY_SIZE(levels);i++) {
581 int level = levels[i];
582 int old_level = levels[i-1];
583 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
584 "EnumPrintProcessors failed");
587 for (i=0;i<ARRAY_SIZE(levels);i++) {
588 int level = levels[i];
589 for (j=0;j<ctx->print_processor_count[level];j++) {
590 #if 0
591 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
592 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
593 #endif
594 switch (level) {
595 case 1:
596 /* level 1 is our reference, and it makes no sense to compare it to itself */
597 break;
602 return true;
605 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
606 struct dcerpc_pipe *p,
607 struct test_spoolss_context *ctx)
609 NTSTATUS status;
610 struct spoolss_EnumPrintProcDataTypes r;
611 uint16_t levels[] = { 1 };
612 int i;
614 for (i=0;i<ARRAY_SIZE(levels);i++) {
615 int level = levels[i];
616 DATA_BLOB blob;
617 uint32_t needed;
618 uint32_t count;
619 union spoolss_PrintProcDataTypesInfo *info;
621 r.in.servername = "";
622 r.in.print_processor_name = "winprint";
623 r.in.level = level;
624 r.in.buffer = NULL;
625 r.in.offered = 0;
626 r.out.needed = &needed;
627 r.out.count = &count;
628 r.out.info = &info;
630 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
632 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
633 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
634 if (W_ERROR_IS_OK(r.out.result)) {
635 /* TODO: do some more checks here */
636 continue;
638 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
639 "EnumPrintProcDataTypes unexpected return code");
641 blob = data_blob_talloc(ctx, NULL, needed);
642 data_blob_clear(&blob);
643 r.in.buffer = &blob;
644 r.in.offered = needed;
646 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
647 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
649 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
652 return true;
656 static bool test_EnumPrinters(struct torture_context *tctx,
657 struct dcerpc_pipe *p,
658 struct test_spoolss_context *ctx)
660 struct spoolss_EnumPrinters r;
661 NTSTATUS status;
662 uint16_t levels[] = { 0, 1, 2, 4, 5 };
663 int i, j;
665 for (i=0;i<ARRAY_SIZE(levels);i++) {
666 int level = levels[i];
667 DATA_BLOB blob;
668 uint32_t needed;
669 uint32_t count;
670 union spoolss_PrinterInfo *info;
672 r.in.flags = PRINTER_ENUM_LOCAL;
673 r.in.server = "";
674 r.in.level = level;
675 r.in.buffer = NULL;
676 r.in.offered = 0;
677 r.out.needed = &needed;
678 r.out.count = &count;
679 r.out.info = &info;
681 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
683 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
684 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
685 if (W_ERROR_IS_OK(r.out.result)) {
686 /* TODO: do some more checks here */
687 continue;
689 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
690 "EnumPrinters unexpected return code");
692 blob = data_blob_talloc(ctx, NULL, needed);
693 data_blob_clear(&blob);
694 r.in.buffer = &blob;
695 r.in.offered = needed;
697 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
698 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
700 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
702 ctx->printer_count[level] = count;
703 ctx->printers[level] = info;
706 for (i=1;i<ARRAY_SIZE(levels);i++) {
707 int level = levels[i];
708 int old_level = levels[i-1];
709 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
710 "EnumPrinters invalid value");
713 for (i=0;i<ARRAY_SIZE(levels);i++) {
714 int level = levels[i];
715 for (j=0;j<ctx->printer_count[level];j++) {
716 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
717 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
718 switch (level) {
719 case 0:
720 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
721 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
723 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
725 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
727 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
737 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
739 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
740 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
742 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
743 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
744 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
745 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
746 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
747 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
748 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
749 break;
750 case 1:
751 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
752 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
753 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
754 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
755 break;
756 case 2:
757 /* level 2 is our reference, and it makes no sense to compare it to itself */
758 break;
759 case 4:
760 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
761 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
762 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
763 break;
764 case 5:
765 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
766 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
767 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
768 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
769 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
770 break;
775 /* TODO:
776 * - verify that the port of a printer was in the list returned by EnumPorts
779 return true;
782 static bool test_GetPrinter(struct torture_context *tctx,
783 struct dcerpc_pipe *p,
784 struct policy_handle *handle)
786 NTSTATUS status;
787 struct spoolss_GetPrinter r;
788 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
789 int i;
790 uint32_t needed;
792 for (i=0;i<ARRAY_SIZE(levels);i++) {
793 r.in.handle = handle;
794 r.in.level = levels[i];
795 r.in.buffer = NULL;
796 r.in.offered = 0;
797 r.out.needed = &needed;
799 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
801 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
802 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
804 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
805 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
806 data_blob_clear(&blob);
807 r.in.buffer = &blob;
808 r.in.offered = needed;
809 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
812 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
814 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
817 return true;
820 static bool test_SetPrinter_errors(struct torture_context *tctx,
821 struct dcerpc_pipe *p,
822 struct policy_handle *handle)
824 struct spoolss_SetPrinter r;
825 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
826 int i;
828 struct spoolss_SetPrinterInfoCtr info_ctr;
829 struct spoolss_DevmodeContainer devmode_ctr;
830 struct sec_desc_buf secdesc_ctr;
832 info_ctr.level = 0;
833 info_ctr.info.info0 = NULL;
835 ZERO_STRUCT(devmode_ctr);
836 ZERO_STRUCT(secdesc_ctr);
838 r.in.handle = handle;
839 r.in.info_ctr = &info_ctr;
840 r.in.devmode_ctr = &devmode_ctr;
841 r.in.secdesc_ctr = &secdesc_ctr;
842 r.in.command = 0;
844 torture_comment(tctx, "Testing SetPrinter all zero\n");
846 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
847 "failed to call SetPrinter");
848 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
849 "failed to call SetPrinter");
851 again:
852 for (i=0; i < ARRAY_SIZE(levels); i++) {
854 struct spoolss_SetPrinterInfo0 info0;
855 struct spoolss_SetPrinterInfo1 info1;
856 struct spoolss_SetPrinterInfo2 info2;
857 struct spoolss_SetPrinterInfo3 info3;
858 struct spoolss_SetPrinterInfo4 info4;
859 struct spoolss_SetPrinterInfo5 info5;
860 struct spoolss_SetPrinterInfo6 info6;
861 struct spoolss_SetPrinterInfo7 info7;
862 struct spoolss_DeviceModeInfo info8;
863 struct spoolss_DeviceModeInfo info9;
866 info_ctr.level = levels[i];
867 switch (levels[i]) {
868 case 0:
869 ZERO_STRUCT(info0);
870 info_ctr.info.info0 = &info0;
871 break;
872 case 1:
873 ZERO_STRUCT(info1);
874 info_ctr.info.info1 = &info1;
875 break;
876 case 2:
877 ZERO_STRUCT(info2);
878 info_ctr.info.info2 = &info2;
879 break;
880 case 3:
881 ZERO_STRUCT(info3);
882 info_ctr.info.info3 = &info3;
883 break;
884 case 4:
885 ZERO_STRUCT(info4);
886 info_ctr.info.info4 = &info4;
887 break;
888 case 5:
889 ZERO_STRUCT(info5);
890 info_ctr.info.info5 = &info5;
891 break;
892 case 6:
893 ZERO_STRUCT(info6);
894 info_ctr.info.info6 = &info6;
895 break;
896 case 7:
897 ZERO_STRUCT(info7);
898 info_ctr.info.info7 = &info7;
899 break;
900 case 8:
901 ZERO_STRUCT(info8);
902 info_ctr.info.info8 = &info8;
903 break;
904 case 9:
905 ZERO_STRUCT(info9);
906 info_ctr.info.info9 = &info9;
907 break;
910 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
911 info_ctr.level, r.in.command);
913 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
914 "failed to call SetPrinter");
916 switch (r.in.command) {
917 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
918 /* is ignored for all levels other then 0 */
919 if (info_ctr.level > 0) {
920 /* ignored then */
921 break;
923 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
924 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
925 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
926 if (info_ctr.level > 0) {
927 /* is invalid for all levels other then 0 */
928 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
929 "unexpected error code returned");
930 continue;
931 } else {
932 torture_assert_werr_ok(tctx, r.out.result,
933 "failed to call SetPrinter with non 0 command");
934 continue;
936 break;
938 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
939 /* FIXME: gd needs further investigation */
940 default:
941 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
942 "unexpected error code returned");
943 continue;
946 switch (info_ctr.level) {
947 case 1:
948 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
949 "unexpected error code returned");
950 break;
951 case 2:
952 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
953 "unexpected error code returned");
954 break;
955 case 3:
956 case 4:
957 case 5:
958 case 7:
959 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
960 "unexpected error code returned");
961 break;
962 case 9:
963 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
964 "unexpected error code returned");
965 break;
966 default:
967 torture_assert_werr_ok(tctx, r.out.result,
968 "failed to call SetPrinter");
969 break;
973 if (r.in.command < 5) {
974 r.in.command++;
975 goto again;
978 return true;
981 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
983 if ((r->level == 2) && (r->info.info2)) {
984 r->info.info2->secdesc = NULL;
985 r->info.info2->devmode = NULL;
989 static bool test_PrinterInfo(struct torture_context *tctx,
990 struct dcerpc_pipe *p,
991 struct policy_handle *handle)
993 NTSTATUS status;
994 struct spoolss_SetPrinter s;
995 struct spoolss_GetPrinter q;
996 struct spoolss_GetPrinter q0;
997 struct spoolss_SetPrinterInfoCtr info_ctr;
998 union spoolss_PrinterInfo info;
999 struct spoolss_DevmodeContainer devmode_ctr;
1000 struct sec_desc_buf secdesc_ctr;
1001 uint32_t needed;
1002 bool ret = true;
1003 int i;
1005 uint32_t status_list[] = {
1006 /* these do not stick
1007 PRINTER_STATUS_PAUSED,
1008 PRINTER_STATUS_ERROR,
1009 PRINTER_STATUS_PENDING_DELETION, */
1010 PRINTER_STATUS_PAPER_JAM,
1011 PRINTER_STATUS_PAPER_OUT,
1012 PRINTER_STATUS_MANUAL_FEED,
1013 PRINTER_STATUS_PAPER_PROBLEM,
1014 PRINTER_STATUS_OFFLINE,
1015 PRINTER_STATUS_IO_ACTIVE,
1016 PRINTER_STATUS_BUSY,
1017 PRINTER_STATUS_PRINTING,
1018 PRINTER_STATUS_OUTPUT_BIN_FULL,
1019 PRINTER_STATUS_NOT_AVAILABLE,
1020 PRINTER_STATUS_WAITING,
1021 PRINTER_STATUS_PROCESSING,
1022 PRINTER_STATUS_INITIALIZING,
1023 PRINTER_STATUS_WARMING_UP,
1024 PRINTER_STATUS_TONER_LOW,
1025 PRINTER_STATUS_NO_TONER,
1026 PRINTER_STATUS_PAGE_PUNT,
1027 PRINTER_STATUS_USER_INTERVENTION,
1028 PRINTER_STATUS_OUT_OF_MEMORY,
1029 PRINTER_STATUS_DOOR_OPEN,
1030 PRINTER_STATUS_SERVER_UNKNOWN,
1031 PRINTER_STATUS_POWER_SAVE,
1032 /* these do not stick
1033 0x02000000,
1034 0x04000000,
1035 0x08000000,
1036 0x10000000,
1037 0x20000000,
1038 0x40000000,
1039 0x80000000 */
1041 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1042 uint32_t attribute_list[] = {
1043 PRINTER_ATTRIBUTE_QUEUED,
1044 /* fails with WERR_INVALID_DATATYPE:
1045 PRINTER_ATTRIBUTE_DIRECT, */
1046 /* does not stick
1047 PRINTER_ATTRIBUTE_DEFAULT, */
1048 PRINTER_ATTRIBUTE_SHARED,
1049 /* does not stick
1050 PRINTER_ATTRIBUTE_NETWORK, */
1051 PRINTER_ATTRIBUTE_HIDDEN,
1052 PRINTER_ATTRIBUTE_LOCAL,
1053 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1054 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1055 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1056 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1057 /* does not stick
1058 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1059 /* fails with WERR_INVALID_DATATYPE:
1060 PRINTER_ATTRIBUTE_RAW_ONLY, */
1061 /* these do not stick
1062 PRINTER_ATTRIBUTE_PUBLISHED,
1063 PRINTER_ATTRIBUTE_FAX,
1064 PRINTER_ATTRIBUTE_TS,
1065 0x00010000,
1066 0x00020000,
1067 0x00040000,
1068 0x00080000,
1069 0x00100000,
1070 0x00200000,
1071 0x00400000,
1072 0x00800000,
1073 0x01000000,
1074 0x02000000,
1075 0x04000000,
1076 0x08000000,
1077 0x10000000,
1078 0x20000000,
1079 0x40000000,
1080 0x80000000 */
1083 ZERO_STRUCT(devmode_ctr);
1084 ZERO_STRUCT(secdesc_ctr);
1086 s.in.handle = handle;
1087 s.in.command = 0;
1088 s.in.info_ctr = &info_ctr;
1089 s.in.devmode_ctr = &devmode_ctr;
1090 s.in.secdesc_ctr = &secdesc_ctr;
1092 q.in.handle = handle;
1093 q.out.info = &info;
1094 q0 = q;
1096 #define TESTGETCALL(call, r) \
1097 r.in.buffer = NULL; \
1098 r.in.offered = 0;\
1099 r.out.needed = &needed; \
1100 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1101 if (!NT_STATUS_IS_OK(status)) { \
1102 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1103 r.in.level, nt_errstr(status), __location__); \
1104 ret = false; \
1105 break; \
1107 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1108 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1109 data_blob_clear(&blob); \
1110 r.in.buffer = &blob; \
1111 r.in.offered = needed; \
1113 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1114 if (!NT_STATUS_IS_OK(status)) { \
1115 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1116 r.in.level, nt_errstr(status), __location__); \
1117 ret = false; \
1118 break; \
1120 if (!W_ERROR_IS_OK(r.out.result)) { \
1121 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1122 r.in.level, win_errstr(r.out.result), __location__); \
1123 ret = false; \
1124 break; \
1128 #define TESTSETCALL_EXP(call, r, err) \
1129 clear_info2(&info_ctr);\
1130 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1131 if (!NT_STATUS_IS_OK(status)) { \
1132 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1133 r.in.info_ctr->level, nt_errstr(status), __location__); \
1134 ret = false; \
1135 break; \
1137 if (!W_ERROR_IS_OK(err)) { \
1138 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1139 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1140 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1141 ret = false; \
1143 break; \
1145 if (!W_ERROR_IS_OK(r.out.result)) { \
1146 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1147 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1148 ret = false; \
1149 break; \
1152 #define TESTSETCALL(call, r) \
1153 TESTSETCALL_EXP(call, r, WERR_OK)
1155 #define STRING_EQUAL(s1, s2, field) \
1156 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1157 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1158 #field, s2, __location__); \
1159 ret = false; \
1160 break; \
1163 #define MEM_EQUAL(s1, s2, length, field) \
1164 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1165 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1166 #field, (const char *)s2, __location__); \
1167 ret = false; \
1168 break; \
1171 #define INT_EQUAL(i1, i2, field) \
1172 if (i1 != i2) { \
1173 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1174 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1175 ret = false; \
1176 break; \
1179 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1180 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1181 q.in.level = lvl1; \
1182 TESTGETCALL(GetPrinter, q) \
1183 info_ctr.level = lvl1; \
1184 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1185 info_ctr.info.info ## lvl1->field1 = value;\
1186 TESTSETCALL_EXP(SetPrinter, s, err) \
1187 info_ctr.info.info ## lvl1->field1 = ""; \
1188 TESTGETCALL(GetPrinter, q) \
1189 info_ctr.info.info ## lvl1->field1 = value; \
1190 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1191 q.in.level = lvl2; \
1192 TESTGETCALL(GetPrinter, q) \
1193 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1194 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1195 } while (0)
1197 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1198 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1199 } while (0);
1201 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1202 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1203 q.in.level = lvl1; \
1204 TESTGETCALL(GetPrinter, q) \
1205 info_ctr.level = lvl1; \
1206 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1207 info_ctr.info.info ## lvl1->field1 = value; \
1208 TESTSETCALL(SetPrinter, s) \
1209 info_ctr.info.info ## lvl1->field1 = 0; \
1210 TESTGETCALL(GetPrinter, q) \
1211 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1212 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1213 q.in.level = lvl2; \
1214 TESTGETCALL(GetPrinter, q) \
1215 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1216 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1217 } while (0)
1219 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1220 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1221 } while (0)
1223 q0.in.level = 0;
1224 do { TESTGETCALL(GetPrinter, q0) } while (0);
1226 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1227 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1229 /* level 0 printername does not stick */
1230 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1231 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1232 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1233 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1234 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1235 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1236 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1237 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1238 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1239 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1240 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1241 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1242 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1243 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1244 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1246 /* servername can be set but does not stick
1247 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1248 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1249 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1252 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1253 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1254 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1255 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1256 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1258 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1259 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1260 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1261 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1262 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1263 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1264 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1265 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1266 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1267 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1269 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1270 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1271 attribute_list[i],
1272 (attribute_list[i] | default_attribute)
1273 ); */
1274 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1275 attribute_list[i],
1276 (attribute_list[i] | default_attribute)
1278 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1279 attribute_list[i],
1280 (attribute_list[i] | default_attribute)
1282 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1283 attribute_list[i],
1284 (attribute_list[i] | default_attribute)
1286 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1287 attribute_list[i],
1288 (attribute_list[i] | default_attribute)
1289 ); */
1290 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1291 attribute_list[i],
1292 (attribute_list[i] | default_attribute)
1294 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1295 attribute_list[i],
1296 (attribute_list[i] | default_attribute)
1298 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1299 attribute_list[i],
1300 (attribute_list[i] | default_attribute)
1302 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1303 attribute_list[i],
1304 (attribute_list[i] | default_attribute)
1305 ); */
1306 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1307 attribute_list[i],
1308 (attribute_list[i] | default_attribute)
1310 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1311 attribute_list[i],
1312 (attribute_list[i] | default_attribute)
1314 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1315 attribute_list[i],
1316 (attribute_list[i] | default_attribute)
1320 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1321 /* level 2 sets do not stick
1322 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1323 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1324 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1325 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1326 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1327 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1330 /* priorities need to be between 0 and 99
1331 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1332 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1333 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1334 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1335 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1336 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1337 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1338 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1339 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1341 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1342 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1344 /* does not stick
1345 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1346 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1348 /* does not stick
1349 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1350 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1352 /* FIXME: gd also test devmode and secdesc behavior */
1355 /* verify composition of level 1 description field */
1356 const char *description;
1357 const char *tmp;
1359 q0.in.level = 1;
1360 do { TESTGETCALL(GetPrinter, q0) } while (0);
1362 description = talloc_strdup(tctx, q0.out.info->info1.description);
1364 q0.in.level = 2;
1365 do { TESTGETCALL(GetPrinter, q0) } while (0);
1367 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1368 q0.out.info->info2.printername,
1369 q0.out.info->info2.drivername,
1370 q0.out.info->info2.location);
1372 do { STRING_EQUAL(description, tmp, "description")} while (0);
1375 return ret;
1379 static bool test_ClosePrinter(struct torture_context *tctx,
1380 struct dcerpc_pipe *p,
1381 struct policy_handle *handle)
1383 NTSTATUS status;
1384 struct spoolss_ClosePrinter r;
1386 r.in.handle = handle;
1387 r.out.handle = handle;
1389 torture_comment(tctx, "Testing ClosePrinter\n");
1391 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1392 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1394 return true;
1397 static bool test_GetForm(struct torture_context *tctx,
1398 struct dcerpc_pipe *p,
1399 struct policy_handle *handle,
1400 const char *form_name,
1401 uint32_t level)
1403 NTSTATUS status;
1404 struct spoolss_GetForm r;
1405 uint32_t needed;
1407 r.in.handle = handle;
1408 r.in.form_name = form_name;
1409 r.in.level = level;
1410 r.in.buffer = NULL;
1411 r.in.offered = 0;
1412 r.out.needed = &needed;
1414 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1416 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1417 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1419 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1420 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1421 data_blob_clear(&blob);
1422 r.in.buffer = &blob;
1423 r.in.offered = needed;
1424 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1425 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1427 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1429 torture_assert(tctx, r.out.info, "No form info returned");
1432 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1434 return true;
1437 static bool test_EnumForms(struct torture_context *tctx,
1438 struct dcerpc_pipe *p,
1439 struct policy_handle *handle, bool print_server)
1441 NTSTATUS status;
1442 struct spoolss_EnumForms r;
1443 bool ret = true;
1444 uint32_t needed;
1445 uint32_t count;
1446 uint32_t levels[] = { 1, 2 };
1447 int i;
1449 for (i=0; i<ARRAY_SIZE(levels); i++) {
1451 union spoolss_FormInfo *info;
1453 r.in.handle = handle;
1454 r.in.level = levels[i];
1455 r.in.buffer = NULL;
1456 r.in.offered = 0;
1457 r.out.needed = &needed;
1458 r.out.count = &count;
1459 r.out.info = &info;
1461 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1463 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1464 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1466 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1467 break;
1470 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1471 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1473 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1474 int j;
1475 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1476 data_blob_clear(&blob);
1477 r.in.buffer = &blob;
1478 r.in.offered = needed;
1480 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1482 torture_assert(tctx, info, "No forms returned");
1484 for (j = 0; j < count; j++) {
1485 if (!print_server)
1486 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1490 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1492 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1495 return true;
1498 static bool test_DeleteForm(struct torture_context *tctx,
1499 struct dcerpc_pipe *p,
1500 struct policy_handle *handle,
1501 const char *form_name)
1503 NTSTATUS status;
1504 struct spoolss_DeleteForm r;
1506 r.in.handle = handle;
1507 r.in.form_name = form_name;
1509 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1511 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1513 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1515 return true;
1518 static bool test_AddForm(struct torture_context *tctx,
1519 struct dcerpc_pipe *p,
1520 struct policy_handle *handle, bool print_server)
1522 struct spoolss_AddForm r;
1523 struct spoolss_AddFormInfo1 addform;
1524 const char *form_name = "testform3";
1525 NTSTATUS status;
1526 bool ret = true;
1528 r.in.handle = handle;
1529 r.in.level = 1;
1530 r.in.info.info1 = &addform;
1531 addform.flags = SPOOLSS_FORM_USER;
1532 addform.form_name = form_name;
1533 addform.size.width = 50;
1534 addform.size.height = 25;
1535 addform.area.left = 5;
1536 addform.area.top = 10;
1537 addform.area.right = 45;
1538 addform.area.bottom = 15;
1540 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1542 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1544 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1546 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1549 struct spoolss_SetForm sf;
1550 struct spoolss_AddFormInfo1 setform;
1552 sf.in.handle = handle;
1553 sf.in.form_name = form_name;
1554 sf.in.level = 1;
1555 sf.in.info.info1= &setform;
1556 setform.flags = addform.flags;
1557 setform.form_name = addform.form_name;
1558 setform.size = addform.size;
1559 setform.area = addform.area;
1561 setform.size.width = 1234;
1563 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1565 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1567 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1570 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1573 struct spoolss_EnumForms e;
1574 union spoolss_FormInfo *info;
1575 uint32_t needed;
1576 uint32_t count;
1577 bool found = false;
1579 e.in.handle = handle;
1580 e.in.level = 1;
1581 e.in.buffer = NULL;
1582 e.in.offered = 0;
1583 e.out.needed = &needed;
1584 e.out.count = &count;
1585 e.out.info = &info;
1587 torture_comment(tctx, "Testing EnumForms level 1\n");
1589 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1590 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1592 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1593 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1595 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1596 int j;
1597 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1598 data_blob_clear(&blob);
1599 e.in.buffer = &blob;
1600 e.in.offered = needed;
1602 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1604 torture_assert(tctx, info, "No forms returned");
1606 for (j = 0; j < count; j++) {
1607 if (strequal(form_name, info[j].info1.form_name)) {
1608 found = true;
1609 break;
1613 torture_assert(tctx, found, "Newly added form not found in enum call");
1616 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1617 ret = false;
1620 return ret;
1623 static bool test_EnumPorts_old(struct torture_context *tctx,
1624 struct dcerpc_pipe *p)
1626 NTSTATUS status;
1627 struct spoolss_EnumPorts r;
1628 uint32_t needed;
1629 uint32_t count;
1630 union spoolss_PortInfo *info;
1632 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1633 dcerpc_server_name(p));
1634 r.in.level = 2;
1635 r.in.buffer = NULL;
1636 r.in.offered = 0;
1637 r.out.needed = &needed;
1638 r.out.count = &count;
1639 r.out.info = &info;
1641 torture_comment(tctx, "Testing EnumPorts\n");
1643 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1645 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1647 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1648 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1649 data_blob_clear(&blob);
1650 r.in.buffer = &blob;
1651 r.in.offered = needed;
1653 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1654 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1656 torture_assert(tctx, info, "No ports returned");
1659 return true;
1662 static bool test_AddPort(struct torture_context *tctx,
1663 struct dcerpc_pipe *p)
1665 NTSTATUS status;
1666 struct spoolss_AddPort r;
1668 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1669 dcerpc_server_name(p));
1670 r.in.unknown = 0;
1671 r.in.monitor_name = "foo";
1673 torture_comment(tctx, "Testing AddPort\n");
1675 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1677 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1679 /* win2k3 returns WERR_NOT_SUPPORTED */
1681 #if 0
1683 if (!W_ERROR_IS_OK(r.out.result)) {
1684 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1685 return false;
1688 #endif
1690 return true;
1693 static bool test_GetJob(struct torture_context *tctx,
1694 struct dcerpc_pipe *p,
1695 struct policy_handle *handle, uint32_t job_id)
1697 NTSTATUS status;
1698 struct spoolss_GetJob r;
1699 union spoolss_JobInfo info;
1700 uint32_t needed;
1701 uint32_t levels[] = {1, 2 /* 3, 4 */};
1702 uint32_t i;
1704 r.in.handle = handle;
1705 r.in.job_id = job_id;
1706 r.in.level = 0;
1707 r.in.buffer = NULL;
1708 r.in.offered = 0;
1709 r.out.needed = &needed;
1710 r.out.info = &info;
1712 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1714 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1715 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1717 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1719 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1721 needed = 0;
1723 r.in.level = levels[i];
1724 r.in.offered = 0;
1725 r.in.buffer = NULL;
1727 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1728 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1730 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1731 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1732 data_blob_clear(&blob);
1733 r.in.buffer = &blob;
1734 r.in.offered = needed;
1736 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1737 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1740 torture_assert(tctx, r.out.info, "No job info returned");
1741 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1744 return true;
1747 static bool test_SetJob(struct torture_context *tctx,
1748 struct dcerpc_pipe *p,
1749 struct policy_handle *handle, uint32_t job_id,
1750 enum spoolss_JobControl command)
1752 NTSTATUS status;
1753 struct spoolss_SetJob r;
1755 r.in.handle = handle;
1756 r.in.job_id = job_id;
1757 r.in.ctr = NULL;
1758 r.in.command = command;
1760 switch (command) {
1761 case SPOOLSS_JOB_CONTROL_PAUSE:
1762 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1763 break;
1764 case SPOOLSS_JOB_CONTROL_RESUME:
1765 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1766 break;
1767 case SPOOLSS_JOB_CONTROL_CANCEL:
1768 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1769 break;
1770 case SPOOLSS_JOB_CONTROL_RESTART:
1771 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1772 break;
1773 case SPOOLSS_JOB_CONTROL_DELETE:
1774 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1775 break;
1776 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1777 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1778 break;
1779 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1780 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1781 break;
1782 case SPOOLSS_JOB_CONTROL_RETAIN:
1783 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1784 break;
1785 case SPOOLSS_JOB_CONTROL_RELEASE:
1786 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1787 break;
1788 default:
1789 torture_comment(tctx, "Testing SetJob\n");
1790 break;
1793 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1794 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1795 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1797 return true;
1800 static bool test_AddJob(struct torture_context *tctx,
1801 struct dcerpc_pipe *p,
1802 struct policy_handle *handle)
1804 NTSTATUS status;
1805 struct spoolss_AddJob r;
1806 uint32_t needed;
1808 r.in.level = 0;
1809 r.in.handle = handle;
1810 r.in.offered = 0;
1811 r.out.needed = &needed;
1812 r.in.buffer = r.out.buffer = NULL;
1814 torture_comment(tctx, "Testing AddJob\n");
1816 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1817 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1819 r.in.level = 1;
1821 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1822 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1824 return true;
1828 static bool test_EnumJobs(struct torture_context *tctx,
1829 struct dcerpc_pipe *p,
1830 struct policy_handle *handle)
1832 NTSTATUS status;
1833 struct spoolss_EnumJobs r;
1834 uint32_t needed;
1835 uint32_t count;
1836 union spoolss_JobInfo *info;
1838 r.in.handle = handle;
1839 r.in.firstjob = 0;
1840 r.in.numjobs = 0xffffffff;
1841 r.in.level = 1;
1842 r.in.buffer = NULL;
1843 r.in.offered = 0;
1844 r.out.needed = &needed;
1845 r.out.count = &count;
1846 r.out.info = &info;
1848 torture_comment(tctx, "Testing EnumJobs\n");
1850 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1852 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1854 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1855 int j;
1856 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1857 data_blob_clear(&blob);
1858 r.in.buffer = &blob;
1859 r.in.offered = needed;
1861 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1863 torture_assert(tctx, info, "No jobs returned");
1865 for (j = 0; j < count; j++) {
1867 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1869 /* FIXME - gd */
1870 if (!torture_setting_bool(tctx, "samba3", false)) {
1871 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1872 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1876 } else {
1877 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1880 return true;
1883 static bool test_DoPrintTest(struct torture_context *tctx,
1884 struct dcerpc_pipe *p,
1885 struct policy_handle *handle)
1887 bool ret = true;
1888 NTSTATUS status;
1889 struct spoolss_StartDocPrinter s;
1890 struct spoolss_DocumentInfo1 info1;
1891 struct spoolss_StartPagePrinter sp;
1892 struct spoolss_WritePrinter w;
1893 struct spoolss_EndPagePrinter ep;
1894 struct spoolss_EndDocPrinter e;
1895 int i;
1896 uint32_t job_id;
1897 uint32_t num_written;
1899 torture_comment(tctx, "Testing StartDocPrinter\n");
1901 s.in.handle = handle;
1902 s.in.level = 1;
1903 s.in.info.info1 = &info1;
1904 s.out.job_id = &job_id;
1905 info1.document_name = "TorturePrintJob";
1906 info1.output_file = NULL;
1907 info1.datatype = "RAW";
1909 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1910 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1911 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1913 for (i=1; i < 4; i++) {
1914 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1916 sp.in.handle = handle;
1918 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1919 torture_assert_ntstatus_ok(tctx, status,
1920 "dcerpc_spoolss_StartPagePrinter failed");
1921 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1923 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1925 w.in.handle = handle;
1926 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1927 w.out.num_written = &num_written;
1929 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1930 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1931 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1933 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1935 ep.in.handle = handle;
1937 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1938 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1939 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1942 torture_comment(tctx, "Testing EndDocPrinter\n");
1944 e.in.handle = handle;
1946 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1947 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1948 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1950 ret &= test_AddJob(tctx, p, handle);
1951 ret &= test_EnumJobs(tctx, p, handle);
1953 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1955 return ret;
1958 static bool test_PausePrinter(struct torture_context *tctx,
1959 struct dcerpc_pipe *p,
1960 struct policy_handle *handle)
1962 NTSTATUS status;
1963 struct spoolss_SetPrinter r;
1964 struct spoolss_SetPrinterInfoCtr info_ctr;
1965 struct spoolss_DevmodeContainer devmode_ctr;
1966 struct sec_desc_buf secdesc_ctr;
1968 info_ctr.level = 0;
1969 info_ctr.info.info0 = NULL;
1971 ZERO_STRUCT(devmode_ctr);
1972 ZERO_STRUCT(secdesc_ctr);
1974 r.in.handle = handle;
1975 r.in.info_ctr = &info_ctr;
1976 r.in.devmode_ctr = &devmode_ctr;
1977 r.in.secdesc_ctr = &secdesc_ctr;
1978 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1980 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1982 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1984 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1986 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1988 return true;
1991 static bool test_ResumePrinter(struct torture_context *tctx,
1992 struct dcerpc_pipe *p,
1993 struct policy_handle *handle)
1995 NTSTATUS status;
1996 struct spoolss_SetPrinter r;
1997 struct spoolss_SetPrinterInfoCtr info_ctr;
1998 struct spoolss_DevmodeContainer devmode_ctr;
1999 struct sec_desc_buf secdesc_ctr;
2001 info_ctr.level = 0;
2002 info_ctr.info.info0 = NULL;
2004 ZERO_STRUCT(devmode_ctr);
2005 ZERO_STRUCT(secdesc_ctr);
2007 r.in.handle = handle;
2008 r.in.info_ctr = &info_ctr;
2009 r.in.devmode_ctr = &devmode_ctr;
2010 r.in.secdesc_ctr = &secdesc_ctr;
2011 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2013 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2015 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2017 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2019 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2021 return true;
2024 static bool test_GetPrinterData(struct torture_context *tctx,
2025 struct dcerpc_pipe *p,
2026 struct policy_handle *handle,
2027 const char *value_name)
2029 NTSTATUS status;
2030 struct spoolss_GetPrinterData r;
2031 uint32_t needed;
2032 enum winreg_Type type;
2033 union spoolss_PrinterData data;
2035 r.in.handle = handle;
2036 r.in.value_name = value_name;
2037 r.in.offered = 0;
2038 r.out.needed = &needed;
2039 r.out.type = &type;
2040 r.out.data = &data;
2042 torture_comment(tctx, "Testing GetPrinterData\n");
2044 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2045 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2047 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2048 r.in.offered = needed;
2050 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2051 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2053 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2056 return true;
2059 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2060 struct dcerpc_pipe *p,
2061 struct policy_handle *handle,
2062 const char *key_name,
2063 const char *value_name)
2065 NTSTATUS status;
2066 struct spoolss_GetPrinterDataEx r;
2067 enum winreg_Type type;
2068 uint32_t needed;
2070 r.in.handle = handle;
2071 r.in.key_name = key_name;
2072 r.in.value_name = value_name;
2073 r.in.offered = 0;
2074 r.out.type = &type;
2075 r.out.needed = &needed;
2076 r.out.buffer = NULL;
2078 torture_comment(tctx, "Testing GetPrinterDataEx\n");
2080 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2083 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2084 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2086 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2089 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2090 r.in.offered = needed;
2091 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2093 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2094 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2096 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
2099 return true;
2102 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2103 struct policy_handle *handle)
2105 NTSTATUS status;
2106 struct spoolss_EnumPrinterData r;
2108 ZERO_STRUCT(r);
2109 r.in.handle = handle;
2110 r.in.enum_index = 0;
2112 do {
2113 uint32_t value_size = 0;
2114 uint32_t data_size = 0;
2115 enum winreg_Type type = 0;
2117 r.in.value_offered = value_size;
2118 r.out.value_needed = &value_size;
2119 r.in.data_offered = data_size;
2120 r.out.data_needed = &data_size;
2122 r.out.type = &type;
2123 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2125 torture_comment(tctx, "Testing EnumPrinterData\n");
2127 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2129 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2131 r.in.value_offered = value_size;
2132 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2133 r.in.data_offered = data_size;
2134 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2136 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2138 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2140 test_GetPrinterData(tctx, p, handle, r.out.value_name);
2142 test_GetPrinterDataEx(tctx,
2143 p, handle, "PrinterDriverData",
2144 r.out.value_name);
2146 r.in.enum_index++;
2148 } while (W_ERROR_IS_OK(r.out.result));
2150 return true;
2153 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2154 struct dcerpc_pipe *p,
2155 struct policy_handle *handle)
2157 NTSTATUS status;
2158 struct spoolss_EnumPrinterDataEx r;
2159 struct spoolss_PrinterEnumValues *info;
2160 uint32_t needed;
2161 uint32_t count;
2163 r.in.handle = handle;
2164 r.in.key_name = "PrinterDriverData";
2165 r.in.offered = 0;
2166 r.out.needed = &needed;
2167 r.out.count = &count;
2168 r.out.info = &info;
2170 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
2172 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2173 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2175 r.in.offered = needed;
2177 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2179 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2181 return true;
2185 static bool test_DeletePrinterData(struct torture_context *tctx,
2186 struct dcerpc_pipe *p,
2187 struct policy_handle *handle,
2188 const char *value_name)
2190 NTSTATUS status;
2191 struct spoolss_DeletePrinterData r;
2193 r.in.handle = handle;
2194 r.in.value_name = value_name;
2196 torture_comment(tctx, "Testing DeletePrinterData\n");
2198 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2200 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2202 return true;
2205 static bool test_SetPrinterData(struct torture_context *tctx,
2206 struct dcerpc_pipe *p,
2207 struct policy_handle *handle)
2209 NTSTATUS status;
2210 struct spoolss_SetPrinterData r;
2211 const char *value_name = "spottyfoot";
2213 r.in.handle = handle;
2214 r.in.value_name = value_name;
2215 r.in.type = REG_SZ;
2216 r.in.data.string = "dog";
2218 torture_comment(tctx, "Testing SetPrinterData\n");
2220 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2222 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2224 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
2225 return false;
2228 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
2229 return false;
2232 return true;
2235 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2236 struct dcerpc_pipe *p,
2237 struct policy_handle *handle)
2239 NTSTATUS status;
2240 struct dcerpc_binding *b;
2241 struct dcerpc_pipe *p2;
2242 struct spoolss_ClosePrinter cp;
2244 /* only makes sense on SMB */
2245 if (p->conn->transport.transport != NCACN_NP) {
2246 return true;
2249 torture_comment(tctx, "testing close on secondary pipe\n");
2251 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2252 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2254 status = dcerpc_secondary_connection(p, &p2, b);
2255 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2257 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2258 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2260 cp.in.handle = handle;
2261 cp.out.handle = handle;
2263 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2264 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2265 "ERROR: Allowed close on secondary connection");
2267 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2268 "Unexpected fault code");
2270 talloc_free(p2);
2272 return true;
2275 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2276 struct dcerpc_pipe *p, const char *name)
2278 NTSTATUS status;
2279 struct spoolss_OpenPrinter op;
2280 struct spoolss_OpenPrinterEx opEx;
2281 struct policy_handle handle;
2282 bool ret = true;
2284 op.in.printername = name;
2285 op.in.datatype = NULL;
2286 op.in.devmode_ctr.devmode= NULL;
2287 op.in.access_mask = 0;
2288 op.out.handle = &handle;
2290 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2292 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2293 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2294 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2295 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2296 name, win_errstr(op.out.result));
2299 if (W_ERROR_IS_OK(op.out.result)) {
2300 ret &=test_ClosePrinter(tctx, p, &handle);
2303 opEx.in.printername = name;
2304 opEx.in.datatype = NULL;
2305 opEx.in.devmode_ctr.devmode = NULL;
2306 opEx.in.access_mask = 0;
2307 opEx.in.level = 1;
2308 opEx.in.userlevel.level1 = NULL;
2309 opEx.out.handle = &handle;
2311 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2313 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2314 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2315 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2316 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2317 name, win_errstr(opEx.out.result));
2320 if (W_ERROR_IS_OK(opEx.out.result)) {
2321 ret &=test_ClosePrinter(tctx, p, &handle);
2324 return ret;
2327 static bool test_OpenPrinter(struct torture_context *tctx,
2328 struct dcerpc_pipe *p,
2329 const char *name)
2331 NTSTATUS status;
2332 struct spoolss_OpenPrinter r;
2333 struct policy_handle handle;
2334 bool ret = true;
2336 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2337 r.in.datatype = NULL;
2338 r.in.devmode_ctr.devmode= NULL;
2339 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2340 r.out.handle = &handle;
2342 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2344 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2346 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2348 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2350 if (!test_GetPrinter(tctx, p, &handle)) {
2351 ret = false;
2354 if (!torture_setting_bool(tctx, "samba3", false)) {
2355 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2356 ret = false;
2360 if (!test_ClosePrinter(tctx, p, &handle)) {
2361 ret = false;
2364 return ret;
2367 static bool call_OpenPrinterEx(struct torture_context *tctx,
2368 struct dcerpc_pipe *p,
2369 const char *name, struct policy_handle *handle)
2371 struct spoolss_OpenPrinterEx r;
2372 struct spoolss_UserLevel1 userlevel1;
2373 NTSTATUS status;
2375 if (name && name[0]) {
2376 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2377 dcerpc_server_name(p), name);
2378 } else {
2379 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2380 dcerpc_server_name(p));
2383 r.in.datatype = NULL;
2384 r.in.devmode_ctr.devmode= NULL;
2385 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2386 r.in.level = 1;
2387 r.in.userlevel.level1 = &userlevel1;
2388 r.out.handle = handle;
2390 userlevel1.size = 1234;
2391 userlevel1.client = "hello";
2392 userlevel1.user = "spottyfoot!";
2393 userlevel1.build = 1;
2394 userlevel1.major = 2;
2395 userlevel1.minor = 3;
2396 userlevel1.processor = 4;
2398 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2400 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2402 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2404 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2406 return true;
2409 static bool test_OpenPrinterEx(struct torture_context *tctx,
2410 struct dcerpc_pipe *p,
2411 const char *name)
2413 struct policy_handle handle;
2414 bool ret = true;
2416 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2417 return false;
2420 if (!test_GetPrinter(tctx, p, &handle)) {
2421 ret = false;
2424 if (!test_EnumForms(tctx, p, &handle, false)) {
2425 ret = false;
2428 if (!test_AddForm(tctx, p, &handle, false)) {
2429 ret = false;
2432 if (!test_EnumPrinterData(tctx, p, &handle)) {
2433 ret = false;
2436 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
2437 ret = false;
2440 if (!test_PausePrinter(tctx, p, &handle)) {
2441 ret = false;
2444 if (!test_DoPrintTest(tctx, p, &handle)) {
2445 ret = false;
2448 if (!test_ResumePrinter(tctx, p, &handle)) {
2449 ret = false;
2452 if (!test_SetPrinterData(tctx, p, &handle)) {
2453 ret = false;
2456 if (!torture_setting_bool(tctx, "samba3", false)) {
2457 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2458 ret = false;
2462 if (!test_ClosePrinter(tctx, p, &handle)) {
2463 ret = false;
2466 return ret;
2469 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2471 struct spoolss_EnumPrinters r;
2472 NTSTATUS status;
2473 uint16_t levels[] = {1, 2, 4, 5};
2474 int i;
2475 bool ret = true;
2477 for (i=0;i<ARRAY_SIZE(levels);i++) {
2478 union spoolss_PrinterInfo *info;
2479 int j;
2480 uint32_t needed;
2481 uint32_t count;
2483 r.in.flags = PRINTER_ENUM_LOCAL;
2484 r.in.server = "";
2485 r.in.level = levels[i];
2486 r.in.buffer = NULL;
2487 r.in.offered = 0;
2488 r.out.needed = &needed;
2489 r.out.count = &count;
2490 r.out.info = &info;
2492 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2494 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2497 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2498 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2499 data_blob_clear(&blob);
2500 r.in.buffer = &blob;
2501 r.in.offered = needed;
2502 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2505 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2507 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2509 if (!info) {
2510 torture_comment(tctx, "No printers returned\n");
2511 return true;
2514 for (j=0;j<count;j++) {
2515 if (r.in.level == 1) {
2516 char *unc = talloc_strdup(tctx, info[j].info1.name);
2517 char *slash, *name;
2518 name = unc;
2519 if (unc[0] == '\\' && unc[1] == '\\') {
2520 unc +=2;
2522 slash = strchr(unc, '\\');
2523 if (slash) {
2524 slash++;
2525 name = slash;
2527 if (!test_OpenPrinter(tctx, p, name)) {
2528 ret = false;
2530 if (!test_OpenPrinterEx(tctx, p, name)) {
2531 ret = false;
2537 return ret;
2540 static bool test_GetPrinterDriver(struct torture_context *tctx,
2541 struct dcerpc_pipe *p,
2542 struct policy_handle *handle,
2543 const char *driver_name)
2545 struct spoolss_GetPrinterDriver r;
2546 uint32_t needed;
2548 r.in.handle = handle;
2549 r.in.architecture = "W32X86";
2550 r.in.level = 1;
2551 r.in.buffer = NULL;
2552 r.in.offered = 0;
2553 r.out.needed = &needed;
2555 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2557 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2558 "failed to call GetPrinterDriver");
2559 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2560 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2561 data_blob_clear(&blob);
2562 r.in.buffer = &blob;
2563 r.in.offered = needed;
2564 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2565 "failed to call GetPrinterDriver");
2568 torture_assert_werr_ok(tctx, r.out.result,
2569 "failed to call GetPrinterDriver");
2571 return true;
2574 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2575 struct dcerpc_pipe *p,
2576 struct policy_handle *handle,
2577 const char *driver_name)
2579 struct spoolss_GetPrinterDriver2 r;
2580 uint32_t needed;
2581 uint32_t server_major_version;
2582 uint32_t server_minor_version;
2584 r.in.handle = handle;
2585 r.in.architecture = "W32X86";
2586 r.in.level = 1;
2587 r.in.buffer = NULL;
2588 r.in.offered = 0;
2589 r.in.client_major_version = 0;
2590 r.in.client_minor_version = 0;
2591 r.out.needed = &needed;
2592 r.out.server_major_version = &server_major_version;
2593 r.out.server_minor_version = &server_minor_version;
2595 torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2597 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2598 "failed to call GetPrinterDriver2");
2599 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2600 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2601 data_blob_clear(&blob);
2602 r.in.buffer = &blob;
2603 r.in.offered = needed;
2604 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2605 "failed to call GetPrinterDriver2");
2608 torture_assert_werr_ok(tctx, r.out.result,
2609 "failed to call GetPrinterDriver2");
2611 return true;
2614 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2615 struct dcerpc_pipe *p)
2617 struct spoolss_EnumPrinterDrivers r;
2618 NTSTATUS status;
2619 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2620 int i;
2622 for (i=0;i<ARRAY_SIZE(levels);i++) {
2624 uint32_t needed;
2625 uint32_t count;
2626 union spoolss_DriverInfo *info;
2628 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2629 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2630 r.in.level = levels[i];
2631 r.in.buffer = NULL;
2632 r.in.offered = 0;
2633 r.out.needed = &needed;
2634 r.out.count = &count;
2635 r.out.info = &info;
2637 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2639 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2641 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2643 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2644 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2645 data_blob_clear(&blob);
2646 r.in.buffer = &blob;
2647 r.in.offered = needed;
2648 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2651 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2653 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2655 if (!info) {
2656 torture_comment(tctx, "No printer drivers returned\n");
2657 break;
2661 return true;
2664 static bool test_DeletePrinter(struct torture_context *tctx,
2665 struct dcerpc_pipe *p,
2666 struct policy_handle *handle)
2668 struct spoolss_DeletePrinter r;
2670 torture_comment(tctx, "Testing DeletePrinter\n");
2672 r.in.handle = handle;
2674 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2675 "failed to delete printer");
2676 torture_assert_werr_ok(tctx, r.out.result,
2677 "failed to delete printer");
2679 return true;
2682 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2683 struct dcerpc_pipe *p,
2684 uint32_t flags,
2685 uint32_t level,
2686 const char *name,
2687 bool *found)
2689 struct spoolss_EnumPrinters e;
2690 uint32_t count;
2691 union spoolss_PrinterInfo *info;
2692 uint32_t needed;
2693 int i;
2695 *found = false;
2697 e.in.flags = flags;
2698 e.in.server = NULL;
2699 e.in.level = level;
2700 e.in.buffer = NULL;
2701 e.in.offered = 0;
2702 e.out.count = &count;
2703 e.out.info = &info;
2704 e.out.needed = &needed;
2706 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2707 "failed to enum printers");
2709 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2710 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2711 data_blob_clear(&blob);
2712 e.in.buffer = &blob;
2713 e.in.offered = needed;
2715 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2716 "failed to enum printers");
2719 torture_assert_werr_ok(tctx, e.out.result,
2720 "failed to enum printers");
2722 for (i=0; i < count; i++) {
2724 const char *current = NULL;
2726 switch (level) {
2727 case 1:
2728 current = info[i].info1.name;
2729 break;
2732 if (strequal(current, name)) {
2733 *found = true;
2734 break;
2738 return true;
2741 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2742 struct dcerpc_pipe *p,
2743 const char *printername,
2744 bool ex)
2746 WERROR result;
2747 struct spoolss_AddPrinter r;
2748 struct spoolss_AddPrinterEx rex;
2749 struct spoolss_SetPrinterInfoCtr info_ctr;
2750 struct spoolss_SetPrinterInfo1 info1;
2751 struct spoolss_DevmodeContainer devmode_ctr;
2752 struct sec_desc_buf secdesc_ctr;
2753 struct spoolss_UserLevelCtr userlevel_ctr;
2754 struct policy_handle handle;
2755 bool found = false;
2757 ZERO_STRUCT(devmode_ctr);
2758 ZERO_STRUCT(secdesc_ctr);
2759 ZERO_STRUCT(userlevel_ctr);
2760 ZERO_STRUCT(info1);
2762 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
2764 /* try to add printer to wellknown printer list (level 1) */
2766 userlevel_ctr.level = 1;
2768 info_ctr.info.info1 = &info1;
2769 info_ctr.level = 1;
2771 rex.in.server = NULL;
2772 rex.in.info_ctr = &info_ctr;
2773 rex.in.devmode_ctr = &devmode_ctr;
2774 rex.in.secdesc_ctr = &secdesc_ctr;
2775 rex.in.userlevel_ctr = &userlevel_ctr;
2776 rex.out.handle = &handle;
2778 r.in.server = NULL;
2779 r.in.info_ctr = &info_ctr;
2780 r.in.devmode_ctr = &devmode_ctr;
2781 r.in.secdesc_ctr = &secdesc_ctr;
2782 r.out.handle = &handle;
2784 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2785 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2786 "failed to add printer");
2787 result = ex ? rex.out.result : r.out.result;
2788 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2789 "unexpected result code");
2791 info1.name = printername;
2792 info1.flags = PRINTER_ATTRIBUTE_SHARED;
2794 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2795 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2796 "failed to add printer");
2797 result = ex ? rex.out.result : r.out.result;
2798 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2799 "unexpected result code");
2801 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2802 better do a real check to see the printer is really there */
2804 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2805 PRINTER_ENUM_NETWORK, 1,
2806 printername,
2807 &found),
2808 "failed to enum printers");
2810 torture_assert(tctx, found, "failed to find newly added printer");
2812 info1.flags = 0;
2814 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2815 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2816 "failed to add printer");
2817 result = ex ? rex.out.result : r.out.result;
2818 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2819 "unexpected result code");
2821 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2822 better do a real check to see the printer has really been removed
2823 from the well known printer list */
2825 found = false;
2827 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2828 PRINTER_ENUM_NETWORK, 1,
2829 printername,
2830 &found),
2831 "failed to enum printers");
2832 #if 0
2833 torture_assert(tctx, !found, "printer still in well known printer list");
2834 #endif
2835 return true;
2838 static bool test_AddPrinter_normal(struct torture_context *tctx,
2839 struct dcerpc_pipe *p,
2840 struct policy_handle *handle_p,
2841 const char *printername,
2842 const char *drivername,
2843 const char *portname,
2844 bool ex)
2846 WERROR result;
2847 struct spoolss_AddPrinter r;
2848 struct spoolss_AddPrinterEx rex;
2849 struct spoolss_SetPrinterInfoCtr info_ctr;
2850 struct spoolss_SetPrinterInfo2 info2;
2851 struct spoolss_DevmodeContainer devmode_ctr;
2852 struct sec_desc_buf secdesc_ctr;
2853 struct spoolss_UserLevelCtr userlevel_ctr;
2854 struct policy_handle handle;
2855 bool found = false;
2857 ZERO_STRUCT(devmode_ctr);
2858 ZERO_STRUCT(secdesc_ctr);
2859 ZERO_STRUCT(userlevel_ctr);
2861 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
2863 userlevel_ctr.level = 1;
2865 rex.in.server = NULL;
2866 rex.in.info_ctr = &info_ctr;
2867 rex.in.devmode_ctr = &devmode_ctr;
2868 rex.in.secdesc_ctr = &secdesc_ctr;
2869 rex.in.userlevel_ctr = &userlevel_ctr;
2870 rex.out.handle = &handle;
2872 r.in.server = NULL;
2873 r.in.info_ctr = &info_ctr;
2874 r.in.devmode_ctr = &devmode_ctr;
2875 r.in.secdesc_ctr = &secdesc_ctr;
2876 r.out.handle = &handle;
2878 again:
2880 /* try to add printer to printer list (level 2) */
2882 ZERO_STRUCT(info2);
2884 info_ctr.info.info2 = &info2;
2885 info_ctr.level = 2;
2887 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2888 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2889 "failed to add printer");
2890 result = ex ? rex.out.result : r.out.result;
2891 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2892 "unexpected result code");
2894 info2.printername = printername;
2896 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2897 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2898 "failed to add printer");
2899 result = ex ? rex.out.result : r.out.result;
2901 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
2902 struct policy_handle printer_handle;
2904 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
2905 "failed to open printer handle");
2907 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
2908 "failed to delete printer");
2910 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
2911 "failed to close server handle");
2913 goto again;
2916 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
2917 "unexpected result code");
2919 info2.portname = portname;
2921 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2922 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2923 "failed to add printer");
2924 result = ex ? rex.out.result : r.out.result;
2925 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
2926 "unexpected result code");
2928 info2.drivername = drivername;
2930 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2931 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2932 "failed to add printer");
2933 result = ex ? rex.out.result : r.out.result;
2934 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
2935 "unexpected result code");
2937 info2.printprocessor = "winprint";
2939 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2940 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2941 "failed to add printer");
2942 result = ex ? rex.out.result : r.out.result;
2943 torture_assert_werr_ok(tctx, result,
2944 "failed to add printer");
2946 *handle_p = handle;
2948 /* we are paranoid, really check if the printer is there now */
2950 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2951 PRINTER_ENUM_LOCAL, 1,
2952 printername,
2953 &found),
2954 "failed to enum printers");
2955 torture_assert(tctx, found, "failed to find newly added printer");
2957 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2958 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2959 "failed to add printer");
2960 result = ex ? rex.out.result : r.out.result;
2961 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2962 "unexpected result code");
2964 return true;
2967 static bool test_AddPrinterEx(struct torture_context *tctx,
2968 struct dcerpc_pipe *p,
2969 struct policy_handle *handle_p,
2970 const char *printername,
2971 const char *drivername,
2972 const char *portname)
2974 bool ret = true;
2976 if (!torture_setting_bool(tctx, "samba3", false)) {
2977 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
2978 torture_comment(tctx, "failed to add printer to well known list\n");
2979 ret = false;
2983 if (!test_AddPrinter_normal(tctx, p, handle_p,
2984 printername, drivername, portname,
2985 true)) {
2986 torture_comment(tctx, "failed to add printer to printer list\n");
2987 ret = false;
2990 return ret;
2993 static bool test_AddPrinter(struct torture_context *tctx,
2994 struct dcerpc_pipe *p,
2995 struct policy_handle *handle_p,
2996 const char *printername,
2997 const char *drivername,
2998 const char *portname)
3000 bool ret = true;
3002 if (!torture_setting_bool(tctx, "samba3", false)) {
3003 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3004 torture_comment(tctx, "failed to add printer to well known list\n");
3005 ret = false;
3009 if (!test_AddPrinter_normal(tctx, p, handle_p,
3010 printername, drivername, portname,
3011 false)) {
3012 torture_comment(tctx, "failed to add printer to printer list\n");
3013 ret = false;
3016 return ret;
3019 static bool test_printer_info(struct torture_context *tctx,
3020 struct dcerpc_pipe *p,
3021 struct policy_handle *handle)
3023 bool ret = true;
3025 if (!test_PrinterInfo(tctx, p, handle)) {
3026 ret = false;
3029 if (!test_SetPrinter_errors(tctx, p, handle)) {
3030 ret = false;
3033 return ret;
3036 static bool test_printer(struct torture_context *tctx,
3037 struct dcerpc_pipe *p)
3039 bool ret = true;
3040 struct policy_handle handle[2];
3041 bool found = false;
3042 const char *drivername = "Microsoft XPS Document Writer";
3043 const char *portname = "LPT1:";
3045 /* test printer created via AddPrinter */
3047 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3048 return false;
3051 if (!test_printer_info(tctx, p, &handle[0])) {
3052 ret = false;
3055 if (!test_DeletePrinter(tctx, p, &handle[0])) {
3056 ret = false;
3059 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3060 TORTURE_PRINTER, &found)) {
3061 ret = false;
3064 torture_assert(tctx, !found, "deleted printer still there");
3066 /* test printer created via AddPrinterEx */
3068 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3069 return false;
3072 if (!test_printer_info(tctx, p, &handle[1])) {
3073 ret = false;
3076 if (!test_DeletePrinter(tctx, p, &handle[1])) {
3077 ret = false;
3080 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3081 TORTURE_PRINTER_EX, &found)) {
3082 ret = false;
3085 torture_assert(tctx, !found, "deleted printer still there");
3087 return ret;
3090 bool torture_rpc_spoolss(struct torture_context *torture)
3092 NTSTATUS status;
3093 struct dcerpc_pipe *p;
3094 bool ret = true;
3095 struct test_spoolss_context *ctx;
3097 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3098 if (!NT_STATUS_IS_OK(status)) {
3099 return false;
3102 ctx = talloc_zero(torture, struct test_spoolss_context);
3104 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3106 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
3107 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
3108 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
3109 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
3110 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
3111 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
3112 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
3113 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
3114 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
3115 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
3116 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
3117 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
3118 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
3119 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3120 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3121 ret &= test_EnumPorts(torture, p, ctx);
3122 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3123 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3124 ret &= test_EnumPrinterDrivers(torture, p, ctx);
3125 ret &= test_EnumMonitors(torture, p, ctx);
3126 ret &= test_EnumPrintProcessors(torture, p, ctx);
3127 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3128 ret &= test_EnumPrinters(torture, p, ctx);
3129 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3130 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3131 ret &= test_OpenPrinter_badname(torture, p, "");
3132 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3133 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3134 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3135 ret &= test_OpenPrinter_badname(torture, p,
3136 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3139 ret &= test_AddPort(torture, p);
3140 ret &= test_EnumPorts_old(torture, p);
3141 ret &= test_EnumPrinters_old(torture, p);
3142 ret &= test_EnumPrinterDrivers_old(torture, p);
3144 return ret;
3147 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3149 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3151 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3152 "printer", &ndr_table_spoolss);
3154 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3156 return suite;