s4-smbtorture: fix RPC-SPOOLSS after _spoolss_SetPrinterDataEx IDL change.
[Samba.git] / source4 / torture / rpc / spoolss.c
blob24c0f465d0e8011d7181a17e8304777b996d85b0
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Stefan Metzmacher 2005
7 Copyright (C) Jelmer Vernooij 2007
8 Copyright (C) Guenther Deschner 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "param/param.h"
31 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
32 #define TORTURE_PRINTER "torture_printer"
33 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
34 #define TORTURE_PRINTER_EX "torture_printer_ex"
36 struct test_spoolss_context {
37 /* print server handle */
38 struct policy_handle server_handle;
40 /* for EnumPorts */
41 uint32_t port_count[3];
42 union spoolss_PortInfo *ports[3];
44 /* for EnumPrinterDrivers */
45 uint32_t driver_count[7];
46 union spoolss_DriverInfo *drivers[7];
48 /* for EnumMonitors */
49 uint32_t monitor_count[3];
50 union spoolss_MonitorInfo *monitors[3];
52 /* for EnumPrintProcessors */
53 uint32_t print_processor_count[2];
54 union spoolss_PrintProcessorInfo *print_processors[2];
56 /* for EnumPrinters */
57 uint32_t printer_count[6];
58 union spoolss_PrinterInfo *printers[6];
61 #define COMPARE_STRING(tctx, c,r,e) \
62 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
64 /* not every compiler supports __typeof__() */
65 #if (__GNUC__ >= 3)
66 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
67 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
68 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
70 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
71 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
73 } while(0)
74 #else
75 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
76 #endif
78 #define COMPARE_UINT32(tctx, c, r, e) do {\
79 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
80 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
81 } while(0)
83 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
85 static bool test_OpenPrinter_server(struct torture_context *tctx,
86 struct dcerpc_pipe *p,
87 struct policy_handle *server_handle)
89 NTSTATUS status;
90 struct spoolss_OpenPrinter op;
92 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
93 op.in.datatype = NULL;
94 op.in.devmode_ctr.devmode= NULL;
95 op.in.access_mask = 0;
96 op.out.handle = server_handle;
98 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
100 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
101 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
102 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
104 return true;
107 static bool test_EnumPorts(struct torture_context *tctx,
108 struct dcerpc_pipe *p,
109 struct test_spoolss_context *ctx)
111 NTSTATUS status;
112 struct spoolss_EnumPorts r;
113 uint16_t levels[] = { 1, 2 };
114 int i, j;
116 for (i=0;i<ARRAY_SIZE(levels);i++) {
117 int level = levels[i];
118 DATA_BLOB blob;
119 uint32_t needed;
120 uint32_t count;
121 union spoolss_PortInfo *info;
123 r.in.servername = "";
124 r.in.level = level;
125 r.in.buffer = NULL;
126 r.in.offered = 0;
127 r.out.needed = &needed;
128 r.out.count = &count;
129 r.out.info = &info;
131 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
133 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
134 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
135 if (W_ERROR_IS_OK(r.out.result)) {
136 /* TODO: do some more checks here */
137 continue;
139 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
140 "EnumPorts unexpected return code");
142 blob = data_blob_talloc(ctx, NULL, needed);
143 data_blob_clear(&blob);
144 r.in.buffer = &blob;
145 r.in.offered = needed;
147 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
148 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
150 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
152 torture_assert(tctx, info, "EnumPorts returned no info");
154 ctx->port_count[level] = count;
155 ctx->ports[level] = info;
158 for (i=1;i<ARRAY_SIZE(levels);i++) {
159 int level = levels[i];
160 int old_level = levels[i-1];
161 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
162 "EnumPorts invalid value");
164 /* if the array sizes are not the same we would maybe segfault in the following code */
166 for (i=0;i<ARRAY_SIZE(levels);i++) {
167 int level = levels[i];
168 for (j=0;j<ctx->port_count[level];j++) {
169 union spoolss_PortInfo *cur = &ctx->ports[level][j];
170 union spoolss_PortInfo *ref = &ctx->ports[2][j];
171 switch (level) {
172 case 1:
173 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
174 break;
175 case 2:
176 /* level 2 is our reference, and it makes no sense to compare it to itself */
177 break;
182 return true;
185 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
186 struct dcerpc_pipe *p,
187 struct test_spoolss_context *ctx)
189 NTSTATUS status;
190 struct spoolss_GetPrintProcessorDirectory r;
191 struct {
192 uint16_t level;
193 const char *server;
194 } levels[] = {{
195 .level = 1,
196 .server = NULL
198 .level = 1,
199 .server = ""
201 .level = 78,
202 .server = ""
204 .level = 1,
205 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
207 .level = 1024,
208 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
211 int i;
212 uint32_t needed;
214 for (i=0;i<ARRAY_SIZE(levels);i++) {
215 int level = levels[i].level;
216 DATA_BLOB blob;
218 r.in.server = levels[i].server;
219 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
220 r.in.level = level;
221 r.in.buffer = NULL;
222 r.in.offered = 0;
223 r.out.needed = &needed;
225 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
227 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
228 torture_assert_ntstatus_ok(tctx, status,
229 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
230 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
231 "GetPrintProcessorDirectory unexpected return code");
233 blob = data_blob_talloc(ctx, NULL, needed);
234 data_blob_clear(&blob);
235 r.in.buffer = &blob;
236 r.in.offered = needed;
238 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
239 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
241 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
244 return true;
248 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
249 struct dcerpc_pipe *p,
250 struct test_spoolss_context *ctx)
252 NTSTATUS status;
253 struct spoolss_GetPrinterDriverDirectory r;
254 struct {
255 uint16_t level;
256 const char *server;
257 } levels[] = {{
258 .level = 1,
259 .server = NULL
261 .level = 1,
262 .server = ""
264 .level = 78,
265 .server = ""
267 .level = 1,
268 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
270 .level = 1024,
271 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
274 int i;
275 uint32_t needed;
277 for (i=0;i<ARRAY_SIZE(levels);i++) {
278 int level = levels[i].level;
279 DATA_BLOB blob;
281 r.in.server = levels[i].server;
282 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
283 r.in.level = level;
284 r.in.buffer = NULL;
285 r.in.offered = 0;
286 r.out.needed = &needed;
288 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
290 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
291 torture_assert_ntstatus_ok(tctx, status,
292 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
293 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
294 "GetPrinterDriverDirectory unexpected return code");
296 blob = data_blob_talloc(ctx, NULL, needed);
297 data_blob_clear(&blob);
298 r.in.buffer = &blob;
299 r.in.offered = needed;
301 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
302 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
304 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
307 return true;
310 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
311 struct dcerpc_pipe *p,
312 struct test_spoolss_context *ctx,
313 const char *architecture)
315 NTSTATUS status;
316 struct spoolss_EnumPrinterDrivers r;
317 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
318 int i, j;
320 for (i=0;i<ARRAY_SIZE(levels);i++) {
321 int level = levels[i];
322 DATA_BLOB blob;
323 uint32_t needed;
324 uint32_t count;
325 union spoolss_DriverInfo *info;
327 /* FIXME: gd, come back and fix "" as server, and handle
328 * priority of returned error codes in torture test and samba 3
329 * server */
331 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
332 r.in.environment = architecture;
333 r.in.level = level;
334 r.in.buffer = NULL;
335 r.in.offered = 0;
336 r.out.needed = &needed;
337 r.out.count = &count;
338 r.out.info = &info;
340 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
342 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
343 torture_assert_ntstatus_ok(tctx, status,
344 "dcerpc_spoolss_EnumPrinterDrivers failed");
345 if (W_ERROR_IS_OK(r.out.result)) {
346 /* TODO: do some more checks here */
347 continue;
349 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
350 blob = data_blob_talloc(ctx, NULL, needed);
351 data_blob_clear(&blob);
352 r.in.buffer = &blob;
353 r.in.offered = needed;
355 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
356 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
359 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
361 ctx->driver_count[level] = count;
362 ctx->drivers[level] = info;
365 for (i=1;i<ARRAY_SIZE(levels);i++) {
366 int level = levels[i];
367 int old_level = levels[i-1];
369 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
370 "EnumPrinterDrivers invalid value");
373 for (i=0;i<ARRAY_SIZE(levels);i++) {
374 int level = levels[i];
376 for (j=0;j<ctx->driver_count[level];j++) {
377 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
378 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
379 switch (level) {
380 case 1:
381 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
382 break;
383 case 2:
384 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
385 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
386 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
387 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
388 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
389 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
390 break;
391 case 3:
392 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
393 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
394 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
395 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
396 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
397 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
398 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
399 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
400 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
401 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
402 break;
403 case 4:
404 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
405 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
406 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
407 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
408 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
409 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
410 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
411 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
412 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
413 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
414 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
415 break;
416 case 5:
417 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
418 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
419 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
420 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
421 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
422 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
423 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
424 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
425 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
426 break;
427 case 6:
428 /* level 6 is our reference, and it makes no sense to compare it to itself */
429 break;
434 return true;
437 static bool test_EnumMonitors(struct torture_context *tctx,
438 struct dcerpc_pipe *p,
439 struct test_spoolss_context *ctx)
441 NTSTATUS status;
442 struct spoolss_EnumMonitors r;
443 uint16_t levels[] = { 1, 2 };
444 int i, j;
446 for (i=0;i<ARRAY_SIZE(levels);i++) {
447 int level = levels[i];
448 DATA_BLOB blob;
449 uint32_t needed;
450 uint32_t count;
451 union spoolss_MonitorInfo *info;
453 r.in.servername = "";
454 r.in.level = level;
455 r.in.buffer = NULL;
456 r.in.offered = 0;
457 r.out.needed = &needed;
458 r.out.count = &count;
459 r.out.info = &info;
461 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
463 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
464 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
465 if (W_ERROR_IS_OK(r.out.result)) {
466 /* TODO: do some more checks here */
467 continue;
469 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
470 "EnumMonitors failed");
472 blob = data_blob_talloc(ctx, NULL, needed);
473 data_blob_clear(&blob);
474 r.in.buffer = &blob;
475 r.in.offered = needed;
477 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
478 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
480 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
482 ctx->monitor_count[level] = count;
483 ctx->monitors[level] = info;
486 for (i=1;i<ARRAY_SIZE(levels);i++) {
487 int level = levels[i];
488 int old_level = levels[i-1];
489 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
490 "EnumMonitors invalid value");
493 for (i=0;i<ARRAY_SIZE(levels);i++) {
494 int level = levels[i];
495 for (j=0;j<ctx->monitor_count[level];j++) {
496 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
497 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
498 switch (level) {
499 case 1:
500 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
501 break;
502 case 2:
503 /* level 2 is our reference, and it makes no sense to compare it to itself */
504 break;
509 return true;
512 static bool test_EnumPrintProcessors(struct torture_context *tctx,
513 struct dcerpc_pipe *p,
514 struct test_spoolss_context *ctx)
516 NTSTATUS status;
517 struct spoolss_EnumPrintProcessors r;
518 uint16_t levels[] = { 1 };
519 int i, j;
521 for (i=0;i<ARRAY_SIZE(levels);i++) {
522 int level = levels[i];
523 DATA_BLOB blob;
524 uint32_t needed;
525 uint32_t count;
526 union spoolss_PrintProcessorInfo *info;
528 r.in.servername = "";
529 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
530 r.in.level = level;
531 r.in.buffer = NULL;
532 r.in.offered = 0;
533 r.out.needed = &needed;
534 r.out.count = &count;
535 r.out.info = &info;
537 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
539 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
540 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
541 if (W_ERROR_IS_OK(r.out.result)) {
542 /* TODO: do some more checks here */
543 continue;
545 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
546 "EnumPrintProcessors unexpected return code");
548 blob = data_blob_talloc(ctx, NULL, needed);
549 data_blob_clear(&blob);
550 r.in.buffer = &blob;
551 r.in.offered = needed;
553 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
554 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
556 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
558 ctx->print_processor_count[level] = count;
559 ctx->print_processors[level] = info;
562 for (i=1;i<ARRAY_SIZE(levels);i++) {
563 int level = levels[i];
564 int old_level = levels[i-1];
565 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
566 "EnumPrintProcessors failed");
569 for (i=0;i<ARRAY_SIZE(levels);i++) {
570 int level = levels[i];
571 for (j=0;j<ctx->print_processor_count[level];j++) {
572 #if 0
573 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
574 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
575 #endif
576 switch (level) {
577 case 1:
578 /* level 1 is our reference, and it makes no sense to compare it to itself */
579 break;
584 return true;
587 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
588 struct dcerpc_pipe *p,
589 struct test_spoolss_context *ctx)
591 NTSTATUS status;
592 struct spoolss_EnumPrintProcDataTypes r;
593 uint16_t levels[] = { 1 };
594 int i;
596 for (i=0;i<ARRAY_SIZE(levels);i++) {
597 int level = levels[i];
598 DATA_BLOB blob;
599 uint32_t needed;
600 uint32_t count;
601 union spoolss_PrintProcDataTypesInfo *info;
603 r.in.servername = "";
604 r.in.print_processor_name = "winprint";
605 r.in.level = level;
606 r.in.buffer = NULL;
607 r.in.offered = 0;
608 r.out.needed = &needed;
609 r.out.count = &count;
610 r.out.info = &info;
612 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
614 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
615 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
616 if (W_ERROR_IS_OK(r.out.result)) {
617 /* TODO: do some more checks here */
618 continue;
620 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
621 "EnumPrintProcDataTypes unexpected return code");
623 blob = data_blob_talloc(ctx, NULL, needed);
624 data_blob_clear(&blob);
625 r.in.buffer = &blob;
626 r.in.offered = needed;
628 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
629 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
631 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
634 return true;
638 static bool test_EnumPrinters(struct torture_context *tctx,
639 struct dcerpc_pipe *p,
640 struct test_spoolss_context *ctx)
642 struct spoolss_EnumPrinters r;
643 NTSTATUS status;
644 uint16_t levels[] = { 0, 1, 2, 4, 5 };
645 int i, j;
647 for (i=0;i<ARRAY_SIZE(levels);i++) {
648 int level = levels[i];
649 DATA_BLOB blob;
650 uint32_t needed;
651 uint32_t count;
652 union spoolss_PrinterInfo *info;
654 r.in.flags = PRINTER_ENUM_LOCAL;
655 r.in.server = "";
656 r.in.level = level;
657 r.in.buffer = NULL;
658 r.in.offered = 0;
659 r.out.needed = &needed;
660 r.out.count = &count;
661 r.out.info = &info;
663 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
665 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
666 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
667 if (W_ERROR_IS_OK(r.out.result)) {
668 /* TODO: do some more checks here */
669 continue;
671 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
672 "EnumPrinters unexpected return code");
674 blob = data_blob_talloc(ctx, NULL, needed);
675 data_blob_clear(&blob);
676 r.in.buffer = &blob;
677 r.in.offered = needed;
679 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
680 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
682 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
684 ctx->printer_count[level] = count;
685 ctx->printers[level] = info;
688 for (i=1;i<ARRAY_SIZE(levels);i++) {
689 int level = levels[i];
690 int old_level = levels[i-1];
691 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
692 "EnumPrinters invalid value");
695 for (i=0;i<ARRAY_SIZE(levels);i++) {
696 int level = levels[i];
697 for (j=0;j<ctx->printer_count[level];j++) {
698 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
699 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
700 switch (level) {
701 case 0:
702 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
703 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
704 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
705 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
706 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
707 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
708 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
709 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
710 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
711 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
712 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
713 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
714 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
715 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
716 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
718 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
719 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
720 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
721 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
723 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
724 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
725 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
726 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
727 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
731 break;
732 case 1:
733 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
734 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
735 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
736 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
737 break;
738 case 2:
739 /* level 2 is our reference, and it makes no sense to compare it to itself */
740 break;
741 case 4:
742 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
743 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
744 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
745 break;
746 case 5:
747 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
748 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
749 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
750 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
751 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
752 break;
757 /* TODO:
758 * - verify that the port of a printer was in the list returned by EnumPorts
761 return true;
764 static bool test_GetPrinter(struct torture_context *tctx,
765 struct dcerpc_pipe *p,
766 struct policy_handle *handle)
768 NTSTATUS status;
769 struct spoolss_GetPrinter r;
770 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
771 int i;
772 uint32_t needed;
774 for (i=0;i<ARRAY_SIZE(levels);i++) {
775 r.in.handle = handle;
776 r.in.level = levels[i];
777 r.in.buffer = NULL;
778 r.in.offered = 0;
779 r.out.needed = &needed;
781 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
783 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
784 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
786 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
787 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
788 data_blob_clear(&blob);
789 r.in.buffer = &blob;
790 r.in.offered = needed;
791 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
794 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
796 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
799 return true;
802 static bool test_SetPrinter_errors(struct torture_context *tctx,
803 struct dcerpc_pipe *p,
804 struct policy_handle *handle)
806 struct spoolss_SetPrinter r;
807 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
808 int i;
810 struct spoolss_SetPrinterInfoCtr info_ctr;
811 struct spoolss_DevmodeContainer devmode_ctr;
812 struct sec_desc_buf secdesc_ctr;
814 info_ctr.level = 0;
815 info_ctr.info.info0 = NULL;
817 ZERO_STRUCT(devmode_ctr);
818 ZERO_STRUCT(secdesc_ctr);
820 r.in.handle = handle;
821 r.in.info_ctr = &info_ctr;
822 r.in.devmode_ctr = &devmode_ctr;
823 r.in.secdesc_ctr = &secdesc_ctr;
824 r.in.command = 0;
826 torture_comment(tctx, "Testing SetPrinter all zero\n");
828 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
829 "failed to call SetPrinter");
830 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
831 "failed to call SetPrinter");
833 again:
834 for (i=0; i < ARRAY_SIZE(levels); i++) {
836 struct spoolss_SetPrinterInfo0 info0;
837 struct spoolss_SetPrinterInfo1 info1;
838 struct spoolss_SetPrinterInfo2 info2;
839 struct spoolss_SetPrinterInfo3 info3;
840 struct spoolss_SetPrinterInfo4 info4;
841 struct spoolss_SetPrinterInfo5 info5;
842 struct spoolss_SetPrinterInfo6 info6;
843 struct spoolss_SetPrinterInfo7 info7;
844 struct spoolss_DeviceModeInfo info8;
845 struct spoolss_DeviceModeInfo info9;
848 info_ctr.level = levels[i];
849 switch (levels[i]) {
850 case 0:
851 ZERO_STRUCT(info0);
852 info_ctr.info.info0 = &info0;
853 break;
854 case 1:
855 ZERO_STRUCT(info1);
856 info_ctr.info.info1 = &info1;
857 break;
858 case 2:
859 ZERO_STRUCT(info2);
860 info_ctr.info.info2 = &info2;
861 break;
862 case 3:
863 ZERO_STRUCT(info3);
864 info_ctr.info.info3 = &info3;
865 break;
866 case 4:
867 ZERO_STRUCT(info4);
868 info_ctr.info.info4 = &info4;
869 break;
870 case 5:
871 ZERO_STRUCT(info5);
872 info_ctr.info.info5 = &info5;
873 break;
874 case 6:
875 ZERO_STRUCT(info6);
876 info_ctr.info.info6 = &info6;
877 break;
878 case 7:
879 ZERO_STRUCT(info7);
880 info_ctr.info.info7 = &info7;
881 break;
882 case 8:
883 ZERO_STRUCT(info8);
884 info_ctr.info.info8 = &info8;
885 break;
886 case 9:
887 ZERO_STRUCT(info9);
888 info_ctr.info.info9 = &info9;
889 break;
892 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
893 info_ctr.level, r.in.command);
895 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
896 "failed to call SetPrinter");
898 switch (r.in.command) {
899 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
900 /* is ignored for all levels other then 0 */
901 if (info_ctr.level > 0) {
902 /* ignored then */
903 break;
905 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
906 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
907 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
908 if (info_ctr.level > 0) {
909 /* is invalid for all levels other then 0 */
910 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
911 "unexpected error code returned");
912 continue;
913 } else {
914 torture_assert_werr_ok(tctx, r.out.result,
915 "failed to call SetPrinter with non 0 command");
916 continue;
918 break;
920 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
921 /* FIXME: gd needs further investigation */
922 default:
923 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
924 "unexpected error code returned");
925 continue;
928 switch (info_ctr.level) {
929 case 1:
930 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
931 "unexpected error code returned");
932 break;
933 case 2:
934 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
935 "unexpected error code returned");
936 break;
937 case 3:
938 case 4:
939 case 5:
940 case 7:
941 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
942 "unexpected error code returned");
943 break;
944 case 9:
945 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
946 "unexpected error code returned");
947 break;
948 default:
949 torture_assert_werr_ok(tctx, r.out.result,
950 "failed to call SetPrinter");
951 break;
955 if (r.in.command < 5) {
956 r.in.command++;
957 goto again;
960 return true;
963 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
965 if ((r->level == 2) && (r->info.info2)) {
966 r->info.info2->secdesc = NULL;
967 r->info.info2->devmode = NULL;
971 static bool test_PrinterInfo(struct torture_context *tctx,
972 struct dcerpc_pipe *p,
973 struct policy_handle *handle)
975 NTSTATUS status;
976 struct spoolss_SetPrinter s;
977 struct spoolss_GetPrinter q;
978 struct spoolss_GetPrinter q0;
979 struct spoolss_SetPrinterInfoCtr info_ctr;
980 union spoolss_PrinterInfo info;
981 struct spoolss_DevmodeContainer devmode_ctr;
982 struct sec_desc_buf secdesc_ctr;
983 uint32_t needed;
984 bool ret = true;
985 int i;
987 uint32_t status_list[] = {
988 /* these do not stick
989 PRINTER_STATUS_PAUSED,
990 PRINTER_STATUS_ERROR,
991 PRINTER_STATUS_PENDING_DELETION, */
992 PRINTER_STATUS_PAPER_JAM,
993 PRINTER_STATUS_PAPER_OUT,
994 PRINTER_STATUS_MANUAL_FEED,
995 PRINTER_STATUS_PAPER_PROBLEM,
996 PRINTER_STATUS_OFFLINE,
997 PRINTER_STATUS_IO_ACTIVE,
998 PRINTER_STATUS_BUSY,
999 PRINTER_STATUS_PRINTING,
1000 PRINTER_STATUS_OUTPUT_BIN_FULL,
1001 PRINTER_STATUS_NOT_AVAILABLE,
1002 PRINTER_STATUS_WAITING,
1003 PRINTER_STATUS_PROCESSING,
1004 PRINTER_STATUS_INITIALIZING,
1005 PRINTER_STATUS_WARMING_UP,
1006 PRINTER_STATUS_TONER_LOW,
1007 PRINTER_STATUS_NO_TONER,
1008 PRINTER_STATUS_PAGE_PUNT,
1009 PRINTER_STATUS_USER_INTERVENTION,
1010 PRINTER_STATUS_OUT_OF_MEMORY,
1011 PRINTER_STATUS_DOOR_OPEN,
1012 PRINTER_STATUS_SERVER_UNKNOWN,
1013 PRINTER_STATUS_POWER_SAVE,
1014 /* these do not stick
1015 0x02000000,
1016 0x04000000,
1017 0x08000000,
1018 0x10000000,
1019 0x20000000,
1020 0x40000000,
1021 0x80000000 */
1023 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1024 uint32_t attribute_list[] = {
1025 PRINTER_ATTRIBUTE_QUEUED,
1026 /* fails with WERR_INVALID_DATATYPE:
1027 PRINTER_ATTRIBUTE_DIRECT, */
1028 /* does not stick
1029 PRINTER_ATTRIBUTE_DEFAULT, */
1030 PRINTER_ATTRIBUTE_SHARED,
1031 /* does not stick
1032 PRINTER_ATTRIBUTE_NETWORK, */
1033 PRINTER_ATTRIBUTE_HIDDEN,
1034 PRINTER_ATTRIBUTE_LOCAL,
1035 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1036 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1037 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1038 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1039 /* does not stick
1040 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1041 /* fails with WERR_INVALID_DATATYPE:
1042 PRINTER_ATTRIBUTE_RAW_ONLY, */
1043 /* these do not stick
1044 PRINTER_ATTRIBUTE_PUBLISHED,
1045 PRINTER_ATTRIBUTE_FAX,
1046 PRINTER_ATTRIBUTE_TS,
1047 0x00010000,
1048 0x00020000,
1049 0x00040000,
1050 0x00080000,
1051 0x00100000,
1052 0x00200000,
1053 0x00400000,
1054 0x00800000,
1055 0x01000000,
1056 0x02000000,
1057 0x04000000,
1058 0x08000000,
1059 0x10000000,
1060 0x20000000,
1061 0x40000000,
1062 0x80000000 */
1065 ZERO_STRUCT(devmode_ctr);
1066 ZERO_STRUCT(secdesc_ctr);
1068 s.in.handle = handle;
1069 s.in.command = 0;
1070 s.in.info_ctr = &info_ctr;
1071 s.in.devmode_ctr = &devmode_ctr;
1072 s.in.secdesc_ctr = &secdesc_ctr;
1074 q.in.handle = handle;
1075 q.out.info = &info;
1076 q0 = q;
1078 #define TESTGETCALL(call, r) \
1079 r.in.buffer = NULL; \
1080 r.in.offered = 0;\
1081 r.out.needed = &needed; \
1082 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1083 if (!NT_STATUS_IS_OK(status)) { \
1084 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1085 r.in.level, nt_errstr(status), __location__); \
1086 ret = false; \
1087 break; \
1089 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1090 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1091 data_blob_clear(&blob); \
1092 r.in.buffer = &blob; \
1093 r.in.offered = 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_IS_OK(r.out.result)) { \
1103 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1104 r.in.level, win_errstr(r.out.result), __location__); \
1105 ret = false; \
1106 break; \
1110 #define TESTSETCALL_EXP(call, r, err) \
1111 clear_info2(&info_ctr);\
1112 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1113 if (!NT_STATUS_IS_OK(status)) { \
1114 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1115 r.in.info_ctr->level, nt_errstr(status), __location__); \
1116 ret = false; \
1117 break; \
1119 if (!W_ERROR_IS_OK(err)) { \
1120 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1121 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1122 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1123 ret = false; \
1125 break; \
1127 if (!W_ERROR_IS_OK(r.out.result)) { \
1128 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1129 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1130 ret = false; \
1131 break; \
1134 #define TESTSETCALL(call, r) \
1135 TESTSETCALL_EXP(call, r, WERR_OK)
1137 #define STRING_EQUAL(s1, s2, field) \
1138 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1139 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1140 #field, s2, __location__); \
1141 ret = false; \
1142 break; \
1145 #define MEM_EQUAL(s1, s2, length, field) \
1146 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1147 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1148 #field, (const char *)s2, __location__); \
1149 ret = false; \
1150 break; \
1153 #define INT_EQUAL(i1, i2, field) \
1154 if (i1 != i2) { \
1155 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1156 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1157 ret = false; \
1158 break; \
1161 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1162 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1163 q.in.level = lvl1; \
1164 TESTGETCALL(GetPrinter, q) \
1165 info_ctr.level = lvl1; \
1166 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1167 info_ctr.info.info ## lvl1->field1 = value;\
1168 TESTSETCALL_EXP(SetPrinter, s, err) \
1169 info_ctr.info.info ## lvl1->field1 = ""; \
1170 TESTGETCALL(GetPrinter, q) \
1171 info_ctr.info.info ## lvl1->field1 = value; \
1172 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1173 q.in.level = lvl2; \
1174 TESTGETCALL(GetPrinter, q) \
1175 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1176 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1177 } while (0)
1179 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1180 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1181 } while (0);
1183 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1184 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1185 q.in.level = lvl1; \
1186 TESTGETCALL(GetPrinter, q) \
1187 info_ctr.level = lvl1; \
1188 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1189 info_ctr.info.info ## lvl1->field1 = value; \
1190 TESTSETCALL(SetPrinter, s) \
1191 info_ctr.info.info ## lvl1->field1 = 0; \
1192 TESTGETCALL(GetPrinter, q) \
1193 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1194 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1195 q.in.level = lvl2; \
1196 TESTGETCALL(GetPrinter, q) \
1197 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1198 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1199 } while (0)
1201 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1202 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1203 } while (0)
1205 q0.in.level = 0;
1206 do { TESTGETCALL(GetPrinter, q0) } while (0);
1208 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1209 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1211 /* level 0 printername does not stick */
1212 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1213 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1214 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1215 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1216 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1217 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1218 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1219 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1220 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1221 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1222 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1223 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1224 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1225 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1226 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1228 /* servername can be set but does not stick
1229 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1230 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1231 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1234 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1235 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1236 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1237 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1238 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1240 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1241 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1242 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1243 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1244 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1245 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1246 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1247 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1248 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1249 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1251 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1252 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1253 attribute_list[i],
1254 (attribute_list[i] | default_attribute)
1255 ); */
1256 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1257 attribute_list[i],
1258 (attribute_list[i] | default_attribute)
1260 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1261 attribute_list[i],
1262 (attribute_list[i] | default_attribute)
1264 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1265 attribute_list[i],
1266 (attribute_list[i] | default_attribute)
1268 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1269 attribute_list[i],
1270 (attribute_list[i] | default_attribute)
1271 ); */
1272 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1273 attribute_list[i],
1274 (attribute_list[i] | default_attribute)
1276 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1277 attribute_list[i],
1278 (attribute_list[i] | default_attribute)
1280 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1281 attribute_list[i],
1282 (attribute_list[i] | default_attribute)
1284 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1285 attribute_list[i],
1286 (attribute_list[i] | default_attribute)
1287 ); */
1288 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1289 attribute_list[i],
1290 (attribute_list[i] | default_attribute)
1292 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1293 attribute_list[i],
1294 (attribute_list[i] | default_attribute)
1296 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1297 attribute_list[i],
1298 (attribute_list[i] | default_attribute)
1302 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1303 /* level 2 sets do not stick
1304 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1305 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1306 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1307 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1308 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1309 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1312 /* priorities need to be between 0 and 99
1313 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1314 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1315 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1316 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1317 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1318 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1319 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1320 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1321 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1323 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1324 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1326 /* does not stick
1327 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1328 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1330 /* does not stick
1331 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1332 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1334 /* FIXME: gd also test devmode and secdesc behavior */
1337 /* verify composition of level 1 description field */
1338 const char *description;
1339 const char *tmp;
1341 q0.in.level = 1;
1342 do { TESTGETCALL(GetPrinter, q0) } while (0);
1344 description = talloc_strdup(tctx, q0.out.info->info1.description);
1346 q0.in.level = 2;
1347 do { TESTGETCALL(GetPrinter, q0) } while (0);
1349 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1350 q0.out.info->info2.printername,
1351 q0.out.info->info2.drivername,
1352 q0.out.info->info2.location);
1354 do { STRING_EQUAL(description, tmp, "description")} while (0);
1357 return ret;
1361 static bool test_ClosePrinter(struct torture_context *tctx,
1362 struct dcerpc_pipe *p,
1363 struct policy_handle *handle)
1365 NTSTATUS status;
1366 struct spoolss_ClosePrinter r;
1368 r.in.handle = handle;
1369 r.out.handle = handle;
1371 torture_comment(tctx, "Testing ClosePrinter\n");
1373 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1374 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1375 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1377 return true;
1380 static bool test_GetForm(struct torture_context *tctx,
1381 struct dcerpc_pipe *p,
1382 struct policy_handle *handle,
1383 const char *form_name,
1384 uint32_t level)
1386 NTSTATUS status;
1387 struct spoolss_GetForm r;
1388 uint32_t needed;
1390 r.in.handle = handle;
1391 r.in.form_name = form_name;
1392 r.in.level = level;
1393 r.in.buffer = NULL;
1394 r.in.offered = 0;
1395 r.out.needed = &needed;
1397 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1399 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1400 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1402 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1403 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1404 data_blob_clear(&blob);
1405 r.in.buffer = &blob;
1406 r.in.offered = needed;
1407 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1408 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1410 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1412 torture_assert(tctx, r.out.info, "No form info returned");
1415 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1417 return true;
1420 static bool test_EnumForms(struct torture_context *tctx,
1421 struct dcerpc_pipe *p,
1422 struct policy_handle *handle, bool print_server)
1424 NTSTATUS status;
1425 struct spoolss_EnumForms r;
1426 bool ret = true;
1427 uint32_t needed;
1428 uint32_t count;
1429 uint32_t levels[] = { 1, 2 };
1430 int i;
1432 for (i=0; i<ARRAY_SIZE(levels); i++) {
1434 union spoolss_FormInfo *info;
1436 r.in.handle = handle;
1437 r.in.level = levels[i];
1438 r.in.buffer = NULL;
1439 r.in.offered = 0;
1440 r.out.needed = &needed;
1441 r.out.count = &count;
1442 r.out.info = &info;
1444 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1446 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1447 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1449 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1450 break;
1453 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1454 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1456 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1457 int j;
1458 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1459 data_blob_clear(&blob);
1460 r.in.buffer = &blob;
1461 r.in.offered = needed;
1463 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1465 torture_assert(tctx, info, "No forms returned");
1467 for (j = 0; j < count; j++) {
1468 if (!print_server)
1469 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1473 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1475 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1478 return true;
1481 static bool test_DeleteForm(struct torture_context *tctx,
1482 struct dcerpc_pipe *p,
1483 struct policy_handle *handle,
1484 const char *form_name)
1486 NTSTATUS status;
1487 struct spoolss_DeleteForm r;
1489 r.in.handle = handle;
1490 r.in.form_name = form_name;
1492 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1494 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1496 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1498 return true;
1501 static bool test_AddForm(struct torture_context *tctx,
1502 struct dcerpc_pipe *p,
1503 struct policy_handle *handle, bool print_server)
1505 struct spoolss_AddForm r;
1506 struct spoolss_AddFormInfo1 addform;
1507 const char *form_name = "testform3";
1508 NTSTATUS status;
1509 bool ret = true;
1511 r.in.handle = handle;
1512 r.in.level = 1;
1513 r.in.info.info1 = &addform;
1514 addform.flags = SPOOLSS_FORM_USER;
1515 addform.form_name = form_name;
1516 addform.size.width = 50;
1517 addform.size.height = 25;
1518 addform.area.left = 5;
1519 addform.area.top = 10;
1520 addform.area.right = 45;
1521 addform.area.bottom = 15;
1523 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1525 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1527 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1529 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1532 struct spoolss_SetForm sf;
1533 struct spoolss_AddFormInfo1 setform;
1535 sf.in.handle = handle;
1536 sf.in.form_name = form_name;
1537 sf.in.level = 1;
1538 sf.in.info.info1= &setform;
1539 setform.flags = addform.flags;
1540 setform.form_name = addform.form_name;
1541 setform.size = addform.size;
1542 setform.area = addform.area;
1544 setform.size.width = 1234;
1546 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1548 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1550 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1553 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1556 struct spoolss_EnumForms e;
1557 union spoolss_FormInfo *info;
1558 uint32_t needed;
1559 uint32_t count;
1560 bool found = false;
1562 e.in.handle = handle;
1563 e.in.level = 1;
1564 e.in.buffer = NULL;
1565 e.in.offered = 0;
1566 e.out.needed = &needed;
1567 e.out.count = &count;
1568 e.out.info = &info;
1570 torture_comment(tctx, "Testing EnumForms level 1\n");
1572 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1573 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1575 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1576 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1578 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1579 int j;
1580 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1581 data_blob_clear(&blob);
1582 e.in.buffer = &blob;
1583 e.in.offered = needed;
1585 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1587 torture_assert(tctx, info, "No forms returned");
1589 for (j = 0; j < count; j++) {
1590 if (strequal(form_name, info[j].info1.form_name)) {
1591 found = true;
1592 break;
1596 torture_assert(tctx, found, "Newly added form not found in enum call");
1599 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1600 ret = false;
1603 return ret;
1606 static bool test_EnumPorts_old(struct torture_context *tctx,
1607 struct dcerpc_pipe *p)
1609 NTSTATUS status;
1610 struct spoolss_EnumPorts r;
1611 uint32_t needed;
1612 uint32_t count;
1613 union spoolss_PortInfo *info;
1615 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1616 dcerpc_server_name(p));
1617 r.in.level = 2;
1618 r.in.buffer = NULL;
1619 r.in.offered = 0;
1620 r.out.needed = &needed;
1621 r.out.count = &count;
1622 r.out.info = &info;
1624 torture_comment(tctx, "Testing EnumPorts\n");
1626 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1628 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1630 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1631 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1632 data_blob_clear(&blob);
1633 r.in.buffer = &blob;
1634 r.in.offered = needed;
1636 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1637 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1638 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1640 torture_assert(tctx, info, "No ports returned");
1643 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1645 return true;
1648 static bool test_AddPort(struct torture_context *tctx,
1649 struct dcerpc_pipe *p)
1651 NTSTATUS status;
1652 struct spoolss_AddPort r;
1654 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1655 dcerpc_server_name(p));
1656 r.in.unknown = 0;
1657 r.in.monitor_name = "foo";
1659 torture_comment(tctx, "Testing AddPort\n");
1661 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1663 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1665 /* win2k3 returns WERR_NOT_SUPPORTED */
1667 #if 0
1669 if (!W_ERROR_IS_OK(r.out.result)) {
1670 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1671 return false;
1674 #endif
1676 return true;
1679 static bool test_GetJob(struct torture_context *tctx,
1680 struct dcerpc_pipe *p,
1681 struct policy_handle *handle, uint32_t job_id)
1683 NTSTATUS status;
1684 struct spoolss_GetJob r;
1685 union spoolss_JobInfo info;
1686 uint32_t needed;
1687 uint32_t levels[] = {1, 2 /* 3, 4 */};
1688 uint32_t i;
1690 r.in.handle = handle;
1691 r.in.job_id = job_id;
1692 r.in.level = 0;
1693 r.in.buffer = NULL;
1694 r.in.offered = 0;
1695 r.out.needed = &needed;
1696 r.out.info = &info;
1698 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1700 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1701 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1703 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1705 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1707 needed = 0;
1709 r.in.level = levels[i];
1710 r.in.offered = 0;
1711 r.in.buffer = NULL;
1713 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1714 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1716 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1717 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1718 data_blob_clear(&blob);
1719 r.in.buffer = &blob;
1720 r.in.offered = needed;
1722 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1723 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1726 torture_assert(tctx, r.out.info, "No job info returned");
1727 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1730 return true;
1733 static bool test_SetJob(struct torture_context *tctx,
1734 struct dcerpc_pipe *p,
1735 struct policy_handle *handle, uint32_t job_id,
1736 enum spoolss_JobControl command)
1738 NTSTATUS status;
1739 struct spoolss_SetJob r;
1741 r.in.handle = handle;
1742 r.in.job_id = job_id;
1743 r.in.ctr = NULL;
1744 r.in.command = command;
1746 switch (command) {
1747 case SPOOLSS_JOB_CONTROL_PAUSE:
1748 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1749 break;
1750 case SPOOLSS_JOB_CONTROL_RESUME:
1751 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1752 break;
1753 case SPOOLSS_JOB_CONTROL_CANCEL:
1754 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1755 break;
1756 case SPOOLSS_JOB_CONTROL_RESTART:
1757 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1758 break;
1759 case SPOOLSS_JOB_CONTROL_DELETE:
1760 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1761 break;
1762 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1763 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1764 break;
1765 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1766 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1767 break;
1768 case SPOOLSS_JOB_CONTROL_RETAIN:
1769 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1770 break;
1771 case SPOOLSS_JOB_CONTROL_RELEASE:
1772 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1773 break;
1774 default:
1775 torture_comment(tctx, "Testing SetJob\n");
1776 break;
1779 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1780 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1781 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1783 return true;
1786 static bool test_AddJob(struct torture_context *tctx,
1787 struct dcerpc_pipe *p,
1788 struct policy_handle *handle)
1790 NTSTATUS status;
1791 struct spoolss_AddJob r;
1792 uint32_t needed;
1794 r.in.level = 0;
1795 r.in.handle = handle;
1796 r.in.offered = 0;
1797 r.out.needed = &needed;
1798 r.in.buffer = r.out.buffer = NULL;
1800 torture_comment(tctx, "Testing AddJob\n");
1802 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1803 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1805 r.in.level = 1;
1807 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1808 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1810 return true;
1814 static bool test_EnumJobs(struct torture_context *tctx,
1815 struct dcerpc_pipe *p,
1816 struct policy_handle *handle)
1818 NTSTATUS status;
1819 struct spoolss_EnumJobs r;
1820 uint32_t needed;
1821 uint32_t count;
1822 union spoolss_JobInfo *info;
1824 r.in.handle = handle;
1825 r.in.firstjob = 0;
1826 r.in.numjobs = 0xffffffff;
1827 r.in.level = 1;
1828 r.in.buffer = NULL;
1829 r.in.offered = 0;
1830 r.out.needed = &needed;
1831 r.out.count = &count;
1832 r.out.info = &info;
1834 torture_comment(tctx, "Testing EnumJobs\n");
1836 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1838 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1840 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1841 int j;
1842 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1843 data_blob_clear(&blob);
1844 r.in.buffer = &blob;
1845 r.in.offered = needed;
1847 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1849 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1850 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1851 torture_assert(tctx, info, "No jobs returned");
1853 for (j = 0; j < count; j++) {
1855 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
1856 "failed to call test_GetJob");
1858 /* FIXME - gd */
1859 if (!torture_setting_bool(tctx, "samba3", false)) {
1860 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1861 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1865 } else {
1866 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1869 return true;
1872 static bool test_DoPrintTest(struct torture_context *tctx,
1873 struct dcerpc_pipe *p,
1874 struct policy_handle *handle)
1876 bool ret = true;
1877 NTSTATUS status;
1878 struct spoolss_StartDocPrinter s;
1879 struct spoolss_DocumentInfo1 info1;
1880 struct spoolss_StartPagePrinter sp;
1881 struct spoolss_WritePrinter w;
1882 struct spoolss_EndPagePrinter ep;
1883 struct spoolss_EndDocPrinter e;
1884 int i;
1885 uint32_t job_id;
1886 uint32_t num_written;
1888 torture_comment(tctx, "Testing StartDocPrinter\n");
1890 s.in.handle = handle;
1891 s.in.level = 1;
1892 s.in.info.info1 = &info1;
1893 s.out.job_id = &job_id;
1894 info1.document_name = "TorturePrintJob";
1895 info1.output_file = NULL;
1896 info1.datatype = "RAW";
1898 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1899 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1900 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1902 for (i=1; i < 4; i++) {
1903 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1905 sp.in.handle = handle;
1907 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1908 torture_assert_ntstatus_ok(tctx, status,
1909 "dcerpc_spoolss_StartPagePrinter failed");
1910 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1912 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1914 w.in.handle = handle;
1915 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1916 w.out.num_written = &num_written;
1918 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1919 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1920 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1922 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1924 ep.in.handle = handle;
1926 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1927 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1928 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1931 torture_comment(tctx, "Testing EndDocPrinter\n");
1933 e.in.handle = handle;
1935 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1936 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1937 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1939 ret &= test_AddJob(tctx, p, handle);
1940 ret &= test_EnumJobs(tctx, p, handle);
1942 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1944 return ret;
1947 static bool test_PausePrinter(struct torture_context *tctx,
1948 struct dcerpc_pipe *p,
1949 struct policy_handle *handle)
1951 NTSTATUS status;
1952 struct spoolss_SetPrinter r;
1953 struct spoolss_SetPrinterInfoCtr info_ctr;
1954 struct spoolss_DevmodeContainer devmode_ctr;
1955 struct sec_desc_buf secdesc_ctr;
1957 info_ctr.level = 0;
1958 info_ctr.info.info0 = NULL;
1960 ZERO_STRUCT(devmode_ctr);
1961 ZERO_STRUCT(secdesc_ctr);
1963 r.in.handle = handle;
1964 r.in.info_ctr = &info_ctr;
1965 r.in.devmode_ctr = &devmode_ctr;
1966 r.in.secdesc_ctr = &secdesc_ctr;
1967 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1969 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1971 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1973 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1975 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1977 return true;
1980 static bool test_ResumePrinter(struct torture_context *tctx,
1981 struct dcerpc_pipe *p,
1982 struct policy_handle *handle)
1984 NTSTATUS status;
1985 struct spoolss_SetPrinter r;
1986 struct spoolss_SetPrinterInfoCtr info_ctr;
1987 struct spoolss_DevmodeContainer devmode_ctr;
1988 struct sec_desc_buf secdesc_ctr;
1990 info_ctr.level = 0;
1991 info_ctr.info.info0 = NULL;
1993 ZERO_STRUCT(devmode_ctr);
1994 ZERO_STRUCT(secdesc_ctr);
1996 r.in.handle = handle;
1997 r.in.info_ctr = &info_ctr;
1998 r.in.devmode_ctr = &devmode_ctr;
1999 r.in.secdesc_ctr = &secdesc_ctr;
2000 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2002 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2004 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2006 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2008 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2010 return true;
2013 static bool test_GetPrinterData(struct torture_context *tctx,
2014 struct dcerpc_pipe *p,
2015 struct policy_handle *handle,
2016 const char *value_name,
2017 enum winreg_Type *type_p,
2018 union spoolss_PrinterData *data_p)
2020 NTSTATUS status;
2021 struct spoolss_GetPrinterData r;
2022 uint32_t needed;
2023 enum winreg_Type type;
2024 union spoolss_PrinterData data;
2026 r.in.handle = handle;
2027 r.in.value_name = value_name;
2028 r.in.offered = 0;
2029 r.out.needed = &needed;
2030 r.out.type = &type;
2031 r.out.data = &data;
2033 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2035 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2036 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2038 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2039 r.in.offered = needed;
2041 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2042 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2045 torture_assert_werr_ok(tctx, r.out.result,
2046 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2048 if (type_p) {
2049 *type_p = type;
2052 if (data_p) {
2053 *data_p = data;
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,
2064 enum winreg_Type *type_p,
2065 union spoolss_PrinterData *data_p)
2067 NTSTATUS status;
2068 struct spoolss_GetPrinterDataEx r;
2069 enum winreg_Type type;
2070 uint32_t needed;
2071 union spoolss_PrinterData data;
2073 r.in.handle = handle;
2074 r.in.key_name = key_name;
2075 r.in.value_name = value_name;
2076 r.in.offered = 0;
2077 r.out.type = &type;
2078 r.out.needed = &needed;
2079 r.out.data = &data;
2081 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2082 r.in.key_name, r.in.value_name);
2084 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2087 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2088 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2090 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2093 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2094 r.in.offered = needed;
2095 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2096 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2099 torture_assert_werr_ok(tctx, r.out.result,
2100 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2102 if (type_p) {
2103 *type_p = type;
2106 if (data_p) {
2107 *data_p = data;
2110 return true;
2113 static bool test_GetPrinterData_list(struct torture_context *tctx,
2114 struct dcerpc_pipe *p,
2115 struct policy_handle *handle)
2117 const char *list[] = {
2118 "W3SvcInstalled",
2119 "BeepEnabled",
2120 "EventLog",
2121 /* "NetPopup", not on w2k8 */
2122 /* "NetPopupToComputer", not on w2k8 */
2123 "MajorVersion",
2124 "MinorVersion",
2125 "DefaultSpoolDirectory",
2126 "Architecture",
2127 "DsPresent",
2128 "OSVersion",
2129 /* "OSVersionEx", not on s3 */
2130 "DNSMachineName"
2132 int i;
2134 for (i=0; i < ARRAY_SIZE(list); i++) {
2135 enum winreg_Type type, type_ex;
2136 union spoolss_PrinterData data, data_ex;
2138 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2139 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2140 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2141 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2142 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2143 switch (type) {
2144 case REG_SZ:
2145 torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2146 break;
2147 case REG_DWORD:
2148 torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2149 break;
2150 case REG_BINARY:
2151 torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2152 break;
2153 default:
2154 break;
2158 return true;
2161 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2162 struct policy_handle *handle)
2164 NTSTATUS status;
2165 struct spoolss_EnumPrinterData r;
2167 ZERO_STRUCT(r);
2168 r.in.handle = handle;
2169 r.in.enum_index = 0;
2171 do {
2172 uint32_t value_size = 0;
2173 uint32_t data_size = 0;
2174 enum winreg_Type type = 0;
2176 r.in.value_offered = value_size;
2177 r.out.value_needed = &value_size;
2178 r.in.data_offered = data_size;
2179 r.out.data_needed = &data_size;
2181 r.out.type = &type;
2182 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2184 torture_comment(tctx, "Testing EnumPrinterData\n");
2186 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2188 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2189 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2190 break;
2192 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2194 r.in.value_offered = value_size;
2195 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2196 r.in.data_offered = data_size;
2197 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2199 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2201 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2202 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2203 break;
2206 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2208 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2209 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2211 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2212 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2214 r.in.enum_index++;
2216 } while (W_ERROR_IS_OK(r.out.result));
2218 return true;
2221 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2222 struct dcerpc_pipe *p,
2223 struct policy_handle *handle,
2224 const char *key_name)
2226 struct spoolss_EnumPrinterDataEx r;
2227 struct spoolss_PrinterEnumValues *info;
2228 uint32_t needed;
2229 uint32_t count;
2231 r.in.handle = handle;
2232 r.in.key_name = key_name;
2233 r.in.offered = 0;
2234 r.out.needed = &needed;
2235 r.out.count = &count;
2236 r.out.info = &info;
2238 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2240 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2241 "EnumPrinterDataEx failed");
2242 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2243 r.in.offered = needed;
2244 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2245 "EnumPrinterDataEx failed");
2248 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2250 return true;
2254 static bool test_DeletePrinterData(struct torture_context *tctx,
2255 struct dcerpc_pipe *p,
2256 struct policy_handle *handle,
2257 const char *value_name)
2259 NTSTATUS status;
2260 struct spoolss_DeletePrinterData r;
2262 r.in.handle = handle;
2263 r.in.value_name = value_name;
2265 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2266 r.in.value_name);
2268 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2270 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2271 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2273 return true;
2276 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2277 struct dcerpc_pipe *p,
2278 struct policy_handle *handle,
2279 const char *key_name,
2280 const char *value_name)
2282 struct spoolss_DeletePrinterDataEx r;
2284 r.in.handle = handle;
2285 r.in.key_name = key_name;
2286 r.in.value_name = value_name;
2288 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2289 r.in.key_name, r.in.value_name);
2291 torture_assert_ntstatus_ok(tctx,
2292 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2293 "DeletePrinterDataEx failed");
2294 torture_assert_werr_ok(tctx, r.out.result,
2295 "DeletePrinterDataEx failed");
2297 return true;
2300 static bool test_DeletePrinterKey(struct torture_context *tctx,
2301 struct dcerpc_pipe *p,
2302 struct policy_handle *handle,
2303 const char *key_name)
2305 struct spoolss_DeletePrinterKey r;
2307 r.in.handle = handle;
2308 r.in.key_name = key_name;
2310 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2312 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2313 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2314 return true;
2317 torture_assert_ntstatus_ok(tctx,
2318 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2319 "DeletePrinterKey failed");
2320 torture_assert_werr_ok(tctx, r.out.result,
2321 "DeletePrinterKey failed");
2323 return true;
2326 static bool test_SetPrinterData(struct torture_context *tctx,
2327 struct dcerpc_pipe *p,
2328 struct policy_handle *handle)
2330 NTSTATUS status;
2331 struct spoolss_SetPrinterData r;
2332 const char *values[] = {
2333 "spootyfoot",
2334 "spooty\\foot",
2335 "spooty,foot",
2336 "spooty,fo,ot",
2337 "spooty foot",
2338 "spooty\\fo,ot",
2339 "spooty,fo\\ot"
2341 int i;
2343 for (i=0; i < ARRAY_SIZE(values); i++) {
2345 enum winreg_Type type;
2346 union spoolss_PrinterData data;
2348 r.in.handle = handle;
2349 r.in.value_name = values[i];
2350 r.in.type = REG_SZ;
2351 r.in.data.string = "dog";
2353 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2354 r.in.value_name);
2356 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2358 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2359 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2361 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2362 return false;
2365 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2366 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2368 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2369 return false;
2373 return true;
2376 static bool test_EnumPrinterKey(struct torture_context *tctx,
2377 struct dcerpc_pipe *p,
2378 struct policy_handle *handle,
2379 const char *key_name,
2380 const char ***array);
2382 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2383 struct dcerpc_pipe *p,
2384 struct policy_handle *handle)
2386 NTSTATUS status;
2387 struct spoolss_SetPrinterDataEx r;
2388 const char *value_name = "dog";
2389 const char *keys[] = {
2390 "torturedataex",
2391 "torture data ex",
2392 "torturedataex_with_subkey\\subkey",
2393 "torturedataex_with_subkey\\subkey:0",
2394 "torturedataex_with_subkey\\subkey:1",
2395 "torturedataex_with_subkey\\subkey\\subsubkey",
2396 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2397 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2398 "torture,data",
2399 "torture,data,ex",
2400 "torture,data\\ex",
2401 "torture\\data,ex"
2403 int i;
2404 DATA_BLOB blob = data_blob_string_const("catfoobar");
2407 for (i=0; i < ARRAY_SIZE(keys); i++) {
2409 char *c;
2410 const char *key;
2411 enum winreg_Type type;
2412 const char **subkeys;
2413 union spoolss_PrinterData data;
2415 r.in.handle = handle;
2416 r.in.key_name = keys[i];
2417 r.in.value_name = value_name;
2418 r.in.type = REG_BINARY;
2419 r.in.data.binary = blob;
2421 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2423 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2425 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2426 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2428 key = talloc_strdup(tctx, r.in.key_name);
2430 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
2431 return false;
2434 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2435 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
2437 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2438 return false;
2441 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2442 return false;
2445 c = strchr(key, '\\');
2446 if (c) {
2447 int i;
2449 /* we have subkeys */
2451 *c = 0;
2453 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2454 return false;
2457 for (i=0; subkeys && subkeys[i]; i++) {
2459 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2461 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2462 return false;
2466 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2467 return false;
2470 } else {
2471 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2472 return false;
2477 return true;
2481 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2482 struct dcerpc_pipe *p,
2483 struct policy_handle *handle)
2485 NTSTATUS status;
2486 struct dcerpc_binding *b;
2487 struct dcerpc_pipe *p2;
2488 struct spoolss_ClosePrinter cp;
2490 /* only makes sense on SMB */
2491 if (p->conn->transport.transport != NCACN_NP) {
2492 return true;
2495 torture_comment(tctx, "testing close on secondary pipe\n");
2497 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2498 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2500 status = dcerpc_secondary_connection(p, &p2, b);
2501 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2503 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2504 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2506 cp.in.handle = handle;
2507 cp.out.handle = handle;
2509 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2510 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2511 "ERROR: Allowed close on secondary connection");
2513 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2514 "Unexpected fault code");
2516 talloc_free(p2);
2518 return true;
2521 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2522 struct dcerpc_pipe *p, const char *name)
2524 NTSTATUS status;
2525 struct spoolss_OpenPrinter op;
2526 struct spoolss_OpenPrinterEx opEx;
2527 struct policy_handle handle;
2528 bool ret = true;
2530 op.in.printername = name;
2531 op.in.datatype = NULL;
2532 op.in.devmode_ctr.devmode= NULL;
2533 op.in.access_mask = 0;
2534 op.out.handle = &handle;
2536 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2538 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2539 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2540 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2541 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2542 name, win_errstr(op.out.result));
2545 if (W_ERROR_IS_OK(op.out.result)) {
2546 ret &=test_ClosePrinter(tctx, p, &handle);
2549 opEx.in.printername = name;
2550 opEx.in.datatype = NULL;
2551 opEx.in.devmode_ctr.devmode = NULL;
2552 opEx.in.access_mask = 0;
2553 opEx.in.level = 1;
2554 opEx.in.userlevel.level1 = NULL;
2555 opEx.out.handle = &handle;
2557 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2559 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2560 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2561 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2562 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2563 name, win_errstr(opEx.out.result));
2566 if (W_ERROR_IS_OK(opEx.out.result)) {
2567 ret &=test_ClosePrinter(tctx, p, &handle);
2570 return ret;
2573 static bool test_OpenPrinter(struct torture_context *tctx,
2574 struct dcerpc_pipe *p,
2575 const char *name)
2577 NTSTATUS status;
2578 struct spoolss_OpenPrinter r;
2579 struct policy_handle handle;
2580 bool ret = true;
2582 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2583 r.in.datatype = NULL;
2584 r.in.devmode_ctr.devmode= NULL;
2585 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2586 r.out.handle = &handle;
2588 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2590 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2592 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2594 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2596 if (!test_GetPrinter(tctx, p, &handle)) {
2597 ret = false;
2600 if (!torture_setting_bool(tctx, "samba3", false)) {
2601 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2602 ret = false;
2606 if (!test_ClosePrinter(tctx, p, &handle)) {
2607 ret = false;
2610 return ret;
2613 static bool call_OpenPrinterEx(struct torture_context *tctx,
2614 struct dcerpc_pipe *p,
2615 const char *name, struct policy_handle *handle)
2617 struct spoolss_OpenPrinterEx r;
2618 struct spoolss_UserLevel1 userlevel1;
2619 NTSTATUS status;
2621 if (name && name[0]) {
2622 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2623 dcerpc_server_name(p), name);
2624 } else {
2625 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2626 dcerpc_server_name(p));
2629 r.in.datatype = NULL;
2630 r.in.devmode_ctr.devmode= NULL;
2631 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2632 r.in.level = 1;
2633 r.in.userlevel.level1 = &userlevel1;
2634 r.out.handle = handle;
2636 userlevel1.size = 1234;
2637 userlevel1.client = "hello";
2638 userlevel1.user = "spottyfoot!";
2639 userlevel1.build = 1;
2640 userlevel1.major = 2;
2641 userlevel1.minor = 3;
2642 userlevel1.processor = 4;
2644 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2646 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2648 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2650 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2652 return true;
2655 static bool test_OpenPrinterEx(struct torture_context *tctx,
2656 struct dcerpc_pipe *p,
2657 const char *name)
2659 struct policy_handle handle;
2660 bool ret = true;
2662 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2663 return false;
2666 if (!test_GetPrinter(tctx, p, &handle)) {
2667 ret = false;
2670 if (!test_EnumForms(tctx, p, &handle, false)) {
2671 ret = false;
2674 if (!test_AddForm(tctx, p, &handle, false)) {
2675 ret = false;
2678 if (!test_EnumPrinterData(tctx, p, &handle)) {
2679 ret = false;
2682 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
2683 ret = false;
2686 if (!test_printer_keys(tctx, p, &handle)) {
2687 ret = false;
2690 if (!test_PausePrinter(tctx, p, &handle)) {
2691 ret = false;
2694 if (!test_DoPrintTest(tctx, p, &handle)) {
2695 ret = false;
2698 if (!test_ResumePrinter(tctx, p, &handle)) {
2699 ret = false;
2702 if (!test_SetPrinterData(tctx, p, &handle)) {
2703 ret = false;
2706 if (!test_SetPrinterDataEx(tctx, p, &handle)) {
2707 ret = false;
2710 if (!torture_setting_bool(tctx, "samba3", false)) {
2711 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2712 ret = false;
2716 if (!test_ClosePrinter(tctx, p, &handle)) {
2717 ret = false;
2720 return ret;
2723 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2725 struct spoolss_EnumPrinters r;
2726 NTSTATUS status;
2727 uint16_t levels[] = {1, 2, 4, 5};
2728 int i;
2729 bool ret = true;
2731 for (i=0;i<ARRAY_SIZE(levels);i++) {
2732 union spoolss_PrinterInfo *info;
2733 int j;
2734 uint32_t needed;
2735 uint32_t count;
2737 r.in.flags = PRINTER_ENUM_LOCAL;
2738 r.in.server = "";
2739 r.in.level = levels[i];
2740 r.in.buffer = NULL;
2741 r.in.offered = 0;
2742 r.out.needed = &needed;
2743 r.out.count = &count;
2744 r.out.info = &info;
2746 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2748 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2749 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2751 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2752 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2753 data_blob_clear(&blob);
2754 r.in.buffer = &blob;
2755 r.in.offered = needed;
2756 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2759 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2761 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2763 if (!info) {
2764 torture_comment(tctx, "No printers returned\n");
2765 return true;
2768 for (j=0;j<count;j++) {
2769 if (r.in.level == 1) {
2770 char *unc = talloc_strdup(tctx, info[j].info1.name);
2771 char *slash, *name;
2772 name = unc;
2773 if (unc[0] == '\\' && unc[1] == '\\') {
2774 unc +=2;
2776 slash = strchr(unc, '\\');
2777 if (slash) {
2778 slash++;
2779 name = slash;
2781 if (!test_OpenPrinter(tctx, p, name)) {
2782 ret = false;
2784 if (!test_OpenPrinterEx(tctx, p, name)) {
2785 ret = false;
2791 return ret;
2794 static bool test_GetPrinterDriver(struct torture_context *tctx,
2795 struct dcerpc_pipe *p,
2796 struct policy_handle *handle,
2797 const char *driver_name)
2799 struct spoolss_GetPrinterDriver r;
2800 uint32_t needed;
2802 r.in.handle = handle;
2803 r.in.architecture = "W32X86";
2804 r.in.level = 1;
2805 r.in.buffer = NULL;
2806 r.in.offered = 0;
2807 r.out.needed = &needed;
2809 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2811 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2812 "failed to call GetPrinterDriver");
2813 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2814 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2815 data_blob_clear(&blob);
2816 r.in.buffer = &blob;
2817 r.in.offered = needed;
2818 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2819 "failed to call GetPrinterDriver");
2822 torture_assert_werr_ok(tctx, r.out.result,
2823 "failed to call GetPrinterDriver");
2825 return true;
2828 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2829 struct dcerpc_pipe *p,
2830 struct policy_handle *handle,
2831 const char *driver_name)
2833 struct spoolss_GetPrinterDriver2 r;
2834 uint32_t needed;
2835 uint32_t server_major_version;
2836 uint32_t server_minor_version;
2838 r.in.handle = handle;
2839 r.in.architecture = "W32X86";
2840 r.in.level = 1;
2841 r.in.buffer = NULL;
2842 r.in.offered = 0;
2843 r.in.client_major_version = 0;
2844 r.in.client_minor_version = 0;
2845 r.out.needed = &needed;
2846 r.out.server_major_version = &server_major_version;
2847 r.out.server_minor_version = &server_minor_version;
2849 torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2851 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2852 "failed to call GetPrinterDriver2");
2853 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2854 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2855 data_blob_clear(&blob);
2856 r.in.buffer = &blob;
2857 r.in.offered = needed;
2858 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2859 "failed to call GetPrinterDriver2");
2862 torture_assert_werr_ok(tctx, r.out.result,
2863 "failed to call GetPrinterDriver2");
2865 return true;
2868 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2869 struct dcerpc_pipe *p)
2871 struct spoolss_EnumPrinterDrivers r;
2872 NTSTATUS status;
2873 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2874 int i;
2876 for (i=0;i<ARRAY_SIZE(levels);i++) {
2878 uint32_t needed;
2879 uint32_t count;
2880 union spoolss_DriverInfo *info;
2882 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2883 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2884 r.in.level = levels[i];
2885 r.in.buffer = NULL;
2886 r.in.offered = 0;
2887 r.out.needed = &needed;
2888 r.out.count = &count;
2889 r.out.info = &info;
2891 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2893 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2895 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2897 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2898 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2899 data_blob_clear(&blob);
2900 r.in.buffer = &blob;
2901 r.in.offered = needed;
2902 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2905 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2907 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2909 if (!info) {
2910 torture_comment(tctx, "No printer drivers returned\n");
2911 break;
2915 return true;
2918 static bool test_DeletePrinter(struct torture_context *tctx,
2919 struct dcerpc_pipe *p,
2920 struct policy_handle *handle)
2922 struct spoolss_DeletePrinter r;
2924 torture_comment(tctx, "Testing DeletePrinter\n");
2926 r.in.handle = handle;
2928 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2929 "failed to delete printer");
2930 torture_assert_werr_ok(tctx, r.out.result,
2931 "failed to delete printer");
2933 return true;
2936 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2937 struct dcerpc_pipe *p,
2938 uint32_t flags,
2939 uint32_t level,
2940 const char *name,
2941 bool *found)
2943 struct spoolss_EnumPrinters e;
2944 uint32_t count;
2945 union spoolss_PrinterInfo *info;
2946 uint32_t needed;
2947 int i;
2949 *found = false;
2951 e.in.flags = flags;
2952 e.in.server = NULL;
2953 e.in.level = level;
2954 e.in.buffer = NULL;
2955 e.in.offered = 0;
2956 e.out.count = &count;
2957 e.out.info = &info;
2958 e.out.needed = &needed;
2960 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2961 "failed to enum printers");
2963 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2964 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2965 data_blob_clear(&blob);
2966 e.in.buffer = &blob;
2967 e.in.offered = needed;
2969 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2970 "failed to enum printers");
2973 torture_assert_werr_ok(tctx, e.out.result,
2974 "failed to enum printers");
2976 for (i=0; i < count; i++) {
2978 const char *current = NULL;
2980 switch (level) {
2981 case 1:
2982 current = info[i].info1.name;
2983 break;
2986 if (strequal(current, name)) {
2987 *found = true;
2988 break;
2992 return true;
2995 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2996 struct dcerpc_pipe *p,
2997 const char *printername,
2998 bool ex)
3000 WERROR result;
3001 struct spoolss_AddPrinter r;
3002 struct spoolss_AddPrinterEx rex;
3003 struct spoolss_SetPrinterInfoCtr info_ctr;
3004 struct spoolss_SetPrinterInfo1 info1;
3005 struct spoolss_DevmodeContainer devmode_ctr;
3006 struct sec_desc_buf secdesc_ctr;
3007 struct spoolss_UserLevelCtr userlevel_ctr;
3008 struct policy_handle handle;
3009 bool found = false;
3011 ZERO_STRUCT(devmode_ctr);
3012 ZERO_STRUCT(secdesc_ctr);
3013 ZERO_STRUCT(userlevel_ctr);
3014 ZERO_STRUCT(info1);
3016 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3018 /* try to add printer to wellknown printer list (level 1) */
3020 userlevel_ctr.level = 1;
3022 info_ctr.info.info1 = &info1;
3023 info_ctr.level = 1;
3025 rex.in.server = NULL;
3026 rex.in.info_ctr = &info_ctr;
3027 rex.in.devmode_ctr = &devmode_ctr;
3028 rex.in.secdesc_ctr = &secdesc_ctr;
3029 rex.in.userlevel_ctr = &userlevel_ctr;
3030 rex.out.handle = &handle;
3032 r.in.server = NULL;
3033 r.in.info_ctr = &info_ctr;
3034 r.in.devmode_ctr = &devmode_ctr;
3035 r.in.secdesc_ctr = &secdesc_ctr;
3036 r.out.handle = &handle;
3038 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3039 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3040 "failed to add printer");
3041 result = ex ? rex.out.result : r.out.result;
3042 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3043 "unexpected result code");
3045 info1.name = printername;
3046 info1.flags = PRINTER_ATTRIBUTE_SHARED;
3048 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3049 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3050 "failed to add printer");
3051 result = ex ? rex.out.result : r.out.result;
3052 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3053 "unexpected result code");
3055 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3056 better do a real check to see the printer is really there */
3058 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3059 PRINTER_ENUM_NETWORK, 1,
3060 printername,
3061 &found),
3062 "failed to enum printers");
3064 torture_assert(tctx, found, "failed to find newly added printer");
3066 info1.flags = 0;
3068 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3069 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3070 "failed to add printer");
3071 result = ex ? rex.out.result : r.out.result;
3072 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3073 "unexpected result code");
3075 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3076 better do a real check to see the printer has really been removed
3077 from the well known printer list */
3079 found = false;
3081 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3082 PRINTER_ENUM_NETWORK, 1,
3083 printername,
3084 &found),
3085 "failed to enum printers");
3086 #if 0
3087 torture_assert(tctx, !found, "printer still in well known printer list");
3088 #endif
3089 return true;
3092 static bool test_AddPrinter_normal(struct torture_context *tctx,
3093 struct dcerpc_pipe *p,
3094 struct policy_handle *handle_p,
3095 const char *printername,
3096 const char *drivername,
3097 const char *portname,
3098 bool ex)
3100 WERROR result;
3101 struct spoolss_AddPrinter r;
3102 struct spoolss_AddPrinterEx rex;
3103 struct spoolss_SetPrinterInfoCtr info_ctr;
3104 struct spoolss_SetPrinterInfo2 info2;
3105 struct spoolss_DevmodeContainer devmode_ctr;
3106 struct sec_desc_buf secdesc_ctr;
3107 struct spoolss_UserLevelCtr userlevel_ctr;
3108 struct policy_handle handle;
3109 bool found = false;
3111 ZERO_STRUCT(devmode_ctr);
3112 ZERO_STRUCT(secdesc_ctr);
3113 ZERO_STRUCT(userlevel_ctr);
3115 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3117 userlevel_ctr.level = 1;
3119 rex.in.server = NULL;
3120 rex.in.info_ctr = &info_ctr;
3121 rex.in.devmode_ctr = &devmode_ctr;
3122 rex.in.secdesc_ctr = &secdesc_ctr;
3123 rex.in.userlevel_ctr = &userlevel_ctr;
3124 rex.out.handle = &handle;
3126 r.in.server = NULL;
3127 r.in.info_ctr = &info_ctr;
3128 r.in.devmode_ctr = &devmode_ctr;
3129 r.in.secdesc_ctr = &secdesc_ctr;
3130 r.out.handle = &handle;
3132 again:
3134 /* try to add printer to printer list (level 2) */
3136 ZERO_STRUCT(info2);
3138 info_ctr.info.info2 = &info2;
3139 info_ctr.level = 2;
3141 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3142 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3143 "failed to add printer");
3144 result = ex ? rex.out.result : r.out.result;
3145 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3146 "unexpected result code");
3148 info2.printername = printername;
3150 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3151 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3152 "failed to add printer");
3153 result = ex ? rex.out.result : r.out.result;
3155 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3156 struct policy_handle printer_handle;
3158 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3159 "failed to open printer handle");
3161 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3162 "failed to delete printer");
3164 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3165 "failed to close server handle");
3167 goto again;
3170 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3171 "unexpected result code");
3173 info2.portname = portname;
3175 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3176 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3177 "failed to add printer");
3178 result = ex ? rex.out.result : r.out.result;
3179 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3180 "unexpected result code");
3182 info2.drivername = drivername;
3184 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3185 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3186 "failed to add printer");
3187 result = ex ? rex.out.result : r.out.result;
3188 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3189 "unexpected result code");
3191 info2.printprocessor = "winprint";
3193 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3194 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3195 "failed to add printer");
3196 result = ex ? rex.out.result : r.out.result;
3197 torture_assert_werr_ok(tctx, result,
3198 "failed to add printer");
3200 *handle_p = handle;
3202 /* we are paranoid, really check if the printer is there now */
3204 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3205 PRINTER_ENUM_LOCAL, 1,
3206 printername,
3207 &found),
3208 "failed to enum printers");
3209 torture_assert(tctx, found, "failed to find newly added printer");
3211 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3212 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3213 "failed to add printer");
3214 result = ex ? rex.out.result : r.out.result;
3215 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3216 "unexpected result code");
3218 return true;
3221 static bool test_AddPrinterEx(struct torture_context *tctx,
3222 struct dcerpc_pipe *p,
3223 struct policy_handle *handle_p,
3224 const char *printername,
3225 const char *drivername,
3226 const char *portname)
3228 bool ret = true;
3230 if (!torture_setting_bool(tctx, "samba3", false)) {
3231 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3232 torture_comment(tctx, "failed to add printer to well known list\n");
3233 ret = false;
3237 if (!test_AddPrinter_normal(tctx, p, handle_p,
3238 printername, drivername, portname,
3239 true)) {
3240 torture_comment(tctx, "failed to add printer to printer list\n");
3241 ret = false;
3244 return ret;
3247 static bool test_AddPrinter(struct torture_context *tctx,
3248 struct dcerpc_pipe *p,
3249 struct policy_handle *handle_p,
3250 const char *printername,
3251 const char *drivername,
3252 const char *portname)
3254 bool ret = true;
3256 if (!torture_setting_bool(tctx, "samba3", false)) {
3257 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3258 torture_comment(tctx, "failed to add printer to well known list\n");
3259 ret = false;
3263 if (!test_AddPrinter_normal(tctx, p, handle_p,
3264 printername, drivername, portname,
3265 false)) {
3266 torture_comment(tctx, "failed to add printer to printer list\n");
3267 ret = false;
3270 return ret;
3273 static bool test_printer_info(struct torture_context *tctx,
3274 struct dcerpc_pipe *p,
3275 struct policy_handle *handle)
3277 bool ret = true;
3279 if (!test_PrinterInfo(tctx, p, handle)) {
3280 ret = false;
3283 if (!test_SetPrinter_errors(tctx, p, handle)) {
3284 ret = false;
3287 return ret;
3290 static bool test_EnumPrinterKey(struct torture_context *tctx,
3291 struct dcerpc_pipe *p,
3292 struct policy_handle *handle,
3293 const char *key_name,
3294 const char ***array)
3296 struct spoolss_EnumPrinterKey r;
3297 uint32_t needed;
3298 struct spoolss_StringArray2 key_buffer;
3300 r.in.handle = handle;
3301 r.in.key_name = key_name;
3302 r.in.offered = 0;
3303 r.out.key_buffer = &key_buffer;
3304 r.out.needed = &needed;
3306 torture_comment(tctx, "Testing EnumPrinterKey(%s)\n", r.in.key_name);
3308 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3309 "failed to call EnumPrinterKey");
3310 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3311 torture_assert(tctx, (key_buffer._ndr_size == 0),
3312 talloc_asprintf(tctx, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer._ndr_size));
3313 r.in.offered = needed;
3314 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3315 "failed to call EnumPrinterKey");
3317 torture_assert_werr_ok(tctx, r.out.result,
3318 "failed to call EnumPrinterKey");
3320 torture_assert(tctx, (key_buffer._ndr_size * 2 == needed),
3321 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3322 key_buffer._ndr_size, needed/2));
3324 if (array) {
3325 *array = key_buffer.string;
3328 return true;
3331 bool test_printer_keys(struct torture_context *tctx,
3332 struct dcerpc_pipe *p,
3333 struct policy_handle *handle)
3335 const char **key_array = NULL;
3336 int i;
3338 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
3339 "failed to call test_EnumPrinterKey");
3341 for (i=0; key_array && key_array[i]; i++) {
3342 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
3343 "failed to call test_EnumPrinterKey");
3345 for (i=0; key_array && key_array[i]; i++) {
3346 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3347 "failed to call test_EnumPrinterDataEx");
3350 return true;
3353 static bool test_printer(struct torture_context *tctx,
3354 struct dcerpc_pipe *p)
3356 bool ret = true;
3357 struct policy_handle handle[2];
3358 bool found = false;
3359 const char *drivername = "Microsoft XPS Document Writer";
3360 const char *portname = "LPT1:";
3362 /* test printer created via AddPrinter */
3364 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3365 return false;
3368 if (!test_printer_info(tctx, p, &handle[0])) {
3369 ret = false;
3372 if (!test_printer_keys(tctx, p, &handle[0])) {
3373 ret = false;
3376 if (!test_DeletePrinter(tctx, p, &handle[0])) {
3377 ret = false;
3380 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3381 TORTURE_PRINTER, &found)) {
3382 ret = false;
3385 torture_assert(tctx, !found, "deleted printer still there");
3387 /* test printer created via AddPrinterEx */
3389 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3390 return false;
3393 if (!test_printer_info(tctx, p, &handle[1])) {
3394 ret = false;
3397 if (!test_printer_keys(tctx, p, &handle[1])) {
3398 ret = false;
3401 if (!test_DeletePrinter(tctx, p, &handle[1])) {
3402 ret = false;
3405 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3406 TORTURE_PRINTER_EX, &found)) {
3407 ret = false;
3410 torture_assert(tctx, !found, "deleted printer still there");
3412 return ret;
3415 bool torture_rpc_spoolss(struct torture_context *torture)
3417 NTSTATUS status;
3418 struct dcerpc_pipe *p;
3419 bool ret = true;
3420 struct test_spoolss_context *ctx;
3422 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3423 if (!NT_STATUS_IS_OK(status)) {
3424 return false;
3427 ctx = talloc_zero(torture, struct test_spoolss_context);
3429 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3430 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
3431 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3432 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3433 ret &= test_EnumPorts(torture, p, ctx);
3434 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3435 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3436 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3437 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3438 ret &= test_EnumMonitors(torture, p, ctx);
3439 ret &= test_EnumPrintProcessors(torture, p, ctx);
3440 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3441 ret &= test_EnumPrinters(torture, p, ctx);
3442 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3443 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3444 ret &= test_OpenPrinter_badname(torture, p, "");
3445 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3446 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3447 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3448 ret &= test_OpenPrinter_badname(torture, p,
3449 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3452 ret &= test_AddPort(torture, p);
3453 ret &= test_EnumPorts_old(torture, p);
3454 ret &= test_EnumPrinters_old(torture, p);
3455 ret &= test_EnumPrinterDrivers_old(torture, p);
3457 return ret;
3460 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3462 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3464 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3465 "printer", &ndr_table_spoolss);
3467 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3469 return suite;