s4-smbtorture: add some tests to check spoolss_SetPrinter behavior.
[Samba/nivanova.git] / source4 / torture / rpc / spoolss.c
blobb6ad1a77c25cd5e8b36d8f56c463a4278eb21d1e
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 struct test_spoolss_context {
30 /* print server handle */
31 struct policy_handle server_handle;
33 /* for EnumPorts */
34 uint32_t port_count[3];
35 union spoolss_PortInfo *ports[3];
37 /* for EnumPrinterDrivers */
38 uint32_t driver_count[7];
39 union spoolss_DriverInfo *drivers[7];
41 /* for EnumMonitors */
42 uint32_t monitor_count[3];
43 union spoolss_MonitorInfo *monitors[3];
45 /* for EnumPrintProcessors */
46 uint32_t print_processor_count[2];
47 union spoolss_PrintProcessorInfo *print_processors[2];
49 /* for EnumPrinters */
50 uint32_t printer_count[6];
51 union spoolss_PrinterInfo *printers[6];
54 #define COMPARE_STRING(tctx, c,r,e) \
55 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
57 /* not every compiler supports __typeof__() */
58 #if (__GNUC__ >= 3)
59 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
60 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
61 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
63 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
64 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
66 } while(0)
67 #else
68 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
69 #endif
71 #define COMPARE_UINT32(tctx, c, r, e) do {\
72 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
73 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
74 } while(0)
76 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
78 static bool test_OpenPrinter_server(struct torture_context *tctx,
79 struct dcerpc_pipe *p,
80 struct policy_handle *server_handle)
82 NTSTATUS status;
83 struct spoolss_OpenPrinter op;
85 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
86 op.in.datatype = NULL;
87 op.in.devmode_ctr.devmode= NULL;
88 op.in.access_mask = 0;
89 op.out.handle = server_handle;
91 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
93 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
94 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
95 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
97 return true;
100 static bool test_EnumPorts(struct torture_context *tctx,
101 struct dcerpc_pipe *p,
102 struct test_spoolss_context *ctx)
104 NTSTATUS status;
105 struct spoolss_EnumPorts r;
106 uint16_t levels[] = { 1, 2 };
107 int i, j;
109 for (i=0;i<ARRAY_SIZE(levels);i++) {
110 int level = levels[i];
111 DATA_BLOB blob;
112 uint32_t needed;
113 uint32_t count;
114 union spoolss_PortInfo *info;
116 r.in.servername = "";
117 r.in.level = level;
118 r.in.buffer = NULL;
119 r.in.offered = 0;
120 r.out.needed = &needed;
121 r.out.count = &count;
122 r.out.info = &info;
124 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
126 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
127 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
128 if (W_ERROR_IS_OK(r.out.result)) {
129 /* TODO: do some more checks here */
130 continue;
132 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
133 "EnumPorts unexpected return code");
135 blob = data_blob_talloc(ctx, NULL, needed);
136 data_blob_clear(&blob);
137 r.in.buffer = &blob;
138 r.in.offered = needed;
140 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
141 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
143 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
145 torture_assert(tctx, info, "EnumPorts returned no info");
147 ctx->port_count[level] = count;
148 ctx->ports[level] = info;
151 for (i=1;i<ARRAY_SIZE(levels);i++) {
152 int level = levels[i];
153 int old_level = levels[i-1];
154 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
155 "EnumPorts invalid value");
157 /* if the array sizes are not the same we would maybe segfault in the following code */
159 for (i=0;i<ARRAY_SIZE(levels);i++) {
160 int level = levels[i];
161 for (j=0;j<ctx->port_count[level];j++) {
162 union spoolss_PortInfo *cur = &ctx->ports[level][j];
163 union spoolss_PortInfo *ref = &ctx->ports[2][j];
164 switch (level) {
165 case 1:
166 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
167 break;
168 case 2:
169 /* level 2 is our reference, and it makes no sense to compare it to itself */
170 break;
175 return true;
178 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
179 struct dcerpc_pipe *p,
180 struct test_spoolss_context *ctx)
182 NTSTATUS status;
183 struct spoolss_GetPrintProcessorDirectory r;
184 struct {
185 uint16_t level;
186 const char *server;
187 } levels[] = {{
188 .level = 1,
189 .server = NULL
191 .level = 1,
192 .server = ""
194 .level = 78,
195 .server = ""
197 .level = 1,
198 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
200 .level = 1024,
201 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
204 int i;
205 uint32_t needed;
207 for (i=0;i<ARRAY_SIZE(levels);i++) {
208 int level = levels[i].level;
209 DATA_BLOB blob;
211 r.in.server = levels[i].server;
212 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
213 r.in.level = level;
214 r.in.buffer = NULL;
215 r.in.offered = 0;
216 r.out.needed = &needed;
218 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
220 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
221 torture_assert_ntstatus_ok(tctx, status,
222 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
223 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
224 "GetPrintProcessorDirectory unexpected return code");
226 blob = data_blob_talloc(ctx, NULL, needed);
227 data_blob_clear(&blob);
228 r.in.buffer = &blob;
229 r.in.offered = needed;
231 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
232 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
234 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
237 return true;
241 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
242 struct dcerpc_pipe *p,
243 struct test_spoolss_context *ctx)
245 NTSTATUS status;
246 struct spoolss_GetPrinterDriverDirectory r;
247 struct {
248 uint16_t level;
249 const char *server;
250 } levels[] = {{
251 .level = 1,
252 .server = NULL
254 .level = 1,
255 .server = ""
257 .level = 78,
258 .server = ""
260 .level = 1,
261 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
263 .level = 1024,
264 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
267 int i;
268 uint32_t needed;
270 for (i=0;i<ARRAY_SIZE(levels);i++) {
271 int level = levels[i].level;
272 DATA_BLOB blob;
274 r.in.server = levels[i].server;
275 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
276 r.in.level = level;
277 r.in.buffer = NULL;
278 r.in.offered = 0;
279 r.out.needed = &needed;
281 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
283 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
284 torture_assert_ntstatus_ok(tctx, status,
285 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
286 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
287 "GetPrinterDriverDirectory unexpected return code");
289 blob = data_blob_talloc(ctx, NULL, needed);
290 data_blob_clear(&blob);
291 r.in.buffer = &blob;
292 r.in.offered = needed;
294 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
295 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
297 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
300 return true;
303 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
304 struct dcerpc_pipe *p,
305 struct test_spoolss_context *ctx)
307 NTSTATUS status;
308 struct spoolss_EnumPrinterDrivers r;
309 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
310 int i, j, a;
311 const char *architectures[] = {
312 SPOOLSS_ARCHITECTURE_NT_X86,
313 SPOOLSS_ARCHITECTURE_ALL
316 for (i=0;i<ARRAY_SIZE(levels);i++) {
317 for (a=0;a<ARRAY_SIZE(architectures);a++) {
318 int level = levels[i];
319 DATA_BLOB blob;
320 uint32_t needed;
321 uint32_t count;
322 union spoolss_DriverInfo *info;
324 /* FIXME: gd, come back and fix "" as server, and handle
325 * priority of returned error codes in torture test and samba 3
326 * server */
328 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
329 r.in.environment = architectures[a];
330 r.in.level = level;
331 r.in.buffer = NULL;
332 r.in.offered = 0;
333 r.out.needed = &needed;
334 r.out.count = &count;
335 r.out.info = &info;
337 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
339 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
340 torture_assert_ntstatus_ok(tctx, status,
341 "dcerpc_spoolss_EnumPrinterDrivers failed");
342 if (W_ERROR_IS_OK(r.out.result)) {
343 /* TODO: do some more checks here */
344 continue;
346 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
347 blob = data_blob_talloc(ctx, NULL, needed);
348 data_blob_clear(&blob);
349 r.in.buffer = &blob;
350 r.in.offered = needed;
352 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
353 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
356 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
358 /* don't do cross-architecture comparison */
359 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
360 continue;
363 ctx->driver_count[level] = count;
364 ctx->drivers[level] = info;
368 for (i=1;i<ARRAY_SIZE(levels);i++) {
369 int level = levels[i];
370 int old_level = levels[i-1];
372 /* don't do cross-architecture comparison */
373 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
374 continue;
377 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
378 "EnumPrinterDrivers invalid value");
381 for (i=0;i<ARRAY_SIZE(levels);i++) {
382 int level = levels[i];
384 /* don't do cross-architecture comparison */
385 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
386 continue;
389 for (j=0;j<ctx->driver_count[level];j++) {
390 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
391 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
392 switch (level) {
393 case 1:
394 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
395 break;
396 case 2:
397 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
398 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
399 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
400 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
401 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
402 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
403 break;
404 case 3:
405 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
406 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
407 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
408 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
409 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
410 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
411 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
412 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
413 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
414 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
415 break;
416 case 4:
417 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
418 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
419 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
420 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
421 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
422 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
423 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
424 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
425 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
426 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
427 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
428 break;
429 case 5:
430 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
431 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
432 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
433 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
434 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
435 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
436 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
437 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
438 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
439 break;
440 case 6:
441 /* level 6 is our reference, and it makes no sense to compare it to itself */
442 break;
447 return true;
450 static bool test_EnumMonitors(struct torture_context *tctx,
451 struct dcerpc_pipe *p,
452 struct test_spoolss_context *ctx)
454 NTSTATUS status;
455 struct spoolss_EnumMonitors r;
456 uint16_t levels[] = { 1, 2 };
457 int i, j;
459 for (i=0;i<ARRAY_SIZE(levels);i++) {
460 int level = levels[i];
461 DATA_BLOB blob;
462 uint32_t needed;
463 uint32_t count;
464 union spoolss_MonitorInfo *info;
466 r.in.servername = "";
467 r.in.level = level;
468 r.in.buffer = NULL;
469 r.in.offered = 0;
470 r.out.needed = &needed;
471 r.out.count = &count;
472 r.out.info = &info;
474 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
476 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
477 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
478 if (W_ERROR_IS_OK(r.out.result)) {
479 /* TODO: do some more checks here */
480 continue;
482 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
483 "EnumMonitors failed");
485 blob = data_blob_talloc(ctx, NULL, needed);
486 data_blob_clear(&blob);
487 r.in.buffer = &blob;
488 r.in.offered = needed;
490 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
491 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
493 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
495 ctx->monitor_count[level] = count;
496 ctx->monitors[level] = info;
499 for (i=1;i<ARRAY_SIZE(levels);i++) {
500 int level = levels[i];
501 int old_level = levels[i-1];
502 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
503 "EnumMonitors invalid value");
506 for (i=0;i<ARRAY_SIZE(levels);i++) {
507 int level = levels[i];
508 for (j=0;j<ctx->monitor_count[level];j++) {
509 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
510 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
511 switch (level) {
512 case 1:
513 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
514 break;
515 case 2:
516 /* level 2 is our reference, and it makes no sense to compare it to itself */
517 break;
522 return true;
525 static bool test_EnumPrintProcessors(struct torture_context *tctx,
526 struct dcerpc_pipe *p,
527 struct test_spoolss_context *ctx)
529 NTSTATUS status;
530 struct spoolss_EnumPrintProcessors r;
531 uint16_t levels[] = { 1 };
532 int i, j;
534 for (i=0;i<ARRAY_SIZE(levels);i++) {
535 int level = levels[i];
536 DATA_BLOB blob;
537 uint32_t needed;
538 uint32_t count;
539 union spoolss_PrintProcessorInfo *info;
541 r.in.servername = "";
542 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
543 r.in.level = level;
544 r.in.buffer = NULL;
545 r.in.offered = 0;
546 r.out.needed = &needed;
547 r.out.count = &count;
548 r.out.info = &info;
550 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
552 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
553 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
554 if (W_ERROR_IS_OK(r.out.result)) {
555 /* TODO: do some more checks here */
556 continue;
558 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
559 "EnumPrintProcessors unexpected return code");
561 blob = data_blob_talloc(ctx, NULL, needed);
562 data_blob_clear(&blob);
563 r.in.buffer = &blob;
564 r.in.offered = needed;
566 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
567 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
569 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
571 ctx->print_processor_count[level] = count;
572 ctx->print_processors[level] = info;
575 for (i=1;i<ARRAY_SIZE(levels);i++) {
576 int level = levels[i];
577 int old_level = levels[i-1];
578 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
579 "EnumPrintProcessors failed");
582 for (i=0;i<ARRAY_SIZE(levels);i++) {
583 int level = levels[i];
584 for (j=0;j<ctx->print_processor_count[level];j++) {
585 #if 0
586 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
587 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
588 #endif
589 switch (level) {
590 case 1:
591 /* level 1 is our reference, and it makes no sense to compare it to itself */
592 break;
597 return true;
600 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
601 struct dcerpc_pipe *p,
602 struct test_spoolss_context *ctx)
604 NTSTATUS status;
605 struct spoolss_EnumPrintProcDataTypes r;
606 uint16_t levels[] = { 1 };
607 int i;
609 for (i=0;i<ARRAY_SIZE(levels);i++) {
610 int level = levels[i];
611 DATA_BLOB blob;
612 uint32_t needed;
613 uint32_t count;
614 union spoolss_PrintProcDataTypesInfo *info;
616 r.in.servername = "";
617 r.in.print_processor_name = "winprint";
618 r.in.level = level;
619 r.in.buffer = NULL;
620 r.in.offered = 0;
621 r.out.needed = &needed;
622 r.out.count = &count;
623 r.out.info = &info;
625 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
627 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
628 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
629 if (W_ERROR_IS_OK(r.out.result)) {
630 /* TODO: do some more checks here */
631 continue;
633 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
634 "EnumPrintProcDataTypes unexpected return code");
636 blob = data_blob_talloc(ctx, NULL, needed);
637 data_blob_clear(&blob);
638 r.in.buffer = &blob;
639 r.in.offered = needed;
641 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
642 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
644 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
647 return true;
651 static bool test_EnumPrinters(struct torture_context *tctx,
652 struct dcerpc_pipe *p,
653 struct test_spoolss_context *ctx)
655 struct spoolss_EnumPrinters r;
656 NTSTATUS status;
657 uint16_t levels[] = { 0, 1, 2, 4, 5 };
658 int i, j;
660 for (i=0;i<ARRAY_SIZE(levels);i++) {
661 int level = levels[i];
662 DATA_BLOB blob;
663 uint32_t needed;
664 uint32_t count;
665 union spoolss_PrinterInfo *info;
667 r.in.flags = PRINTER_ENUM_LOCAL;
668 r.in.server = "";
669 r.in.level = level;
670 r.in.buffer = NULL;
671 r.in.offered = 0;
672 r.out.needed = &needed;
673 r.out.count = &count;
674 r.out.info = &info;
676 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
678 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
679 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
680 if (W_ERROR_IS_OK(r.out.result)) {
681 /* TODO: do some more checks here */
682 continue;
684 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
685 "EnumPrinters unexpected return code");
687 blob = data_blob_talloc(ctx, NULL, needed);
688 data_blob_clear(&blob);
689 r.in.buffer = &blob;
690 r.in.offered = needed;
692 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
693 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
695 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
697 ctx->printer_count[level] = count;
698 ctx->printers[level] = info;
701 for (i=1;i<ARRAY_SIZE(levels);i++) {
702 int level = levels[i];
703 int old_level = levels[i-1];
704 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
705 "EnumPrinters invalid value");
708 for (i=0;i<ARRAY_SIZE(levels);i++) {
709 int level = levels[i];
710 for (j=0;j<ctx->printer_count[level];j++) {
711 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
712 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
713 switch (level) {
714 case 0:
715 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
716 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
718 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
719 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
720 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
721 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
723 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
725 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
727 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
737 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
739 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
740 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
742 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
743 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
744 break;
745 case 1:
746 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
747 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
748 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
749 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
750 break;
751 case 2:
752 /* level 2 is our reference, and it makes no sense to compare it to itself */
753 break;
754 case 4:
755 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
756 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
757 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
758 break;
759 case 5:
760 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
761 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
762 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
763 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
764 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
765 break;
770 /* TODO:
771 * - verify that the port of a printer was in the list returned by EnumPorts
774 return true;
777 static bool test_GetPrinter(struct torture_context *tctx,
778 struct dcerpc_pipe *p,
779 struct policy_handle *handle)
781 NTSTATUS status;
782 struct spoolss_GetPrinter r;
783 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
784 int i;
785 uint32_t needed;
787 for (i=0;i<ARRAY_SIZE(levels);i++) {
788 r.in.handle = handle;
789 r.in.level = levels[i];
790 r.in.buffer = NULL;
791 r.in.offered = 0;
792 r.out.needed = &needed;
794 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
796 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
797 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
799 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
800 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
801 data_blob_clear(&blob);
802 r.in.buffer = &blob;
803 r.in.offered = needed;
804 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
807 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
809 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
812 return true;
815 static bool test_SetPrinter_errors(struct torture_context *tctx,
816 struct dcerpc_pipe *p,
817 struct policy_handle *handle)
819 struct spoolss_SetPrinter r;
820 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
821 int i;
823 struct spoolss_SetPrinterInfoCtr info_ctr;
824 struct spoolss_DevmodeContainer devmode_ctr;
825 struct sec_desc_buf secdesc_ctr;
827 info_ctr.level = 0;
828 info_ctr.info.info0 = NULL;
830 ZERO_STRUCT(devmode_ctr);
831 ZERO_STRUCT(secdesc_ctr);
833 r.in.handle = handle;
834 r.in.info_ctr = &info_ctr;
835 r.in.devmode_ctr = &devmode_ctr;
836 r.in.secdesc_ctr = &secdesc_ctr;
837 r.in.command = 0;
839 torture_comment(tctx, "Testing SetPrinter all zero\n");
841 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
842 "failed to call SetPrinter");
843 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
844 "failed to call SetPrinter");
846 again:
847 for (i=0; i < ARRAY_SIZE(levels); i++) {
849 struct spoolss_SetPrinterInfo0 info0;
850 struct spoolss_SetPrinterInfo1 info1;
851 struct spoolss_SetPrinterInfo2 info2;
852 struct spoolss_SetPrinterInfo3 info3;
853 struct spoolss_SetPrinterInfo4 info4;
854 struct spoolss_SetPrinterInfo5 info5;
855 struct spoolss_SetPrinterInfo6 info6;
856 struct spoolss_SetPrinterInfo7 info7;
857 struct spoolss_DeviceModeInfo info8;
858 struct spoolss_DeviceModeInfo info9;
861 info_ctr.level = levels[i];
862 switch (levels[i]) {
863 case 0:
864 ZERO_STRUCT(info0);
865 info_ctr.info.info0 = &info0;
866 break;
867 case 1:
868 ZERO_STRUCT(info1);
869 info_ctr.info.info1 = &info1;
870 break;
871 case 2:
872 ZERO_STRUCT(info2);
873 info_ctr.info.info2 = &info2;
874 break;
875 case 3:
876 ZERO_STRUCT(info3);
877 info_ctr.info.info3 = &info3;
878 break;
879 case 4:
880 ZERO_STRUCT(info4);
881 info_ctr.info.info4 = &info4;
882 break;
883 case 5:
884 ZERO_STRUCT(info5);
885 info_ctr.info.info5 = &info5;
886 break;
887 case 6:
888 ZERO_STRUCT(info6);
889 info_ctr.info.info6 = &info6;
890 break;
891 case 7:
892 ZERO_STRUCT(info7);
893 info_ctr.info.info7 = &info7;
894 break;
895 case 8:
896 ZERO_STRUCT(info8);
897 info_ctr.info.info8 = &info8;
898 break;
899 case 9:
900 ZERO_STRUCT(info9);
901 info_ctr.info.info9 = &info9;
902 break;
905 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
906 info_ctr.level, r.in.command);
908 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
909 "failed to call SetPrinter");
911 switch (r.in.command) {
912 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
913 /* is ignored for all levels other then 0 */
914 if (info_ctr.level > 0) {
915 /* ignored then */
916 break;
918 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
919 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
920 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
921 if (info_ctr.level > 0) {
922 /* is invalid for all levels other then 0 */
923 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
924 "unexpected error code returned");
925 continue;
926 } else {
927 torture_assert_werr_ok(tctx, r.out.result,
928 "failed to call SetPrinter with non 0 command");
929 continue;
931 break;
933 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
934 /* FIXME: gd needs further investigation */
935 default:
936 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
937 "unexpected error code returned");
938 continue;
941 switch (info_ctr.level) {
942 case 1:
943 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
944 "unexpected error code returned");
945 break;
946 case 2:
947 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
948 "unexpected error code returned");
949 break;
950 case 3:
951 case 4:
952 case 5:
953 case 7:
954 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
955 "unexpected error code returned");
956 break;
957 case 9:
958 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
959 "unexpected error code returned");
960 break;
961 default:
962 torture_assert_werr_ok(tctx, r.out.result,
963 "failed to call SetPrinter");
964 break;
968 if (r.in.command < 5) {
969 r.in.command++;
970 goto again;
973 return true;
976 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
978 if ((r->level == 2) && (r->info.info2)) {
979 r->info.info2->secdesc = NULL;
980 r->info.info2->devmode = NULL;
984 static bool test_PrinterInfo(struct torture_context *tctx,
985 struct dcerpc_pipe *p,
986 struct policy_handle *handle)
988 NTSTATUS status;
989 struct spoolss_SetPrinter s;
990 struct spoolss_GetPrinter q;
991 struct spoolss_GetPrinter q0;
992 struct spoolss_SetPrinterInfoCtr info_ctr;
993 union spoolss_PrinterInfo info;
994 struct spoolss_DevmodeContainer devmode_ctr;
995 struct sec_desc_buf secdesc_ctr;
996 uint32_t needed;
997 bool ret = true;
998 int i;
1000 uint32_t status_list[] = {
1001 /* these do not stick
1002 PRINTER_STATUS_PAUSED,
1003 PRINTER_STATUS_ERROR,
1004 PRINTER_STATUS_PENDING_DELETION, */
1005 PRINTER_STATUS_PAPER_JAM,
1006 PRINTER_STATUS_PAPER_OUT,
1007 PRINTER_STATUS_MANUAL_FEED,
1008 PRINTER_STATUS_PAPER_PROBLEM,
1009 PRINTER_STATUS_OFFLINE,
1010 PRINTER_STATUS_IO_ACTIVE,
1011 PRINTER_STATUS_BUSY,
1012 PRINTER_STATUS_PRINTING,
1013 PRINTER_STATUS_OUTPUT_BIN_FULL,
1014 PRINTER_STATUS_NOT_AVAILABLE,
1015 PRINTER_STATUS_WAITING,
1016 PRINTER_STATUS_PROCESSING,
1017 PRINTER_STATUS_INITIALIZING,
1018 PRINTER_STATUS_WARMING_UP,
1019 PRINTER_STATUS_TONER_LOW,
1020 PRINTER_STATUS_NO_TONER,
1021 PRINTER_STATUS_PAGE_PUNT,
1022 PRINTER_STATUS_USER_INTERVENTION,
1023 PRINTER_STATUS_OUT_OF_MEMORY,
1024 PRINTER_STATUS_DOOR_OPEN,
1025 PRINTER_STATUS_SERVER_UNKNOWN,
1026 PRINTER_STATUS_POWER_SAVE,
1027 /* these do not stick
1028 0x02000000,
1029 0x04000000,
1030 0x08000000,
1031 0x10000000,
1032 0x20000000,
1033 0x40000000,
1034 0x80000000 */
1036 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1037 uint32_t attribute_list[] = {
1038 PRINTER_ATTRIBUTE_QUEUED,
1039 /* fails with WERR_INVALID_DATATYPE:
1040 PRINTER_ATTRIBUTE_DIRECT, */
1041 /* does not stick
1042 PRINTER_ATTRIBUTE_DEFAULT, */
1043 PRINTER_ATTRIBUTE_SHARED,
1044 /* does not stick
1045 PRINTER_ATTRIBUTE_NETWORK, */
1046 PRINTER_ATTRIBUTE_HIDDEN,
1047 PRINTER_ATTRIBUTE_LOCAL,
1048 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1049 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1050 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1051 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1052 /* does not stick
1053 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1054 /* fails with WERR_INVALID_DATATYPE:
1055 PRINTER_ATTRIBUTE_RAW_ONLY, */
1056 /* these do not stick
1057 PRINTER_ATTRIBUTE_PUBLISHED,
1058 PRINTER_ATTRIBUTE_FAX,
1059 PRINTER_ATTRIBUTE_TS,
1060 0x00010000,
1061 0x00020000,
1062 0x00040000,
1063 0x00080000,
1064 0x00100000,
1065 0x00200000,
1066 0x00400000,
1067 0x00800000,
1068 0x01000000,
1069 0x02000000,
1070 0x04000000,
1071 0x08000000,
1072 0x10000000,
1073 0x20000000,
1074 0x40000000,
1075 0x80000000 */
1078 ZERO_STRUCT(devmode_ctr);
1079 ZERO_STRUCT(secdesc_ctr);
1081 s.in.handle = handle;
1082 s.in.command = 0;
1083 s.in.info_ctr = &info_ctr;
1084 s.in.devmode_ctr = &devmode_ctr;
1085 s.in.secdesc_ctr = &secdesc_ctr;
1087 q.in.handle = handle;
1088 q.out.info = &info;
1089 q0 = q;
1091 #define TESTGETCALL(call, r) \
1092 r.in.buffer = NULL; \
1093 r.in.offered = 0;\
1094 r.out.needed = &needed; \
1095 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1096 if (!NT_STATUS_IS_OK(status)) { \
1097 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1098 r.in.level, nt_errstr(status), __location__); \
1099 ret = false; \
1100 break; \
1102 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1103 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1104 data_blob_clear(&blob); \
1105 r.in.buffer = &blob; \
1106 r.in.offered = needed; \
1108 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1109 if (!NT_STATUS_IS_OK(status)) { \
1110 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1111 r.in.level, nt_errstr(status), __location__); \
1112 ret = false; \
1113 break; \
1115 if (!W_ERROR_IS_OK(r.out.result)) { \
1116 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1117 r.in.level, win_errstr(r.out.result), __location__); \
1118 ret = false; \
1119 break; \
1123 #define TESTSETCALL_EXP(call, r, err) \
1124 clear_info2(&info_ctr);\
1125 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1126 if (!NT_STATUS_IS_OK(status)) { \
1127 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1128 r.in.info_ctr->level, nt_errstr(status), __location__); \
1129 ret = false; \
1130 break; \
1132 if (!W_ERROR_IS_OK(err)) { \
1133 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1134 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1135 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1136 ret = false; \
1138 break; \
1140 if (!W_ERROR_IS_OK(r.out.result)) { \
1141 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1142 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1143 ret = false; \
1144 break; \
1147 #define TESTSETCALL(call, r) \
1148 TESTSETCALL_EXP(call, r, WERR_OK)
1150 #define STRING_EQUAL(s1, s2, field) \
1151 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1152 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1153 #field, s2, __location__); \
1154 ret = false; \
1155 break; \
1158 #define MEM_EQUAL(s1, s2, length, field) \
1159 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1160 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1161 #field, (const char *)s2, __location__); \
1162 ret = false; \
1163 break; \
1166 #define INT_EQUAL(i1, i2, field) \
1167 if (i1 != i2) { \
1168 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1169 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1170 ret = false; \
1171 break; \
1174 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1175 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1176 q.in.level = lvl1; \
1177 TESTGETCALL(GetPrinter, q) \
1178 info_ctr.level = lvl1; \
1179 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1180 info_ctr.info.info ## lvl1->field1 = value;\
1181 TESTSETCALL_EXP(SetPrinter, s, err) \
1182 info_ctr.info.info ## lvl1->field1 = ""; \
1183 TESTGETCALL(GetPrinter, q) \
1184 info_ctr.info.info ## lvl1->field1 = value; \
1185 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1186 q.in.level = lvl2; \
1187 TESTGETCALL(GetPrinter, q) \
1188 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1189 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1190 } while (0)
1192 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1193 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1194 } while (0);
1196 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1197 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1198 q.in.level = lvl1; \
1199 TESTGETCALL(GetPrinter, q) \
1200 info_ctr.level = lvl1; \
1201 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1202 info_ctr.info.info ## lvl1->field1 = value; \
1203 TESTSETCALL(SetPrinter, s) \
1204 info_ctr.info.info ## lvl1->field1 = 0; \
1205 TESTGETCALL(GetPrinter, q) \
1206 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1207 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1208 q.in.level = lvl2; \
1209 TESTGETCALL(GetPrinter, q) \
1210 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1211 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1212 } while (0)
1214 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1215 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1216 } while (0)
1218 q0.in.level = 0;
1219 do { TESTGETCALL(GetPrinter, q0) } while (0);
1221 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1222 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1224 /* level 0 printername does not stick */
1225 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1226 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1227 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1228 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1229 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1230 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1231 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1232 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1233 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1234 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1235 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1236 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1237 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1238 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1239 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1241 /* servername can be set but does not stick
1242 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1243 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1244 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1247 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1248 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1249 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1250 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1251 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1253 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1254 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1255 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1256 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1257 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1258 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1259 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1260 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1261 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1262 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1264 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1265 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1266 attribute_list[i],
1267 (attribute_list[i] | default_attribute)
1268 ); */
1269 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1270 attribute_list[i],
1271 (attribute_list[i] | default_attribute)
1273 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1274 attribute_list[i],
1275 (attribute_list[i] | default_attribute)
1277 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1278 attribute_list[i],
1279 (attribute_list[i] | default_attribute)
1281 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1282 attribute_list[i],
1283 (attribute_list[i] | default_attribute)
1284 ); */
1285 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1286 attribute_list[i],
1287 (attribute_list[i] | default_attribute)
1289 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1290 attribute_list[i],
1291 (attribute_list[i] | default_attribute)
1293 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1294 attribute_list[i],
1295 (attribute_list[i] | default_attribute)
1297 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1298 attribute_list[i],
1299 (attribute_list[i] | default_attribute)
1300 ); */
1301 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1302 attribute_list[i],
1303 (attribute_list[i] | default_attribute)
1305 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1306 attribute_list[i],
1307 (attribute_list[i] | default_attribute)
1309 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1310 attribute_list[i],
1311 (attribute_list[i] | default_attribute)
1315 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1316 /* level 2 sets do not stick
1317 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1318 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1319 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1320 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1321 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1322 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1325 /* priorities need to be between 0 and 99
1326 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1327 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1328 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1329 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1330 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1331 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1332 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1333 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1334 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1336 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1337 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1339 /* does not stick
1340 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1341 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1343 /* does not stick
1344 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1345 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1347 /* FIXME: gd also test devmode and secdesc behavior */
1350 /* verify composition of level 1 description field */
1351 const char *description;
1352 const char *tmp;
1354 q0.in.level = 1;
1355 do { TESTGETCALL(GetPrinter, q0) } while (0);
1357 description = talloc_strdup(tctx, q0.out.info->info1.description);
1359 q0.in.level = 2;
1360 do { TESTGETCALL(GetPrinter, q0) } while (0);
1362 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1363 q0.out.info->info2.printername,
1364 q0.out.info->info2.drivername,
1365 q0.out.info->info2.location);
1367 do { STRING_EQUAL(description, tmp, "description")} while (0);
1370 return ret;
1374 static bool test_ClosePrinter(struct torture_context *tctx,
1375 struct dcerpc_pipe *p,
1376 struct policy_handle *handle)
1378 NTSTATUS status;
1379 struct spoolss_ClosePrinter r;
1381 r.in.handle = handle;
1382 r.out.handle = handle;
1384 torture_comment(tctx, "Testing ClosePrinter\n");
1386 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1387 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1389 return true;
1392 static bool test_GetForm(struct torture_context *tctx,
1393 struct dcerpc_pipe *p,
1394 struct policy_handle *handle,
1395 const char *form_name,
1396 uint32_t level)
1398 NTSTATUS status;
1399 struct spoolss_GetForm r;
1400 uint32_t needed;
1402 r.in.handle = handle;
1403 r.in.form_name = form_name;
1404 r.in.level = level;
1405 r.in.buffer = NULL;
1406 r.in.offered = 0;
1407 r.out.needed = &needed;
1409 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1411 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1412 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1414 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1415 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1416 data_blob_clear(&blob);
1417 r.in.buffer = &blob;
1418 r.in.offered = needed;
1419 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1420 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1422 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1424 torture_assert(tctx, r.out.info, "No form info returned");
1427 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1429 return true;
1432 static bool test_EnumForms(struct torture_context *tctx,
1433 struct dcerpc_pipe *p,
1434 struct policy_handle *handle, bool print_server)
1436 NTSTATUS status;
1437 struct spoolss_EnumForms r;
1438 bool ret = true;
1439 uint32_t needed;
1440 uint32_t count;
1441 uint32_t levels[] = { 1, 2 };
1442 int i;
1444 for (i=0; i<ARRAY_SIZE(levels); i++) {
1446 union spoolss_FormInfo *info;
1448 r.in.handle = handle;
1449 r.in.level = levels[i];
1450 r.in.buffer = NULL;
1451 r.in.offered = 0;
1452 r.out.needed = &needed;
1453 r.out.count = &count;
1454 r.out.info = &info;
1456 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1458 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1459 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1461 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1462 break;
1465 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1466 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1468 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1469 int j;
1470 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1471 data_blob_clear(&blob);
1472 r.in.buffer = &blob;
1473 r.in.offered = needed;
1475 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1477 torture_assert(tctx, info, "No forms returned");
1479 for (j = 0; j < count; j++) {
1480 if (!print_server)
1481 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1485 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1487 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1490 return true;
1493 static bool test_DeleteForm(struct torture_context *tctx,
1494 struct dcerpc_pipe *p,
1495 struct policy_handle *handle,
1496 const char *form_name)
1498 NTSTATUS status;
1499 struct spoolss_DeleteForm r;
1501 r.in.handle = handle;
1502 r.in.form_name = form_name;
1504 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1506 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1508 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1510 return true;
1513 static bool test_AddForm(struct torture_context *tctx,
1514 struct dcerpc_pipe *p,
1515 struct policy_handle *handle, bool print_server)
1517 struct spoolss_AddForm r;
1518 struct spoolss_AddFormInfo1 addform;
1519 const char *form_name = "testform3";
1520 NTSTATUS status;
1521 bool ret = true;
1523 r.in.handle = handle;
1524 r.in.level = 1;
1525 r.in.info.info1 = &addform;
1526 addform.flags = SPOOLSS_FORM_USER;
1527 addform.form_name = form_name;
1528 addform.size.width = 50;
1529 addform.size.height = 25;
1530 addform.area.left = 5;
1531 addform.area.top = 10;
1532 addform.area.right = 45;
1533 addform.area.bottom = 15;
1535 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1537 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1539 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1541 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1544 struct spoolss_SetForm sf;
1545 struct spoolss_AddFormInfo1 setform;
1547 sf.in.handle = handle;
1548 sf.in.form_name = form_name;
1549 sf.in.level = 1;
1550 sf.in.info.info1= &setform;
1551 setform.flags = addform.flags;
1552 setform.form_name = addform.form_name;
1553 setform.size = addform.size;
1554 setform.area = addform.area;
1556 setform.size.width = 1234;
1558 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1560 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1562 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1565 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1568 struct spoolss_EnumForms e;
1569 union spoolss_FormInfo *info;
1570 uint32_t needed;
1571 uint32_t count;
1572 bool found = false;
1574 e.in.handle = handle;
1575 e.in.level = 1;
1576 e.in.buffer = NULL;
1577 e.in.offered = 0;
1578 e.out.needed = &needed;
1579 e.out.count = &count;
1580 e.out.info = &info;
1582 torture_comment(tctx, "Testing EnumForms level 1\n");
1584 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1585 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1587 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1588 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1590 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1591 int j;
1592 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1593 data_blob_clear(&blob);
1594 e.in.buffer = &blob;
1595 e.in.offered = needed;
1597 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1599 torture_assert(tctx, info, "No forms returned");
1601 for (j = 0; j < count; j++) {
1602 if (strequal(form_name, info[j].info1.form_name)) {
1603 found = true;
1604 break;
1608 torture_assert(tctx, found, "Newly added form not found in enum call");
1611 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1612 ret = false;
1615 return ret;
1618 static bool test_EnumPorts_old(struct torture_context *tctx,
1619 struct dcerpc_pipe *p)
1621 NTSTATUS status;
1622 struct spoolss_EnumPorts r;
1623 uint32_t needed;
1624 uint32_t count;
1625 union spoolss_PortInfo *info;
1627 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1628 dcerpc_server_name(p));
1629 r.in.level = 2;
1630 r.in.buffer = NULL;
1631 r.in.offered = 0;
1632 r.out.needed = &needed;
1633 r.out.count = &count;
1634 r.out.info = &info;
1636 torture_comment(tctx, "Testing EnumPorts\n");
1638 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1640 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1642 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1643 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1644 data_blob_clear(&blob);
1645 r.in.buffer = &blob;
1646 r.in.offered = needed;
1648 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1649 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1651 torture_assert(tctx, info, "No ports returned");
1654 return true;
1657 static bool test_AddPort(struct torture_context *tctx,
1658 struct dcerpc_pipe *p)
1660 NTSTATUS status;
1661 struct spoolss_AddPort r;
1663 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1664 dcerpc_server_name(p));
1665 r.in.unknown = 0;
1666 r.in.monitor_name = "foo";
1668 torture_comment(tctx, "Testing AddPort\n");
1670 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1672 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1674 /* win2k3 returns WERR_NOT_SUPPORTED */
1676 #if 0
1678 if (!W_ERROR_IS_OK(r.out.result)) {
1679 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1680 return false;
1683 #endif
1685 return true;
1688 static bool test_GetJob(struct torture_context *tctx,
1689 struct dcerpc_pipe *p,
1690 struct policy_handle *handle, uint32_t job_id)
1692 NTSTATUS status;
1693 struct spoolss_GetJob r;
1694 union spoolss_JobInfo info;
1695 uint32_t needed;
1696 uint32_t levels[] = {1, 2 /* 3, 4 */};
1697 uint32_t i;
1699 r.in.handle = handle;
1700 r.in.job_id = job_id;
1701 r.in.level = 0;
1702 r.in.buffer = NULL;
1703 r.in.offered = 0;
1704 r.out.needed = &needed;
1705 r.out.info = &info;
1707 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1709 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1710 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1712 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1714 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1716 needed = 0;
1718 r.in.level = levels[i];
1719 r.in.offered = 0;
1720 r.in.buffer = NULL;
1722 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1723 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1725 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1726 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1727 data_blob_clear(&blob);
1728 r.in.buffer = &blob;
1729 r.in.offered = needed;
1731 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1732 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1735 torture_assert(tctx, r.out.info, "No job info returned");
1736 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1739 return true;
1742 static bool test_SetJob(struct torture_context *tctx,
1743 struct dcerpc_pipe *p,
1744 struct policy_handle *handle, uint32_t job_id,
1745 enum spoolss_JobControl command)
1747 NTSTATUS status;
1748 struct spoolss_SetJob r;
1750 r.in.handle = handle;
1751 r.in.job_id = job_id;
1752 r.in.ctr = NULL;
1753 r.in.command = command;
1755 switch (command) {
1756 case SPOOLSS_JOB_CONTROL_PAUSE:
1757 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1758 break;
1759 case SPOOLSS_JOB_CONTROL_RESUME:
1760 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1761 break;
1762 case SPOOLSS_JOB_CONTROL_CANCEL:
1763 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1764 break;
1765 case SPOOLSS_JOB_CONTROL_RESTART:
1766 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1767 break;
1768 case SPOOLSS_JOB_CONTROL_DELETE:
1769 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1770 break;
1771 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1772 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1773 break;
1774 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1775 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1776 break;
1777 case SPOOLSS_JOB_CONTROL_RETAIN:
1778 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1779 break;
1780 case SPOOLSS_JOB_CONTROL_RELEASE:
1781 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1782 break;
1783 default:
1784 torture_comment(tctx, "Testing SetJob\n");
1785 break;
1788 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1789 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1790 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1792 return true;
1795 static bool test_AddJob(struct torture_context *tctx,
1796 struct dcerpc_pipe *p,
1797 struct policy_handle *handle)
1799 NTSTATUS status;
1800 struct spoolss_AddJob r;
1801 uint32_t needed;
1803 r.in.level = 0;
1804 r.in.handle = handle;
1805 r.in.offered = 0;
1806 r.out.needed = &needed;
1807 r.in.buffer = r.out.buffer = NULL;
1809 torture_comment(tctx, "Testing AddJob\n");
1811 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1812 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1814 r.in.level = 1;
1816 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1817 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1819 return true;
1823 static bool test_EnumJobs(struct torture_context *tctx,
1824 struct dcerpc_pipe *p,
1825 struct policy_handle *handle)
1827 NTSTATUS status;
1828 struct spoolss_EnumJobs r;
1829 uint32_t needed;
1830 uint32_t count;
1831 union spoolss_JobInfo *info;
1833 r.in.handle = handle;
1834 r.in.firstjob = 0;
1835 r.in.numjobs = 0xffffffff;
1836 r.in.level = 1;
1837 r.in.buffer = NULL;
1838 r.in.offered = 0;
1839 r.out.needed = &needed;
1840 r.out.count = &count;
1841 r.out.info = &info;
1843 torture_comment(tctx, "Testing EnumJobs\n");
1845 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1847 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1849 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1850 int j;
1851 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1852 data_blob_clear(&blob);
1853 r.in.buffer = &blob;
1854 r.in.offered = needed;
1856 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1858 torture_assert(tctx, info, "No jobs returned");
1860 for (j = 0; j < count; j++) {
1862 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1864 /* FIXME - gd */
1865 if (!torture_setting_bool(tctx, "samba3", false)) {
1866 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1867 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1871 } else {
1872 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1875 return true;
1878 static bool test_DoPrintTest(struct torture_context *tctx,
1879 struct dcerpc_pipe *p,
1880 struct policy_handle *handle)
1882 bool ret = true;
1883 NTSTATUS status;
1884 struct spoolss_StartDocPrinter s;
1885 struct spoolss_DocumentInfo1 info1;
1886 struct spoolss_StartPagePrinter sp;
1887 struct spoolss_WritePrinter w;
1888 struct spoolss_EndPagePrinter ep;
1889 struct spoolss_EndDocPrinter e;
1890 int i;
1891 uint32_t job_id;
1892 uint32_t num_written;
1894 torture_comment(tctx, "Testing StartDocPrinter\n");
1896 s.in.handle = handle;
1897 s.in.level = 1;
1898 s.in.info.info1 = &info1;
1899 s.out.job_id = &job_id;
1900 info1.document_name = "TorturePrintJob";
1901 info1.output_file = NULL;
1902 info1.datatype = "RAW";
1904 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1905 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1906 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1908 for (i=1; i < 4; i++) {
1909 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1911 sp.in.handle = handle;
1913 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1914 torture_assert_ntstatus_ok(tctx, status,
1915 "dcerpc_spoolss_StartPagePrinter failed");
1916 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1918 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1920 w.in.handle = handle;
1921 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1922 w.out.num_written = &num_written;
1924 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1925 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1926 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1928 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1930 ep.in.handle = handle;
1932 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1933 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1934 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1937 torture_comment(tctx, "Testing EndDocPrinter\n");
1939 e.in.handle = handle;
1941 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1942 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1943 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1945 ret &= test_AddJob(tctx, p, handle);
1946 ret &= test_EnumJobs(tctx, p, handle);
1948 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1950 return ret;
1953 static bool test_PausePrinter(struct torture_context *tctx,
1954 struct dcerpc_pipe *p,
1955 struct policy_handle *handle)
1957 NTSTATUS status;
1958 struct spoolss_SetPrinter r;
1959 struct spoolss_SetPrinterInfoCtr info_ctr;
1960 struct spoolss_DevmodeContainer devmode_ctr;
1961 struct sec_desc_buf secdesc_ctr;
1963 info_ctr.level = 0;
1964 info_ctr.info.info0 = NULL;
1966 ZERO_STRUCT(devmode_ctr);
1967 ZERO_STRUCT(secdesc_ctr);
1969 r.in.handle = handle;
1970 r.in.info_ctr = &info_ctr;
1971 r.in.devmode_ctr = &devmode_ctr;
1972 r.in.secdesc_ctr = &secdesc_ctr;
1973 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1975 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1977 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1979 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1981 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1983 return true;
1986 static bool test_ResumePrinter(struct torture_context *tctx,
1987 struct dcerpc_pipe *p,
1988 struct policy_handle *handle)
1990 NTSTATUS status;
1991 struct spoolss_SetPrinter r;
1992 struct spoolss_SetPrinterInfoCtr info_ctr;
1993 struct spoolss_DevmodeContainer devmode_ctr;
1994 struct sec_desc_buf secdesc_ctr;
1996 info_ctr.level = 0;
1997 info_ctr.info.info0 = NULL;
1999 ZERO_STRUCT(devmode_ctr);
2000 ZERO_STRUCT(secdesc_ctr);
2002 r.in.handle = handle;
2003 r.in.info_ctr = &info_ctr;
2004 r.in.devmode_ctr = &devmode_ctr;
2005 r.in.secdesc_ctr = &secdesc_ctr;
2006 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2008 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2010 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2012 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2014 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2016 return true;
2019 static bool test_GetPrinterData(struct torture_context *tctx,
2020 struct dcerpc_pipe *p,
2021 struct policy_handle *handle,
2022 const char *value_name)
2024 NTSTATUS status;
2025 struct spoolss_GetPrinterData r;
2026 uint32_t needed;
2027 enum winreg_Type type;
2028 union spoolss_PrinterData data;
2030 r.in.handle = handle;
2031 r.in.value_name = value_name;
2032 r.in.offered = 0;
2033 r.out.needed = &needed;
2034 r.out.type = &type;
2035 r.out.data = &data;
2037 torture_comment(tctx, "Testing GetPrinterData\n");
2039 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2040 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2042 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2043 r.in.offered = needed;
2045 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2046 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2048 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2051 return true;
2054 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2055 struct dcerpc_pipe *p,
2056 struct policy_handle *handle,
2057 const char *key_name,
2058 const char *value_name)
2060 NTSTATUS status;
2061 struct spoolss_GetPrinterDataEx r;
2062 enum winreg_Type type;
2063 uint32_t needed;
2065 r.in.handle = handle;
2066 r.in.key_name = key_name;
2067 r.in.value_name = value_name;
2068 r.in.offered = 0;
2069 r.out.type = &type;
2070 r.out.needed = &needed;
2071 r.out.buffer = NULL;
2073 torture_comment(tctx, "Testing GetPrinterDataEx\n");
2075 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2078 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2079 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2081 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2084 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2085 r.in.offered = needed;
2086 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2088 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2089 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2091 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
2094 return true;
2097 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2098 struct policy_handle *handle)
2100 NTSTATUS status;
2101 struct spoolss_EnumPrinterData r;
2103 ZERO_STRUCT(r);
2104 r.in.handle = handle;
2105 r.in.enum_index = 0;
2107 do {
2108 uint32_t value_size = 0;
2109 uint32_t data_size = 0;
2110 enum winreg_Type type = 0;
2112 r.in.value_offered = value_size;
2113 r.out.value_needed = &value_size;
2114 r.in.data_offered = data_size;
2115 r.out.data_needed = &data_size;
2117 r.out.type = &type;
2118 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2120 torture_comment(tctx, "Testing EnumPrinterData\n");
2122 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2124 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2126 r.in.value_offered = value_size;
2127 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2128 r.in.data_offered = data_size;
2129 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2131 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2133 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2135 test_GetPrinterData(tctx, p, handle, r.out.value_name);
2137 test_GetPrinterDataEx(tctx,
2138 p, handle, "PrinterDriverData",
2139 r.out.value_name);
2141 r.in.enum_index++;
2143 } while (W_ERROR_IS_OK(r.out.result));
2145 return true;
2148 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2149 struct dcerpc_pipe *p,
2150 struct policy_handle *handle)
2152 NTSTATUS status;
2153 struct spoolss_EnumPrinterDataEx r;
2154 struct spoolss_PrinterEnumValues *info;
2155 uint32_t needed;
2156 uint32_t count;
2158 r.in.handle = handle;
2159 r.in.key_name = "PrinterDriverData";
2160 r.in.offered = 0;
2161 r.out.needed = &needed;
2162 r.out.count = &count;
2163 r.out.info = &info;
2165 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
2167 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2168 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2170 r.in.offered = needed;
2172 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2174 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2176 return true;
2180 static bool test_DeletePrinterData(struct torture_context *tctx,
2181 struct dcerpc_pipe *p,
2182 struct policy_handle *handle,
2183 const char *value_name)
2185 NTSTATUS status;
2186 struct spoolss_DeletePrinterData r;
2188 r.in.handle = handle;
2189 r.in.value_name = value_name;
2191 torture_comment(tctx, "Testing DeletePrinterData\n");
2193 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2195 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2197 return true;
2200 static bool test_SetPrinterData(struct torture_context *tctx,
2201 struct dcerpc_pipe *p,
2202 struct policy_handle *handle)
2204 NTSTATUS status;
2205 struct spoolss_SetPrinterData r;
2206 const char *value_name = "spottyfoot";
2208 r.in.handle = handle;
2209 r.in.value_name = value_name;
2210 r.in.type = REG_SZ;
2211 r.in.data.string = "dog";
2213 torture_comment(tctx, "Testing SetPrinterData\n");
2215 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2217 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2219 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
2220 return false;
2223 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
2224 return false;
2227 return true;
2230 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2231 struct dcerpc_pipe *p,
2232 struct policy_handle *handle)
2234 NTSTATUS status;
2235 struct dcerpc_binding *b;
2236 struct dcerpc_pipe *p2;
2237 struct spoolss_ClosePrinter cp;
2239 /* only makes sense on SMB */
2240 if (p->conn->transport.transport != NCACN_NP) {
2241 return true;
2244 torture_comment(tctx, "testing close on secondary pipe\n");
2246 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2247 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2249 status = dcerpc_secondary_connection(p, &p2, b);
2250 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2252 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2253 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2255 cp.in.handle = handle;
2256 cp.out.handle = handle;
2258 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2259 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2260 "ERROR: Allowed close on secondary connection");
2262 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2263 "Unexpected fault code");
2265 talloc_free(p2);
2267 return true;
2270 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2271 struct dcerpc_pipe *p, const char *name)
2273 NTSTATUS status;
2274 struct spoolss_OpenPrinter op;
2275 struct spoolss_OpenPrinterEx opEx;
2276 struct policy_handle handle;
2277 bool ret = true;
2279 op.in.printername = name;
2280 op.in.datatype = NULL;
2281 op.in.devmode_ctr.devmode= NULL;
2282 op.in.access_mask = 0;
2283 op.out.handle = &handle;
2285 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2287 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2288 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2289 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2290 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2291 name, win_errstr(op.out.result));
2294 if (W_ERROR_IS_OK(op.out.result)) {
2295 ret &=test_ClosePrinter(tctx, p, &handle);
2298 opEx.in.printername = name;
2299 opEx.in.datatype = NULL;
2300 opEx.in.devmode_ctr.devmode = NULL;
2301 opEx.in.access_mask = 0;
2302 opEx.in.level = 1;
2303 opEx.in.userlevel.level1 = NULL;
2304 opEx.out.handle = &handle;
2306 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2308 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2309 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2310 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2311 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2312 name, win_errstr(opEx.out.result));
2315 if (W_ERROR_IS_OK(opEx.out.result)) {
2316 ret &=test_ClosePrinter(tctx, p, &handle);
2319 return ret;
2322 static bool test_OpenPrinter(struct torture_context *tctx,
2323 struct dcerpc_pipe *p,
2324 const char *name)
2326 NTSTATUS status;
2327 struct spoolss_OpenPrinter r;
2328 struct policy_handle handle;
2329 bool ret = true;
2331 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2332 r.in.datatype = NULL;
2333 r.in.devmode_ctr.devmode= NULL;
2334 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2335 r.out.handle = &handle;
2337 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2339 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2341 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2343 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2345 if (!test_GetPrinter(tctx, p, &handle)) {
2346 ret = false;
2349 if (!torture_setting_bool(tctx, "samba3", false)) {
2350 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2351 ret = false;
2355 if (!test_ClosePrinter(tctx, p, &handle)) {
2356 ret = false;
2359 return ret;
2362 static bool call_OpenPrinterEx(struct torture_context *tctx,
2363 struct dcerpc_pipe *p,
2364 const char *name, struct policy_handle *handle)
2366 struct spoolss_OpenPrinterEx r;
2367 struct spoolss_UserLevel1 userlevel1;
2368 NTSTATUS status;
2370 if (name && name[0]) {
2371 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2372 dcerpc_server_name(p), name);
2373 } else {
2374 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2375 dcerpc_server_name(p));
2378 r.in.datatype = NULL;
2379 r.in.devmode_ctr.devmode= NULL;
2380 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2381 r.in.level = 1;
2382 r.in.userlevel.level1 = &userlevel1;
2383 r.out.handle = handle;
2385 userlevel1.size = 1234;
2386 userlevel1.client = "hello";
2387 userlevel1.user = "spottyfoot!";
2388 userlevel1.build = 1;
2389 userlevel1.major = 2;
2390 userlevel1.minor = 3;
2391 userlevel1.processor = 4;
2393 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2395 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2397 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2399 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2401 return true;
2404 static bool test_OpenPrinterEx(struct torture_context *tctx,
2405 struct dcerpc_pipe *p,
2406 const char *name)
2408 struct policy_handle handle;
2409 bool ret = true;
2411 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2412 return false;
2415 if (!test_GetPrinter(tctx, p, &handle)) {
2416 ret = false;
2419 if (!test_EnumForms(tctx, p, &handle, false)) {
2420 ret = false;
2423 if (!test_AddForm(tctx, p, &handle, false)) {
2424 ret = false;
2427 if (!test_EnumPrinterData(tctx, p, &handle)) {
2428 ret = false;
2431 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
2432 ret = false;
2435 if (!test_PausePrinter(tctx, p, &handle)) {
2436 ret = false;
2439 if (!test_DoPrintTest(tctx, p, &handle)) {
2440 ret = false;
2443 if (!test_ResumePrinter(tctx, p, &handle)) {
2444 ret = false;
2447 if (!test_SetPrinterData(tctx, p, &handle)) {
2448 ret = false;
2451 if (!torture_setting_bool(tctx, "samba3", false)) {
2452 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2453 ret = false;
2457 if (!test_ClosePrinter(tctx, p, &handle)) {
2458 ret = false;
2461 return ret;
2464 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2466 struct spoolss_EnumPrinters r;
2467 NTSTATUS status;
2468 uint16_t levels[] = {1, 2, 4, 5};
2469 int i;
2470 bool ret = true;
2472 for (i=0;i<ARRAY_SIZE(levels);i++) {
2473 union spoolss_PrinterInfo *info;
2474 int j;
2475 uint32_t needed;
2476 uint32_t count;
2478 r.in.flags = PRINTER_ENUM_LOCAL;
2479 r.in.server = "";
2480 r.in.level = levels[i];
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2484 r.out.count = &count;
2485 r.out.info = &info;
2487 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2489 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2490 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2492 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2493 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2494 data_blob_clear(&blob);
2495 r.in.buffer = &blob;
2496 r.in.offered = needed;
2497 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2500 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2502 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2504 if (!info) {
2505 torture_comment(tctx, "No printers returned\n");
2506 return true;
2509 for (j=0;j<count;j++) {
2510 if (r.in.level == 1) {
2511 char *unc = talloc_strdup(tctx, info[j].info1.name);
2512 char *slash, *name;
2513 name = unc;
2514 if (unc[0] == '\\' && unc[1] == '\\') {
2515 unc +=2;
2517 slash = strchr(unc, '\\');
2518 if (slash) {
2519 slash++;
2520 name = slash;
2522 if (!test_OpenPrinter(tctx, p, name)) {
2523 ret = false;
2525 if (!test_OpenPrinterEx(tctx, p, name)) {
2526 ret = false;
2532 return ret;
2535 #if 0
2536 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
2537 struct policy_handle *handle,
2538 const char *driver_name)
2540 NTSTATUS status;
2541 struct spoolss_GetPrinterDriver2 r;
2542 uint32_t needed;
2543 uint32_t server_major_version;
2544 uint32_t server_minor_version;
2546 r.in.handle = handle;
2547 r.in.architecture = "W32X86";
2548 r.in.level = 1;
2549 r.in.buffer = NULL;
2550 r.in.offered = 0;
2551 r.in.client_major_version = 0;
2552 r.in.client_minor_version = 0;
2553 r.out.needed = &needed;
2554 r.out.server_major_version = &server_major_version;
2555 r.out.server_minor_version = &server_minor_version;
2557 printf("Testing GetPrinterDriver2\n");
2559 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
2562 return false;
2565 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2566 r.in.offered = needed;
2567 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 printf("GetPrinterDriver2 failed - %s\n",
2572 nt_errstr(status));
2573 return false;
2576 if (!W_ERROR_IS_OK(r.out.result)) {
2577 printf("GetPrinterDriver2 failed - %s\n",
2578 win_errstr(r.out.result));
2579 return false;
2582 return true;
2584 #endif
2586 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2587 struct dcerpc_pipe *p)
2589 struct spoolss_EnumPrinterDrivers r;
2590 NTSTATUS status;
2591 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2592 int i;
2594 for (i=0;i<ARRAY_SIZE(levels);i++) {
2596 uint32_t needed;
2597 uint32_t count;
2598 union spoolss_DriverInfo *info;
2600 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2601 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2602 r.in.level = levels[i];
2603 r.in.buffer = NULL;
2604 r.in.offered = 0;
2605 r.out.needed = &needed;
2606 r.out.count = &count;
2607 r.out.info = &info;
2609 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2611 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2613 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2615 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2616 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2617 data_blob_clear(&blob);
2618 r.in.buffer = &blob;
2619 r.in.offered = needed;
2620 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2623 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2625 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2627 if (!info) {
2628 torture_comment(tctx, "No printer drivers returned\n");
2629 break;
2633 return true;
2636 bool torture_rpc_spoolss(struct torture_context *torture)
2638 NTSTATUS status;
2639 struct dcerpc_pipe *p;
2640 bool ret = true;
2641 struct test_spoolss_context *ctx;
2643 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 return false;
2648 ctx = talloc_zero(torture, struct test_spoolss_context);
2650 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
2652 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2653 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2654 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2655 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2656 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2657 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2658 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2659 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2660 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2661 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2662 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2663 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2664 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2665 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2666 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2667 ret &= test_EnumPorts(torture, p, ctx);
2668 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2669 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2670 ret &= test_EnumPrinterDrivers(torture, p, ctx);
2671 ret &= test_EnumMonitors(torture, p, ctx);
2672 ret &= test_EnumPrintProcessors(torture, p, ctx);
2673 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2674 ret &= test_EnumPrinters(torture, p, ctx);
2675 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2676 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2677 ret &= test_OpenPrinter_badname(torture, p, "");
2678 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2679 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2680 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2681 ret &= test_OpenPrinter_badname(torture, p,
2682 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2685 ret &= test_AddPort(torture, p);
2686 ret &= test_EnumPorts_old(torture, p);
2687 ret &= test_EnumPrinters_old(torture, p);
2688 ret &= test_EnumPrinterDrivers_old(torture, p);
2690 return ret;