s3 swat: Allow getting the user's HTTP auth password
[Samba.git] / source4 / torture / rpc / spoolss.c
blobd107616ef3ce8bab5c31fcda265d71a4455aa9b3
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "torture/rpc/rpc.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "param/param.h"
30 struct test_spoolss_context {
31 /* print server handle */
32 struct policy_handle server_handle;
34 /* for EnumPorts */
35 uint32_t port_count[3];
36 union spoolss_PortInfo *ports[3];
38 /* for EnumPrinterDrivers */
39 uint32_t driver_count[7];
40 union spoolss_DriverInfo *drivers[7];
42 /* for EnumMonitors */
43 uint32_t monitor_count[3];
44 union spoolss_MonitorInfo *monitors[3];
46 /* for EnumPrintProcessors */
47 uint32_t print_processor_count[2];
48 union spoolss_PrintProcessorInfo *print_processors[2];
50 /* for EnumPrinters */
51 uint32_t printer_count[6];
52 union spoolss_PrinterInfo *printers[6];
55 #define COMPARE_STRING(tctx, c,r,e) \
56 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
58 /* not every compiler supports __typeof__() */
59 #if (__GNUC__ >= 3)
60 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
61 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
62 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
64 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
65 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
67 } while(0)
68 #else
69 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
70 #endif
72 #define COMPARE_UINT32(tctx, c, r, e) do {\
73 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
74 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
75 } while(0)
77 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
79 static bool test_OpenPrinter_server(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
81 NTSTATUS status;
82 struct spoolss_OpenPrinter op;
84 op.in.printername = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
85 op.in.datatype = NULL;
86 op.in.devmode_ctr.devmode= NULL;
87 op.in.access_mask = 0;
88 op.out.handle = &ctx->server_handle;
90 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
92 status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
93 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
94 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
96 return true;
99 static bool test_EnumPorts(struct torture_context *tctx,
100 struct dcerpc_pipe *p,
101 struct test_spoolss_context *ctx)
103 NTSTATUS status;
104 struct spoolss_EnumPorts r;
105 uint16_t levels[] = { 1, 2 };
106 int i, j;
108 for (i=0;i<ARRAY_SIZE(levels);i++) {
109 int level = levels[i];
110 DATA_BLOB blob;
111 uint32_t needed;
112 uint32_t count;
113 union spoolss_PortInfo *info;
115 r.in.servername = "";
116 r.in.level = level;
117 r.in.buffer = NULL;
118 r.in.offered = 0;
119 r.out.needed = &needed;
120 r.out.count = &count;
121 r.out.info = &info;
123 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
125 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
126 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
127 if (W_ERROR_IS_OK(r.out.result)) {
128 /* TODO: do some more checks here */
129 continue;
131 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
132 "EnumPorts unexpected return code");
134 blob = data_blob_talloc(ctx, NULL, needed);
135 data_blob_clear(&blob);
136 r.in.buffer = &blob;
137 r.in.offered = needed;
139 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
140 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
142 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
144 torture_assert(tctx, info, "EnumPorts returned no info");
146 ctx->port_count[level] = count;
147 ctx->ports[level] = info;
150 for (i=1;i<ARRAY_SIZE(levels);i++) {
151 int level = levels[i];
152 int old_level = levels[i-1];
153 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
154 "EnumPorts invalid value");
156 /* if the array sizes are not the same we would maybe segfault in the following code */
158 for (i=0;i<ARRAY_SIZE(levels);i++) {
159 int level = levels[i];
160 for (j=0;j<ctx->port_count[level];j++) {
161 union spoolss_PortInfo *cur = &ctx->ports[level][j];
162 union spoolss_PortInfo *ref = &ctx->ports[2][j];
163 switch (level) {
164 case 1:
165 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
166 break;
167 case 2:
168 /* level 2 is our reference, and it makes no sense to compare it to itself */
169 break;
174 return true;
177 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
178 struct dcerpc_pipe *p,
179 struct test_spoolss_context *ctx)
181 NTSTATUS status;
182 struct spoolss_GetPrintProcessorDirectory r;
183 struct {
184 uint16_t level;
185 const char *server;
186 } levels[] = {{
187 .level = 1,
188 .server = NULL
190 .level = 1,
191 .server = ""
193 .level = 78,
194 .server = ""
196 .level = 1,
197 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
199 .level = 1024,
200 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
203 int i;
204 uint32_t needed;
206 for (i=0;i<ARRAY_SIZE(levels);i++) {
207 int level = levels[i].level;
208 DATA_BLOB blob;
210 r.in.server = levels[i].server;
211 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
212 r.in.level = level;
213 r.in.buffer = NULL;
214 r.in.offered = 0;
215 r.out.needed = &needed;
217 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
219 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
220 torture_assert_ntstatus_ok(tctx, status,
221 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
222 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
223 "GetPrintProcessorDirectory unexpected return code");
225 blob = data_blob_talloc(ctx, NULL, needed);
226 data_blob_clear(&blob);
227 r.in.buffer = &blob;
228 r.in.offered = needed;
230 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
231 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
233 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
236 return true;
240 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
241 struct dcerpc_pipe *p,
242 struct test_spoolss_context *ctx)
244 NTSTATUS status;
245 struct spoolss_GetPrinterDriverDirectory r;
246 struct {
247 uint16_t level;
248 const char *server;
249 } levels[] = {{
250 .level = 1,
251 .server = NULL
253 .level = 1,
254 .server = ""
256 .level = 78,
257 .server = ""
259 .level = 1,
260 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
262 .level = 1024,
263 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
266 int i;
267 uint32_t needed;
269 for (i=0;i<ARRAY_SIZE(levels);i++) {
270 int level = levels[i].level;
271 DATA_BLOB blob;
273 r.in.server = levels[i].server;
274 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
275 r.in.level = level;
276 r.in.buffer = NULL;
277 r.in.offered = 0;
278 r.out.needed = &needed;
280 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
282 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
283 torture_assert_ntstatus_ok(tctx, status,
284 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
285 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
286 "GetPrinterDriverDirectory unexpected return code");
288 blob = data_blob_talloc(ctx, NULL, needed);
289 data_blob_clear(&blob);
290 r.in.buffer = &blob;
291 r.in.offered = needed;
293 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
294 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
296 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
299 return true;
302 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
303 struct dcerpc_pipe *p,
304 struct test_spoolss_context *ctx)
306 NTSTATUS status;
307 struct spoolss_EnumPrinterDrivers r;
308 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
309 int i, j;
311 for (i=0;i<ARRAY_SIZE(levels);i++) {
312 int level = levels[i];
313 DATA_BLOB blob;
314 uint32_t needed;
315 uint32_t count;
316 union spoolss_DriverInfo *info;
318 /* FIXME: gd, come back and fix "" as server, and handle
319 * priority of returned error codes in torture test and samba 3
320 * server */
322 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
323 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
324 r.in.level = level;
325 r.in.buffer = NULL;
326 r.in.offered = 0;
327 r.out.needed = &needed;
328 r.out.count = &count;
329 r.out.info = &info;
331 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
333 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
334 torture_assert_ntstatus_ok(tctx, status,
335 "dcerpc_spoolss_EnumPrinterDrivers failed");
336 if (W_ERROR_IS_OK(r.out.result)) {
337 /* TODO: do some more checks here */
338 continue;
340 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
341 blob = data_blob_talloc(ctx, NULL, needed);
342 data_blob_clear(&blob);
343 r.in.buffer = &blob;
344 r.in.offered = needed;
346 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
347 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
350 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
352 ctx->driver_count[level] = count;
353 ctx->drivers[level] = info;
356 for (i=1;i<ARRAY_SIZE(levels);i++) {
357 int level = levels[i];
358 int old_level = levels[i-1];
359 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
360 "EnumPrinterDrivers invalid value");
363 for (i=0;i<ARRAY_SIZE(levels);i++) {
364 int level = levels[i];
365 for (j=0;j<ctx->driver_count[level];j++) {
366 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
367 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
368 switch (level) {
369 case 1:
370 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
371 break;
372 case 2:
373 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
374 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
375 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
376 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
377 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
378 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
379 break;
380 case 3:
381 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
382 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
383 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
384 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
385 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
386 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
387 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
388 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
389 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
390 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
391 break;
392 case 4:
393 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
394 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
395 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
396 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
397 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
398 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
399 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
400 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
401 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
402 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
403 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
404 break;
405 case 5:
406 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
407 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
408 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
409 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
410 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
411 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
412 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
413 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
414 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
415 break;
416 case 6:
417 /* level 6 is our reference, and it makes no sense to compare it to itself */
418 break;
423 return true;
426 static bool test_EnumMonitors(struct torture_context *tctx,
427 struct dcerpc_pipe *p,
428 struct test_spoolss_context *ctx)
430 NTSTATUS status;
431 struct spoolss_EnumMonitors r;
432 uint16_t levels[] = { 1, 2 };
433 int i, j;
435 for (i=0;i<ARRAY_SIZE(levels);i++) {
436 int level = levels[i];
437 DATA_BLOB blob;
438 uint32_t needed;
439 uint32_t count;
440 union spoolss_MonitorInfo *info;
442 r.in.servername = "";
443 r.in.level = level;
444 r.in.buffer = NULL;
445 r.in.offered = 0;
446 r.out.needed = &needed;
447 r.out.count = &count;
448 r.out.info = &info;
450 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
452 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
453 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
454 if (W_ERROR_IS_OK(r.out.result)) {
455 /* TODO: do some more checks here */
456 continue;
458 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
459 "EnumMonitors failed");
461 blob = data_blob_talloc(ctx, NULL, needed);
462 data_blob_clear(&blob);
463 r.in.buffer = &blob;
464 r.in.offered = needed;
466 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
467 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
469 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
471 ctx->monitor_count[level] = count;
472 ctx->monitors[level] = info;
475 for (i=1;i<ARRAY_SIZE(levels);i++) {
476 int level = levels[i];
477 int old_level = levels[i-1];
478 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
479 "EnumMonitors invalid value");
482 for (i=0;i<ARRAY_SIZE(levels);i++) {
483 int level = levels[i];
484 for (j=0;j<ctx->monitor_count[level];j++) {
485 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
486 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
487 switch (level) {
488 case 1:
489 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
490 break;
491 case 2:
492 /* level 2 is our reference, and it makes no sense to compare it to itself */
493 break;
498 return true;
501 static bool test_EnumPrintProcessors(struct torture_context *tctx,
502 struct dcerpc_pipe *p,
503 struct test_spoolss_context *ctx)
505 NTSTATUS status;
506 struct spoolss_EnumPrintProcessors r;
507 uint16_t levels[] = { 1 };
508 int i, j;
510 for (i=0;i<ARRAY_SIZE(levels);i++) {
511 int level = levels[i];
512 DATA_BLOB blob;
513 uint32_t needed;
514 uint32_t count;
515 union spoolss_PrintProcessorInfo *info;
517 r.in.servername = "";
518 r.in.environment = "Windows NT x86";
519 r.in.level = level;
520 r.in.buffer = NULL;
521 r.in.offered = 0;
522 r.out.needed = &needed;
523 r.out.count = &count;
524 r.out.info = &info;
526 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
528 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
529 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
530 if (W_ERROR_IS_OK(r.out.result)) {
531 /* TODO: do some more checks here */
532 continue;
534 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
535 "EnumPrintProcessors unexpected return code");
537 blob = data_blob_talloc(ctx, NULL, needed);
538 data_blob_clear(&blob);
539 r.in.buffer = &blob;
540 r.in.offered = needed;
542 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
543 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
545 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
547 ctx->print_processor_count[level] = count;
548 ctx->print_processors[level] = info;
551 for (i=1;i<ARRAY_SIZE(levels);i++) {
552 int level = levels[i];
553 int old_level = levels[i-1];
554 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
555 "EnumPrintProcessors failed");
558 for (i=0;i<ARRAY_SIZE(levels);i++) {
559 int level = levels[i];
560 for (j=0;j<ctx->print_processor_count[level];j++) {
561 #if 0
562 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
563 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
564 #endif
565 switch (level) {
566 case 1:
567 /* level 1 is our reference, and it makes no sense to compare it to itself */
568 break;
573 return true;
576 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
577 struct dcerpc_pipe *p,
578 struct test_spoolss_context *ctx)
580 NTSTATUS status;
581 struct spoolss_EnumPrintProcDataTypes r;
582 uint16_t levels[] = { 1 };
583 int i;
585 for (i=0;i<ARRAY_SIZE(levels);i++) {
586 int level = levels[i];
587 DATA_BLOB blob;
588 uint32_t needed;
589 uint32_t count;
590 union spoolss_PrintProcDataTypesInfo *info;
592 r.in.servername = "";
593 r.in.print_processor_name = "winprint";
594 r.in.level = level;
595 r.in.buffer = NULL;
596 r.in.offered = 0;
597 r.out.needed = &needed;
598 r.out.count = &count;
599 r.out.info = &info;
601 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
603 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
604 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
605 if (W_ERROR_IS_OK(r.out.result)) {
606 /* TODO: do some more checks here */
607 continue;
609 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
610 "EnumPrintProcDataTypes unexpected return code");
612 blob = data_blob_talloc(ctx, NULL, needed);
613 data_blob_clear(&blob);
614 r.in.buffer = &blob;
615 r.in.offered = needed;
617 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
618 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
620 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
623 return true;
627 static bool test_EnumPrinters(struct torture_context *tctx,
628 struct dcerpc_pipe *p,
629 struct test_spoolss_context *ctx)
631 struct spoolss_EnumPrinters r;
632 NTSTATUS status;
633 uint16_t levels[] = { 0, 1, 2, 4, 5 };
634 int i, j;
636 for (i=0;i<ARRAY_SIZE(levels);i++) {
637 int level = levels[i];
638 DATA_BLOB blob;
639 uint32_t needed;
640 uint32_t count;
641 union spoolss_PrinterInfo *info;
643 r.in.flags = PRINTER_ENUM_LOCAL;
644 r.in.server = "";
645 r.in.level = level;
646 r.in.buffer = NULL;
647 r.in.offered = 0;
648 r.out.needed = &needed;
649 r.out.count = &count;
650 r.out.info = &info;
652 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
654 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
655 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
656 if (W_ERROR_IS_OK(r.out.result)) {
657 /* TODO: do some more checks here */
658 continue;
660 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
661 "EnumPrinters unexpected return code");
663 blob = data_blob_talloc(ctx, NULL, needed);
664 data_blob_clear(&blob);
665 r.in.buffer = &blob;
666 r.in.offered = needed;
668 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
669 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
671 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
673 ctx->printer_count[level] = count;
674 ctx->printers[level] = info;
677 for (i=1;i<ARRAY_SIZE(levels);i++) {
678 int level = levels[i];
679 int old_level = levels[i-1];
680 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
681 "EnumPrinters invalid value");
684 for (i=0;i<ARRAY_SIZE(levels);i++) {
685 int level = levels[i];
686 for (j=0;j<ctx->printer_count[level];j++) {
687 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
688 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
689 switch (level) {
690 case 0:
691 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
692 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
693 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
694 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
695 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
696 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
697 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
698 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
699 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
700 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
701 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
702 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
703 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
704 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
705 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
706 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
707 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
708 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
709 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
710 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
711 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
712 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
713 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
714 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
715 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
716 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
718 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
719 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
720 break;
721 case 1:
722 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
723 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
724 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
725 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
726 break;
727 case 2:
728 /* level 2 is our reference, and it makes no sense to compare it to itself */
729 break;
730 case 4:
731 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
732 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
733 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
734 break;
735 case 5:
736 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
737 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
738 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
739 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
740 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
741 break;
746 /* TODO:
747 * - verify that the port of a printer was in the list returned by EnumPorts
750 return true;
753 static bool test_GetPrinter(struct torture_context *tctx,
754 struct dcerpc_pipe *p,
755 struct policy_handle *handle)
757 NTSTATUS status;
758 struct spoolss_GetPrinter r;
759 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
760 int i;
761 uint32_t needed;
763 for (i=0;i<ARRAY_SIZE(levels);i++) {
764 r.in.handle = handle;
765 r.in.level = levels[i];
766 r.in.buffer = NULL;
767 r.in.offered = 0;
768 r.out.needed = &needed;
770 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
772 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
773 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
775 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
776 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
777 data_blob_clear(&blob);
778 r.in.buffer = &blob;
779 r.in.offered = needed;
780 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
783 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
785 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
788 return true;
792 static bool test_ClosePrinter(struct torture_context *tctx,
793 struct dcerpc_pipe *p,
794 struct policy_handle *handle)
796 NTSTATUS status;
797 struct spoolss_ClosePrinter r;
799 r.in.handle = handle;
800 r.out.handle = handle;
802 torture_comment(tctx, "Testing ClosePrinter\n");
804 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
805 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
807 return true;
810 static bool test_GetForm(struct torture_context *tctx,
811 struct dcerpc_pipe *p,
812 struct policy_handle *handle,
813 const char *form_name,
814 uint32_t level)
816 NTSTATUS status;
817 struct spoolss_GetForm r;
818 uint32_t needed;
820 r.in.handle = handle;
821 r.in.form_name = form_name;
822 r.in.level = level;
823 r.in.buffer = NULL;
824 r.in.offered = 0;
825 r.out.needed = &needed;
827 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
829 status = dcerpc_spoolss_GetForm(p, tctx, &r);
830 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
832 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
833 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
834 data_blob_clear(&blob);
835 r.in.buffer = &blob;
836 r.in.offered = needed;
837 status = dcerpc_spoolss_GetForm(p, tctx, &r);
838 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
840 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
842 torture_assert(tctx, r.out.info, "No form info returned");
845 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
847 return true;
850 static bool test_EnumForms(struct torture_context *tctx,
851 struct dcerpc_pipe *p,
852 struct policy_handle *handle, bool print_server)
854 NTSTATUS status;
855 struct spoolss_EnumForms r;
856 bool ret = true;
857 uint32_t needed;
858 uint32_t count;
859 uint32_t levels[] = { 1, 2 };
860 int i;
862 for (i=0; i<ARRAY_SIZE(levels); i++) {
864 union spoolss_FormInfo *info;
866 r.in.handle = handle;
867 r.in.level = levels[i];
868 r.in.buffer = NULL;
869 r.in.offered = 0;
870 r.out.needed = &needed;
871 r.out.count = &count;
872 r.out.info = &info;
874 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
876 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
877 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
879 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
880 break;
883 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
884 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
886 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
887 int j;
888 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
889 data_blob_clear(&blob);
890 r.in.buffer = &blob;
891 r.in.offered = needed;
893 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
895 torture_assert(tctx, info, "No forms returned");
897 for (j = 0; j < count; j++) {
898 if (!print_server)
899 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
903 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
905 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
908 return true;
911 static bool test_DeleteForm(struct torture_context *tctx,
912 struct dcerpc_pipe *p,
913 struct policy_handle *handle,
914 const char *form_name)
916 NTSTATUS status;
917 struct spoolss_DeleteForm r;
919 r.in.handle = handle;
920 r.in.form_name = form_name;
922 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
924 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
926 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
928 return true;
931 static bool test_AddForm(struct torture_context *tctx,
932 struct dcerpc_pipe *p,
933 struct policy_handle *handle, bool print_server)
935 struct spoolss_AddForm r;
936 struct spoolss_AddFormInfo1 addform;
937 const char *form_name = "testform3";
938 NTSTATUS status;
939 bool ret = true;
941 r.in.handle = handle;
942 r.in.level = 1;
943 r.in.info.info1 = &addform;
944 addform.flags = SPOOLSS_FORM_USER;
945 addform.form_name = form_name;
946 addform.size.width = 50;
947 addform.size.height = 25;
948 addform.area.left = 5;
949 addform.area.top = 10;
950 addform.area.right = 45;
951 addform.area.bottom = 15;
953 status = dcerpc_spoolss_AddForm(p, tctx, &r);
955 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
957 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
959 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
962 struct spoolss_SetForm sf;
963 struct spoolss_AddFormInfo1 setform;
965 sf.in.handle = handle;
966 sf.in.form_name = form_name;
967 sf.in.level = 1;
968 sf.in.info.info1= &setform;
969 setform.flags = addform.flags;
970 setform.form_name = addform.form_name;
971 setform.size = addform.size;
972 setform.area = addform.area;
974 setform.size.width = 1234;
976 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
978 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
980 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
983 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
985 if (!test_DeleteForm(tctx, p, handle, form_name)) {
986 ret = false;
989 return ret;
992 static bool test_EnumPorts_old(struct torture_context *tctx,
993 struct dcerpc_pipe *p)
995 NTSTATUS status;
996 struct spoolss_EnumPorts r;
997 uint32_t needed;
998 uint32_t count;
999 union spoolss_PortInfo *info;
1001 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1002 dcerpc_server_name(p));
1003 r.in.level = 2;
1004 r.in.buffer = NULL;
1005 r.in.offered = 0;
1006 r.out.needed = &needed;
1007 r.out.count = &count;
1008 r.out.info = &info;
1010 torture_comment(tctx, "Testing EnumPorts\n");
1012 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1014 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1016 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1017 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1018 data_blob_clear(&blob);
1019 r.in.buffer = &blob;
1020 r.in.offered = needed;
1022 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1023 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1025 torture_assert(tctx, info, "No ports returned");
1028 return true;
1031 static bool test_AddPort(struct torture_context *tctx,
1032 struct dcerpc_pipe *p)
1034 NTSTATUS status;
1035 struct spoolss_AddPort r;
1037 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1038 dcerpc_server_name(p));
1039 r.in.unknown = 0;
1040 r.in.monitor_name = "foo";
1042 torture_comment(tctx, "Testing AddPort\n");
1044 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1046 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1048 /* win2k3 returns WERR_NOT_SUPPORTED */
1050 #if 0
1052 if (!W_ERROR_IS_OK(r.out.result)) {
1053 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1054 return false;
1057 #endif
1059 return true;
1062 static bool test_GetJob(struct torture_context *tctx,
1063 struct dcerpc_pipe *p,
1064 struct policy_handle *handle, uint32_t job_id)
1066 NTSTATUS status;
1067 struct spoolss_GetJob r;
1068 uint32_t needed;
1069 uint32_t levels[] = {1, 2 /* 3, 4 */};
1070 uint32_t i;
1072 r.in.handle = handle;
1073 r.in.job_id = job_id;
1074 r.in.level = 0;
1075 r.in.buffer = NULL;
1076 r.in.offered = 0;
1077 r.out.needed = &needed;
1079 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1081 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1082 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1084 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1086 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1088 r.in.level = levels[i];
1089 r.in.offered = 0;
1091 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1092 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1094 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1095 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1096 data_blob_clear(&blob);
1097 r.in.buffer = &blob;
1098 r.in.offered = needed;
1100 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1101 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1104 torture_assert(tctx, r.out.info, "No job info returned");
1105 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1108 return true;
1111 static bool test_SetJob(struct torture_context *tctx,
1112 struct dcerpc_pipe *p,
1113 struct policy_handle *handle, uint32_t job_id,
1114 enum spoolss_JobControl command)
1116 NTSTATUS status;
1117 struct spoolss_SetJob r;
1119 r.in.handle = handle;
1120 r.in.job_id = job_id;
1121 r.in.ctr = NULL;
1122 r.in.command = command;
1124 switch (command) {
1125 case SPOOLSS_JOB_CONTROL_PAUSE:
1126 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1127 break;
1128 case SPOOLSS_JOB_CONTROL_RESUME:
1129 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1130 break;
1131 case SPOOLSS_JOB_CONTROL_CANCEL:
1132 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1133 break;
1134 case SPOOLSS_JOB_CONTROL_RESTART:
1135 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1136 break;
1137 case SPOOLSS_JOB_CONTROL_DELETE:
1138 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1139 break;
1140 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1141 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1142 break;
1143 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1144 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1145 break;
1146 case SPOOLSS_JOB_CONTROL_RETAIN:
1147 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1148 break;
1149 case SPOOLSS_JOB_CONTROL_RELEASE:
1150 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1151 break;
1152 default:
1153 torture_comment(tctx, "Testing SetJob\n");
1154 break;
1157 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1158 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1159 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1161 return true;
1164 static bool test_AddJob(struct torture_context *tctx,
1165 struct dcerpc_pipe *p,
1166 struct policy_handle *handle)
1168 NTSTATUS status;
1169 struct spoolss_AddJob r;
1170 uint32_t needed;
1172 r.in.level = 0;
1173 r.in.handle = handle;
1174 r.in.offered = 0;
1175 r.out.needed = &needed;
1176 r.in.buffer = r.out.buffer = NULL;
1178 torture_comment(tctx, "Testing AddJob\n");
1180 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1181 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1183 r.in.level = 1;
1185 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1186 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1188 return true;
1192 static bool test_EnumJobs(struct torture_context *tctx,
1193 struct dcerpc_pipe *p,
1194 struct policy_handle *handle)
1196 NTSTATUS status;
1197 struct spoolss_EnumJobs r;
1198 uint32_t needed;
1199 uint32_t count;
1200 union spoolss_JobInfo *info;
1202 r.in.handle = handle;
1203 r.in.firstjob = 0;
1204 r.in.numjobs = 0xffffffff;
1205 r.in.level = 1;
1206 r.in.buffer = NULL;
1207 r.in.offered = 0;
1208 r.out.needed = &needed;
1209 r.out.count = &count;
1210 r.out.info = &info;
1212 torture_comment(tctx, "Testing EnumJobs\n");
1214 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1216 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1218 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1219 int j;
1220 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1221 data_blob_clear(&blob);
1222 r.in.buffer = &blob;
1223 r.in.offered = needed;
1225 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1227 torture_assert(tctx, info, "No jobs returned");
1229 for (j = 0; j < count; j++) {
1231 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1233 /* FIXME - gd */
1234 if (!torture_setting_bool(tctx, "samba3", false)) {
1235 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1236 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1240 } else {
1241 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1244 return true;
1247 static bool test_DoPrintTest(struct torture_context *tctx,
1248 struct dcerpc_pipe *p,
1249 struct policy_handle *handle)
1251 bool ret = true;
1252 NTSTATUS status;
1253 struct spoolss_StartDocPrinter s;
1254 struct spoolss_DocumentInfo1 info1;
1255 struct spoolss_StartPagePrinter sp;
1256 struct spoolss_WritePrinter w;
1257 struct spoolss_EndPagePrinter ep;
1258 struct spoolss_EndDocPrinter e;
1259 int i;
1260 uint32_t job_id;
1261 uint32_t num_written;
1263 torture_comment(tctx, "Testing StartDocPrinter\n");
1265 s.in.handle = handle;
1266 s.in.level = 1;
1267 s.in.info.info1 = &info1;
1268 s.out.job_id = &job_id;
1269 info1.document_name = "TorturePrintJob";
1270 info1.output_file = NULL;
1271 info1.datatype = "RAW";
1273 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1274 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1275 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1277 for (i=1; i < 4; i++) {
1278 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1280 sp.in.handle = handle;
1282 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1283 torture_assert_ntstatus_ok(tctx, status,
1284 "dcerpc_spoolss_StartPagePrinter failed");
1285 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1287 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1289 w.in.handle = handle;
1290 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1291 w.out.num_written = &num_written;
1293 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1294 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1295 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1297 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1299 ep.in.handle = handle;
1301 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1302 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1303 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1306 torture_comment(tctx, "Testing EndDocPrinter\n");
1308 e.in.handle = handle;
1310 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1311 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1312 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1314 ret &= test_AddJob(tctx, p, handle);
1315 ret &= test_EnumJobs(tctx, p, handle);
1317 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1319 return ret;
1322 static bool test_PausePrinter(struct torture_context *tctx,
1323 struct dcerpc_pipe *p,
1324 struct policy_handle *handle)
1326 NTSTATUS status;
1327 struct spoolss_SetPrinter r;
1328 struct spoolss_SetPrinterInfoCtr info_ctr;
1329 struct spoolss_DevmodeContainer devmode_ctr;
1330 struct sec_desc_buf secdesc_ctr;
1332 info_ctr.level = 0;
1333 info_ctr.info.info0 = NULL;
1335 ZERO_STRUCT(devmode_ctr);
1336 ZERO_STRUCT(secdesc_ctr);
1338 r.in.handle = handle;
1339 r.in.info_ctr = &info_ctr;
1340 r.in.devmode_ctr = &devmode_ctr;
1341 r.in.secdesc_ctr = &secdesc_ctr;
1342 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1344 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1346 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1348 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1350 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1352 return true;
1355 static bool test_ResumePrinter(struct torture_context *tctx,
1356 struct dcerpc_pipe *p,
1357 struct policy_handle *handle)
1359 NTSTATUS status;
1360 struct spoolss_SetPrinter r;
1361 struct spoolss_SetPrinterInfoCtr info_ctr;
1362 struct spoolss_DevmodeContainer devmode_ctr;
1363 struct sec_desc_buf secdesc_ctr;
1365 info_ctr.level = 0;
1366 info_ctr.info.info0 = NULL;
1368 ZERO_STRUCT(devmode_ctr);
1369 ZERO_STRUCT(secdesc_ctr);
1371 r.in.handle = handle;
1372 r.in.info_ctr = &info_ctr;
1373 r.in.devmode_ctr = &devmode_ctr;
1374 r.in.secdesc_ctr = &secdesc_ctr;
1375 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
1377 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1379 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1381 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1383 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1385 return true;
1388 static bool test_GetPrinterData(struct torture_context *tctx,
1389 struct dcerpc_pipe *p,
1390 struct policy_handle *handle,
1391 const char *value_name)
1393 NTSTATUS status;
1394 struct spoolss_GetPrinterData r;
1395 uint32_t needed;
1396 enum winreg_Type type;
1397 union spoolss_PrinterData data;
1399 r.in.handle = handle;
1400 r.in.value_name = value_name;
1401 r.in.offered = 0;
1402 r.out.needed = &needed;
1403 r.out.type = &type;
1404 r.out.data = &data;
1406 torture_comment(tctx, "Testing GetPrinterData\n");
1408 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1409 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1411 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1412 r.in.offered = needed;
1414 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1415 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1417 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1420 return true;
1423 static bool test_GetPrinterDataEx(struct torture_context *tctx,
1424 struct dcerpc_pipe *p,
1425 struct policy_handle *handle,
1426 const char *key_name,
1427 const char *value_name)
1429 NTSTATUS status;
1430 struct spoolss_GetPrinterDataEx r;
1431 enum winreg_Type type;
1432 uint32_t needed;
1434 r.in.handle = handle;
1435 r.in.key_name = key_name;
1436 r.in.value_name = value_name;
1437 r.in.offered = 0;
1438 r.out.type = &type;
1439 r.out.needed = &needed;
1440 r.out.buffer = NULL;
1442 torture_comment(tctx, "Testing GetPrinterDataEx\n");
1444 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1447 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1448 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1450 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1453 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1454 r.in.offered = needed;
1455 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1457 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1458 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1460 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
1463 return true;
1466 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
1467 struct policy_handle *handle)
1469 NTSTATUS status;
1470 struct spoolss_EnumPrinterData r;
1472 ZERO_STRUCT(r);
1473 r.in.handle = handle;
1474 r.in.enum_index = 0;
1476 do {
1477 uint32_t value_size = 0;
1478 uint32_t data_size = 0;
1479 enum winreg_Type type = 0;
1481 r.in.value_offered = value_size;
1482 r.out.value_needed = &value_size;
1483 r.in.data_offered = data_size;
1484 r.out.data_needed = &data_size;
1486 r.out.type = &type;
1487 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1489 torture_comment(tctx, "Testing EnumPrinterData\n");
1491 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1493 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1495 r.in.value_offered = value_size;
1496 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1497 r.in.data_offered = data_size;
1498 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1500 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1502 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1504 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1506 test_GetPrinterDataEx(tctx,
1507 p, handle, "PrinterDriverData",
1508 r.out.value_name);
1510 r.in.enum_index++;
1512 } while (W_ERROR_IS_OK(r.out.result));
1514 return true;
1517 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
1518 struct dcerpc_pipe *p,
1519 struct policy_handle *handle)
1521 NTSTATUS status;
1522 struct spoolss_EnumPrinterDataEx r;
1523 struct spoolss_PrinterEnumValues *info;
1524 uint32_t needed;
1525 uint32_t count;
1527 r.in.handle = handle;
1528 r.in.key_name = "PrinterDriverData";
1529 r.in.offered = 0;
1530 r.out.needed = &needed;
1531 r.out.count = &count;
1532 r.out.info = &info;
1534 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1536 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1537 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1539 r.in.offered = needed;
1541 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1543 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1545 return true;
1549 static bool test_DeletePrinterData(struct torture_context *tctx,
1550 struct dcerpc_pipe *p,
1551 struct policy_handle *handle,
1552 const char *value_name)
1554 NTSTATUS status;
1555 struct spoolss_DeletePrinterData r;
1557 r.in.handle = handle;
1558 r.in.value_name = value_name;
1560 torture_comment(tctx, "Testing DeletePrinterData\n");
1562 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1564 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1566 return true;
1569 static bool test_SetPrinterData(struct torture_context *tctx,
1570 struct dcerpc_pipe *p,
1571 struct policy_handle *handle)
1573 NTSTATUS status;
1574 struct spoolss_SetPrinterData r;
1575 const char *value_name = "spottyfoot";
1577 r.in.handle = handle;
1578 r.in.value_name = value_name;
1579 r.in.type = REG_SZ;
1580 r.in.data.string = "dog";
1582 torture_comment(tctx, "Testing SetPrinterData\n");
1584 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1586 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1588 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1589 return false;
1592 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1593 return false;
1596 return true;
1599 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
1600 struct dcerpc_pipe *p,
1601 struct policy_handle *handle)
1603 NTSTATUS status;
1604 struct dcerpc_binding *b;
1605 struct dcerpc_pipe *p2;
1606 struct spoolss_ClosePrinter cp;
1608 /* only makes sense on SMB */
1609 if (p->conn->transport.transport != NCACN_NP) {
1610 return true;
1613 torture_comment(tctx, "testing close on secondary pipe\n");
1615 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1616 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1618 status = dcerpc_secondary_connection(p, &p2, b);
1619 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1621 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1622 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1624 cp.in.handle = handle;
1625 cp.out.handle = handle;
1627 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1628 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1629 "ERROR: Allowed close on secondary connection");
1631 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1632 "Unexpected fault code");
1634 talloc_free(p2);
1636 return true;
1639 static bool test_OpenPrinter_badname(struct torture_context *tctx,
1640 struct dcerpc_pipe *p, const char *name)
1642 NTSTATUS status;
1643 struct spoolss_OpenPrinter op;
1644 struct spoolss_OpenPrinterEx opEx;
1645 struct policy_handle handle;
1646 bool ret = true;
1648 op.in.printername = name;
1649 op.in.datatype = NULL;
1650 op.in.devmode_ctr.devmode= NULL;
1651 op.in.access_mask = 0;
1652 op.out.handle = &handle;
1654 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1656 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1657 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1658 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1659 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1660 name, win_errstr(op.out.result));
1663 if (W_ERROR_IS_OK(op.out.result)) {
1664 ret &=test_ClosePrinter(tctx, p, &handle);
1667 opEx.in.printername = name;
1668 opEx.in.datatype = NULL;
1669 opEx.in.devmode_ctr.devmode = NULL;
1670 opEx.in.access_mask = 0;
1671 opEx.in.level = 1;
1672 opEx.in.userlevel.level1 = NULL;
1673 opEx.out.handle = &handle;
1675 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1677 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1678 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1679 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1680 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1681 name, win_errstr(opEx.out.result));
1684 if (W_ERROR_IS_OK(opEx.out.result)) {
1685 ret &=test_ClosePrinter(tctx, p, &handle);
1688 return ret;
1691 static bool test_OpenPrinter(struct torture_context *tctx,
1692 struct dcerpc_pipe *p,
1693 const char *name)
1695 NTSTATUS status;
1696 struct spoolss_OpenPrinter r;
1697 struct policy_handle handle;
1698 bool ret = true;
1700 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1701 r.in.datatype = NULL;
1702 r.in.devmode_ctr.devmode= NULL;
1703 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1704 r.out.handle = &handle;
1706 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1708 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1710 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1712 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1714 if (!test_GetPrinter(tctx, p, &handle)) {
1715 ret = false;
1718 if (!torture_setting_bool(tctx, "samba3", false)) {
1719 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1720 ret = false;
1724 if (!test_ClosePrinter(tctx, p, &handle)) {
1725 ret = false;
1728 return ret;
1731 static bool call_OpenPrinterEx(struct torture_context *tctx,
1732 struct dcerpc_pipe *p,
1733 const char *name, struct policy_handle *handle)
1735 struct spoolss_OpenPrinterEx r;
1736 struct spoolss_UserLevel1 userlevel1;
1737 NTSTATUS status;
1739 if (name && name[0]) {
1740 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1741 dcerpc_server_name(p), name);
1742 } else {
1743 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1744 dcerpc_server_name(p));
1747 r.in.datatype = NULL;
1748 r.in.devmode_ctr.devmode= NULL;
1749 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1750 r.in.level = 1;
1751 r.in.userlevel.level1 = &userlevel1;
1752 r.out.handle = handle;
1754 userlevel1.size = 1234;
1755 userlevel1.client = "hello";
1756 userlevel1.user = "spottyfoot!";
1757 userlevel1.build = 1;
1758 userlevel1.major = 2;
1759 userlevel1.minor = 3;
1760 userlevel1.processor = 4;
1762 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1764 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1766 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1768 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1770 return true;
1773 static bool test_OpenPrinterEx(struct torture_context *tctx,
1774 struct dcerpc_pipe *p,
1775 const char *name)
1777 struct policy_handle handle;
1778 bool ret = true;
1780 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1781 return false;
1784 if (!test_GetPrinter(tctx, p, &handle)) {
1785 ret = false;
1788 if (!test_EnumForms(tctx, p, &handle, false)) {
1789 ret = false;
1792 if (!test_AddForm(tctx, p, &handle, false)) {
1793 ret = false;
1796 if (!test_EnumPrinterData(tctx, p, &handle)) {
1797 ret = false;
1800 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1801 ret = false;
1804 if (!test_PausePrinter(tctx, p, &handle)) {
1805 ret = false;
1808 if (!test_DoPrintTest(tctx, p, &handle)) {
1809 ret = false;
1812 if (!test_ResumePrinter(tctx, p, &handle)) {
1813 ret = false;
1816 if (!test_SetPrinterData(tctx, p, &handle)) {
1817 ret = false;
1820 if (!torture_setting_bool(tctx, "samba3", false)) {
1821 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1822 ret = false;
1826 if (!test_ClosePrinter(tctx, p, &handle)) {
1827 ret = false;
1830 return ret;
1833 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1835 struct spoolss_EnumPrinters r;
1836 NTSTATUS status;
1837 uint16_t levels[] = {1, 2, 4, 5};
1838 int i;
1839 bool ret = true;
1841 for (i=0;i<ARRAY_SIZE(levels);i++) {
1842 union spoolss_PrinterInfo *info;
1843 int j;
1844 uint32_t needed;
1845 uint32_t count;
1847 r.in.flags = PRINTER_ENUM_LOCAL;
1848 r.in.server = "";
1849 r.in.level = levels[i];
1850 r.in.buffer = NULL;
1851 r.in.offered = 0;
1852 r.out.needed = &needed;
1853 r.out.count = &count;
1854 r.out.info = &info;
1856 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1858 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1859 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1861 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1862 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1863 data_blob_clear(&blob);
1864 r.in.buffer = &blob;
1865 r.in.offered = needed;
1866 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1869 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1871 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1873 if (!info) {
1874 torture_comment(tctx, "No printers returned\n");
1875 return true;
1878 for (j=0;j<count;j++) {
1879 if (r.in.level == 1) {
1880 char *unc = talloc_strdup(tctx, info[j].info1.name);
1881 char *slash, *name;
1882 name = unc;
1883 if (unc[0] == '\\' && unc[1] == '\\') {
1884 unc +=2;
1886 slash = strchr(unc, '\\');
1887 if (slash) {
1888 slash++;
1889 name = slash;
1891 if (!test_OpenPrinter(tctx, p, name)) {
1892 ret = false;
1894 if (!test_OpenPrinterEx(tctx, p, name)) {
1895 ret = false;
1901 return ret;
1904 #if 0
1905 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
1906 struct policy_handle *handle,
1907 const char *driver_name)
1909 NTSTATUS status;
1910 struct spoolss_GetPrinterDriver2 r;
1911 uint32_t needed;
1912 uint32_t server_major_version;
1913 uint32_t server_minor_version;
1915 r.in.handle = handle;
1916 r.in.architecture = "W32X86";
1917 r.in.level = 1;
1918 r.in.buffer = NULL;
1919 r.in.offered = 0;
1920 r.in.client_major_version = 0;
1921 r.in.client_minor_version = 0;
1922 r.out.needed = &needed;
1923 r.out.server_major_version = &server_major_version;
1924 r.out.server_minor_version = &server_minor_version;
1926 printf("Testing GetPrinterDriver2\n");
1928 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1931 return false;
1934 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1935 r.in.offered = needed;
1936 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1939 if (!NT_STATUS_IS_OK(status)) {
1940 printf("GetPrinterDriver2 failed - %s\n",
1941 nt_errstr(status));
1942 return false;
1945 if (!W_ERROR_IS_OK(r.out.result)) {
1946 printf("GetPrinterDriver2 failed - %s\n",
1947 win_errstr(r.out.result));
1948 return false;
1951 return true;
1953 #endif
1955 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
1956 struct dcerpc_pipe *p)
1958 struct spoolss_EnumPrinterDrivers r;
1959 NTSTATUS status;
1960 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1961 int i;
1963 for (i=0;i<ARRAY_SIZE(levels);i++) {
1965 uint32_t needed;
1966 uint32_t count;
1967 union spoolss_DriverInfo *info;
1969 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1970 r.in.environment = "Windows NT x86";
1971 r.in.level = levels[i];
1972 r.in.buffer = NULL;
1973 r.in.offered = 0;
1974 r.out.needed = &needed;
1975 r.out.count = &count;
1976 r.out.info = &info;
1978 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1980 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1982 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1984 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1985 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1986 data_blob_clear(&blob);
1987 r.in.buffer = &blob;
1988 r.in.offered = needed;
1989 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1992 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1994 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1996 if (!info) {
1997 torture_comment(tctx, "No printer drivers returned\n");
1998 break;
2002 return true;
2005 static bool test_EnumPrinterKey(struct torture_context *tctx,
2006 struct dcerpc_pipe *p,
2007 struct policy_handle *handle,
2008 const char *key_name,
2009 const char ***array)
2011 struct spoolss_EnumPrinterKey r;
2012 uint32_t needed = 0;
2013 union spoolss_KeyNames key_buffer;
2014 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
2015 uint32_t _ndr_size;
2016 int i;
2018 r.in.handle = handle;
2019 r.in.key_name = key_name;
2020 r.out.key_buffer = &key_buffer;
2021 r.out.needed = &needed;
2022 r.out._ndr_size = &_ndr_size;
2024 for (i=0; i < ARRAY_SIZE(offered); i++) {
2026 if (offered[i] < 0 && needed) {
2027 if (needed <= 4) {
2028 continue;
2030 r.in.offered = needed + offered[i];
2031 } else {
2032 r.in.offered = offered[i];
2035 ZERO_STRUCT(key_buffer);
2037 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
2039 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
2040 "failed to call EnumPrinterKey");
2041 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2043 torture_assert(tctx, (_ndr_size == r.in.offered/2),
2044 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
2045 _ndr_size, r.in.offered/2));
2047 r.in.offered = needed;
2048 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
2049 "failed to call EnumPrinterKey");
2052 if (offered[i] > 0) {
2053 torture_assert_werr_ok(tctx, r.out.result,
2054 "failed to call EnumPrinterKey");
2057 torture_assert(tctx, (_ndr_size == r.in.offered/2),
2058 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
2059 _ndr_size, r.in.offered/2));
2061 torture_assert(tctx, (*r.out.needed <= r.in.offered),
2062 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
2064 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
2065 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
2067 if (key_buffer.string_array) {
2068 uint32_t calc_needed = 0;
2069 int s;
2070 for (s=0; key_buffer.string_array[s]; s++) {
2071 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
2073 if (!key_buffer.string_array[0]) {
2074 calc_needed += 2;
2076 calc_needed += 2;
2078 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
2079 "EnumPrinterKey unexpected size");
2083 if (array) {
2084 *array = key_buffer.string_array;
2087 return true;
2090 bool test_printer_keys(struct torture_context *tctx,
2091 struct dcerpc_pipe *p,
2092 struct policy_handle *handle)
2094 const char **key_array = NULL;
2095 int i;
2098 struct spoolss_EnumPrinterKey r;
2099 uint32_t needed;
2100 struct spoolss_StringArray2 key_buffer;
2102 r.in.handle = handle;
2103 r.in.key_name = "";
2104 r.in.offered = 0;
2105 r.out.key_buffer = &key_buffer;
2106 r.out.needed = &needed;
2108 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
2109 "failed to call EnumPrinterKey");
2110 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2111 r.in.offered = needed;
2112 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
2113 "failed to call EnumPrinterKey");
2115 torture_assert_werr_ok(tctx, r.out.result,
2116 "failed to call EnumPrinterKey");
2118 key_array = key_buffer.string;
2121 for (i=0; key_array[i]; i++) {
2122 struct spoolss_EnumPrinterDataEx r;
2123 uint32_t count;
2124 struct spoolss_PrinterEnumValues *info;
2125 uint32_t needed;
2127 r.in.handle = handle;
2128 r.in.key_name = key_array[i];
2129 r.in.offered = 0;
2130 r.out.count = &count;
2131 r.out.info = &info;
2132 r.out.needed = &needed;
2134 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2135 "failed to call EnumPrinterDataEx");
2136 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2137 r.in.offered = needed;
2138 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2139 "failed to call EnumPrinterDataEx");
2141 torture_assert_werr_ok(tctx, r.out.result,
2142 "failed to call EnumPrinterDataEx");
2145 return true;
2148 bool torture_rpc_spoolss(struct torture_context *torture)
2150 NTSTATUS status;
2151 struct dcerpc_pipe *p;
2152 bool ret = true;
2153 struct test_spoolss_context *ctx;
2155 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2156 if (!NT_STATUS_IS_OK(status)) {
2157 return false;
2160 ctx = talloc_zero(torture, struct test_spoolss_context);
2162 ret &= test_OpenPrinter_server(torture, p, ctx);
2164 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2165 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2166 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2167 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2168 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2169 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2170 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2171 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2172 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2173 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2174 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2175 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2176 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2177 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2178 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2179 ret &= test_EnumPorts(torture, p, ctx);
2180 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2181 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2182 ret &= test_EnumPrinterDrivers(torture, p, ctx);
2183 ret &= test_EnumMonitors(torture, p, ctx);
2184 ret &= test_EnumPrintProcessors(torture, p, ctx);
2185 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2186 ret &= test_EnumPrinters(torture, p, ctx);
2187 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2188 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2189 ret &= test_OpenPrinter_badname(torture, p, "");
2190 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2191 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2192 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2193 ret &= test_OpenPrinter_badname(torture, p,
2194 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2197 ret &= test_AddPort(torture, p);
2198 ret &= test_EnumPorts_old(torture, p);
2199 ret &= test_EnumPrinters_old(torture, p);
2200 ret &= test_EnumPrinterDrivers_old(torture, p);
2202 return ret;