s4-smbtorture: fix spoolss SD test against w2k8r2.
[Samba/cd1.git] / source4 / torture / rpc / spoolss.c
blobec7233516ce7fb00a917f044eb39fa24e65fffb4
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-2010
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 "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "libcli/security/security.h"
31 #include "torture/rpc/rpc.h"
32 #include "param/param.h"
34 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
35 #define TORTURE_PRINTER "torture_printer"
36 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
37 #define TORTURE_PRINTER_EX "torture_printer_ex"
39 struct test_spoolss_context {
40 /* print server handle */
41 struct policy_handle server_handle;
43 /* for EnumPorts */
44 uint32_t port_count[3];
45 union spoolss_PortInfo *ports[3];
47 /* for EnumPrinterDrivers */
48 uint32_t driver_count[8];
49 union spoolss_DriverInfo *drivers[8];
51 /* for EnumMonitors */
52 uint32_t monitor_count[3];
53 union spoolss_MonitorInfo *monitors[3];
55 /* for EnumPrintProcessors */
56 uint32_t print_processor_count[2];
57 union spoolss_PrintProcessorInfo *print_processors[2];
59 /* for EnumPrinters */
60 uint32_t printer_count[6];
61 union spoolss_PrinterInfo *printers[6];
64 #define COMPARE_STRING(tctx, c,r,e) \
65 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
67 /* not every compiler supports __typeof__() */
68 #if (__GNUC__ >= 3)
69 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
70 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
71 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
73 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
74 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
76 } while(0)
77 #else
78 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
79 #endif
81 #define COMPARE_UINT32(tctx, c, r, e) do {\
82 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
83 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
84 } while(0)
86 #define COMPARE_UINT64(tctx, c, r, e) do {\
87 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
88 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
89 } while(0)
92 #define COMPARE_NTTIME(tctx, c, r, e) do {\
93 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
94 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
95 } while(0)
97 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
98 int __i; \
99 if (!c.e && !r.e) { \
100 break; \
102 if (c.e && !r.e) { \
103 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
105 if (!c.e && r.e) { \
106 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
108 for (__i=0;c.e[__i] != NULL; __i++) { \
109 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
111 } while(0)
113 #define CHECK_ALIGN(size, n) do {\
114 if (size % n) {\
115 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
116 size, n, size + n - (size % n));\
118 } while(0)
120 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
122 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
123 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
124 uint32_t round_size = DO_ROUND(size, align);\
125 if (round_size != needed) {\
126 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
127 CHECK_ALIGN(size, align);\
129 } while(0)
131 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
132 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
133 uint32_t round_size = DO_ROUND(size, align);\
134 if (round_size != needed) {\
135 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
136 CHECK_ALIGN(size, align);\
138 } while(0)
140 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
141 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
142 uint32_t round_size = DO_ROUND(size, align);\
143 if (round_size != needed) {\
144 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
145 CHECK_ALIGN(size, align);\
147 } while(0)
149 static bool test_OpenPrinter_server(struct torture_context *tctx,
150 struct dcerpc_pipe *p,
151 struct policy_handle *server_handle)
153 NTSTATUS status;
154 struct spoolss_OpenPrinter op;
156 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
157 op.in.datatype = NULL;
158 op.in.devmode_ctr.devmode= NULL;
159 op.in.access_mask = 0;
160 op.out.handle = server_handle;
162 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
164 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
165 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
166 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
168 return true;
171 static bool test_EnumPorts(struct torture_context *tctx,
172 struct dcerpc_pipe *p,
173 struct test_spoolss_context *ctx)
175 NTSTATUS status;
176 struct spoolss_EnumPorts r;
177 uint16_t levels[] = { 1, 2 };
178 int i, j;
180 for (i=0;i<ARRAY_SIZE(levels);i++) {
181 int level = levels[i];
182 DATA_BLOB blob;
183 uint32_t needed;
184 uint32_t count;
185 union spoolss_PortInfo *info;
187 r.in.servername = "";
188 r.in.level = level;
189 r.in.buffer = NULL;
190 r.in.offered = 0;
191 r.out.needed = &needed;
192 r.out.count = &count;
193 r.out.info = &info;
195 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
197 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
198 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
199 if (W_ERROR_IS_OK(r.out.result)) {
200 /* TODO: do some more checks here */
201 continue;
203 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
204 "EnumPorts unexpected return code");
206 blob = data_blob_talloc(ctx, NULL, needed);
207 data_blob_clear(&blob);
208 r.in.buffer = &blob;
209 r.in.offered = needed;
211 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
212 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
214 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
216 torture_assert(tctx, info, "EnumPorts returned no info");
218 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
220 ctx->port_count[level] = count;
221 ctx->ports[level] = info;
224 for (i=1;i<ARRAY_SIZE(levels);i++) {
225 int level = levels[i];
226 int old_level = levels[i-1];
227 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
228 "EnumPorts invalid value");
230 /* if the array sizes are not the same we would maybe segfault in the following code */
232 for (i=0;i<ARRAY_SIZE(levels);i++) {
233 int level = levels[i];
234 for (j=0;j<ctx->port_count[level];j++) {
235 union spoolss_PortInfo *cur = &ctx->ports[level][j];
236 union spoolss_PortInfo *ref = &ctx->ports[2][j];
237 switch (level) {
238 case 1:
239 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
240 break;
241 case 2:
242 /* level 2 is our reference, and it makes no sense to compare it to itself */
243 break;
248 return true;
251 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
252 struct dcerpc_pipe *p,
253 struct test_spoolss_context *ctx)
255 NTSTATUS status;
256 struct spoolss_GetPrintProcessorDirectory r;
257 struct {
258 uint16_t level;
259 const char *server;
260 } levels[] = {{
261 .level = 1,
262 .server = NULL
264 .level = 1,
265 .server = ""
267 .level = 78,
268 .server = ""
270 .level = 1,
271 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
273 .level = 1024,
274 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
277 int i;
278 uint32_t needed;
280 for (i=0;i<ARRAY_SIZE(levels);i++) {
281 int level = levels[i].level;
282 DATA_BLOB blob;
284 r.in.server = levels[i].server;
285 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
286 r.in.level = level;
287 r.in.buffer = NULL;
288 r.in.offered = 0;
289 r.out.needed = &needed;
291 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
293 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
294 torture_assert_ntstatus_ok(tctx, status,
295 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
296 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
297 "GetPrintProcessorDirectory unexpected return code");
299 blob = data_blob_talloc(ctx, NULL, needed);
300 data_blob_clear(&blob);
301 r.in.buffer = &blob;
302 r.in.offered = needed;
304 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
305 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
307 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
309 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
312 return true;
316 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
317 struct dcerpc_pipe *p,
318 struct test_spoolss_context *ctx)
320 NTSTATUS status;
321 struct spoolss_GetPrinterDriverDirectory r;
322 struct {
323 uint16_t level;
324 const char *server;
325 } levels[] = {{
326 .level = 1,
327 .server = NULL
329 .level = 1,
330 .server = ""
332 .level = 78,
333 .server = ""
335 .level = 1,
336 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
338 .level = 1024,
339 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
342 int i;
343 uint32_t needed;
345 for (i=0;i<ARRAY_SIZE(levels);i++) {
346 int level = levels[i].level;
347 DATA_BLOB blob;
349 r.in.server = levels[i].server;
350 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
351 r.in.level = level;
352 r.in.buffer = NULL;
353 r.in.offered = 0;
354 r.out.needed = &needed;
356 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
358 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
359 torture_assert_ntstatus_ok(tctx, status,
360 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
361 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
362 "GetPrinterDriverDirectory unexpected return code");
364 blob = data_blob_talloc(ctx, NULL, needed);
365 data_blob_clear(&blob);
366 r.in.buffer = &blob;
367 r.in.offered = needed;
369 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
370 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
372 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
374 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
377 return true;
380 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
381 struct dcerpc_pipe *p,
382 struct test_spoolss_context *ctx,
383 const char *architecture)
385 NTSTATUS status;
386 struct spoolss_EnumPrinterDrivers r;
387 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
388 int i, j;
390 for (i=0;i<ARRAY_SIZE(levels);i++) {
391 int level = levels[i];
392 DATA_BLOB blob;
393 uint32_t needed;
394 uint32_t count;
395 union spoolss_DriverInfo *info;
397 /* FIXME: gd, come back and fix "" as server, and handle
398 * priority of returned error codes in torture test and samba 3
399 * server */
401 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
402 r.in.environment = architecture;
403 r.in.level = level;
404 r.in.buffer = NULL;
405 r.in.offered = 0;
406 r.out.needed = &needed;
407 r.out.count = &count;
408 r.out.info = &info;
410 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
412 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
413 torture_assert_ntstatus_ok(tctx, status,
414 "dcerpc_spoolss_EnumPrinterDrivers failed");
415 if (W_ERROR_IS_OK(r.out.result)) {
416 /* TODO: do some more checks here */
417 continue;
419 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
420 blob = data_blob_talloc(ctx, NULL, needed);
421 data_blob_clear(&blob);
422 r.in.buffer = &blob;
423 r.in.offered = needed;
425 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
426 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
429 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
431 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
433 ctx->driver_count[level] = count;
434 ctx->drivers[level] = info;
437 for (i=1;i<ARRAY_SIZE(levels);i++) {
438 int level = levels[i];
439 int old_level = levels[i-1];
441 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
442 "EnumPrinterDrivers invalid value");
445 for (i=0;i<ARRAY_SIZE(levels);i++) {
446 int level = levels[i];
448 for (j=0;j<ctx->driver_count[level];j++) {
449 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
450 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
452 switch (level) {
453 case 1:
454 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
455 break;
456 case 2:
457 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
458 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
459 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
460 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
461 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
462 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
463 break;
464 case 3:
465 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
466 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
467 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
468 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
469 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
470 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
471 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
472 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
473 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
474 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
475 break;
476 case 4:
477 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
478 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
479 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
480 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
481 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
482 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
483 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
484 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
485 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
486 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
487 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
488 break;
489 case 5:
490 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
491 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
492 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
493 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
494 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
495 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
496 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
497 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
498 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
499 break;
500 case 6:
501 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
502 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
503 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
504 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
505 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
506 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
507 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
508 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
509 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
510 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
511 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
512 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
513 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
514 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
515 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
516 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
517 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
518 break;
519 case 8:
520 /* level 8 is our reference, and it makes no sense to compare it to itself */
521 break;
526 return true;
529 static bool test_EnumMonitors(struct torture_context *tctx,
530 struct dcerpc_pipe *p,
531 struct test_spoolss_context *ctx)
533 NTSTATUS status;
534 struct spoolss_EnumMonitors r;
535 uint16_t levels[] = { 1, 2 };
536 int i, j;
538 for (i=0;i<ARRAY_SIZE(levels);i++) {
539 int level = levels[i];
540 DATA_BLOB blob;
541 uint32_t needed;
542 uint32_t count;
543 union spoolss_MonitorInfo *info;
545 r.in.servername = "";
546 r.in.level = level;
547 r.in.buffer = NULL;
548 r.in.offered = 0;
549 r.out.needed = &needed;
550 r.out.count = &count;
551 r.out.info = &info;
553 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
555 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
556 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
557 if (W_ERROR_IS_OK(r.out.result)) {
558 /* TODO: do some more checks here */
559 continue;
561 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
562 "EnumMonitors failed");
564 blob = data_blob_talloc(ctx, NULL, needed);
565 data_blob_clear(&blob);
566 r.in.buffer = &blob;
567 r.in.offered = needed;
569 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
570 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
572 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
574 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
576 ctx->monitor_count[level] = count;
577 ctx->monitors[level] = info;
580 for (i=1;i<ARRAY_SIZE(levels);i++) {
581 int level = levels[i];
582 int old_level = levels[i-1];
583 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
584 "EnumMonitors invalid value");
587 for (i=0;i<ARRAY_SIZE(levels);i++) {
588 int level = levels[i];
589 for (j=0;j<ctx->monitor_count[level];j++) {
590 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
591 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
592 switch (level) {
593 case 1:
594 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
595 break;
596 case 2:
597 /* level 2 is our reference, and it makes no sense to compare it to itself */
598 break;
603 return true;
606 static bool test_EnumPrintProcessors(struct torture_context *tctx,
607 struct dcerpc_pipe *p,
608 struct test_spoolss_context *ctx)
610 NTSTATUS status;
611 struct spoolss_EnumPrintProcessors r;
612 uint16_t levels[] = { 1 };
613 int i, j;
615 for (i=0;i<ARRAY_SIZE(levels);i++) {
616 int level = levels[i];
617 DATA_BLOB blob;
618 uint32_t needed;
619 uint32_t count;
620 union spoolss_PrintProcessorInfo *info;
622 r.in.servername = "";
623 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
624 r.in.level = level;
625 r.in.buffer = NULL;
626 r.in.offered = 0;
627 r.out.needed = &needed;
628 r.out.count = &count;
629 r.out.info = &info;
631 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
633 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
634 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
635 if (W_ERROR_IS_OK(r.out.result)) {
636 /* TODO: do some more checks here */
637 continue;
639 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
640 "EnumPrintProcessors unexpected return code");
642 blob = data_blob_talloc(ctx, NULL, needed);
643 data_blob_clear(&blob);
644 r.in.buffer = &blob;
645 r.in.offered = needed;
647 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
648 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
650 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
652 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
654 ctx->print_processor_count[level] = count;
655 ctx->print_processors[level] = info;
658 for (i=1;i<ARRAY_SIZE(levels);i++) {
659 int level = levels[i];
660 int old_level = levels[i-1];
661 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
662 "EnumPrintProcessors failed");
665 for (i=0;i<ARRAY_SIZE(levels);i++) {
666 int level = levels[i];
667 for (j=0;j<ctx->print_processor_count[level];j++) {
668 #if 0
669 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
670 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
671 #endif
672 switch (level) {
673 case 1:
674 /* level 1 is our reference, and it makes no sense to compare it to itself */
675 break;
680 return true;
683 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
684 struct dcerpc_pipe *p,
685 struct test_spoolss_context *ctx)
687 NTSTATUS status;
688 struct spoolss_EnumPrintProcDataTypes r;
689 uint16_t levels[] = { 1 };
690 int i;
692 for (i=0;i<ARRAY_SIZE(levels);i++) {
693 int level = levels[i];
694 DATA_BLOB blob;
695 uint32_t needed;
696 uint32_t count;
697 union spoolss_PrintProcDataTypesInfo *info;
699 r.in.servername = "";
700 r.in.print_processor_name = "winprint";
701 r.in.level = level;
702 r.in.buffer = NULL;
703 r.in.offered = 0;
704 r.out.needed = &needed;
705 r.out.count = &count;
706 r.out.info = &info;
708 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
710 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
711 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
712 if (W_ERROR_IS_OK(r.out.result)) {
713 /* TODO: do some more checks here */
714 continue;
716 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
717 "EnumPrintProcDataTypes unexpected return code");
719 blob = data_blob_talloc(ctx, NULL, needed);
720 data_blob_clear(&blob);
721 r.in.buffer = &blob;
722 r.in.offered = needed;
724 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
725 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
727 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
729 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
733 return true;
737 static bool test_EnumPrinters(struct torture_context *tctx,
738 struct dcerpc_pipe *p,
739 struct test_spoolss_context *ctx)
741 struct spoolss_EnumPrinters r;
742 NTSTATUS status;
743 uint16_t levels[] = { 0, 1, 2, 4, 5 };
744 int i, j;
746 for (i=0;i<ARRAY_SIZE(levels);i++) {
747 int level = levels[i];
748 DATA_BLOB blob;
749 uint32_t needed;
750 uint32_t count;
751 union spoolss_PrinterInfo *info;
753 r.in.flags = PRINTER_ENUM_LOCAL;
754 r.in.server = "";
755 r.in.level = level;
756 r.in.buffer = NULL;
757 r.in.offered = 0;
758 r.out.needed = &needed;
759 r.out.count = &count;
760 r.out.info = &info;
762 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
764 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
765 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
766 if (W_ERROR_IS_OK(r.out.result)) {
767 /* TODO: do some more checks here */
768 continue;
770 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
771 "EnumPrinters unexpected return code");
773 blob = data_blob_talloc(ctx, NULL, needed);
774 data_blob_clear(&blob);
775 r.in.buffer = &blob;
776 r.in.offered = needed;
778 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
779 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
781 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
783 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
785 ctx->printer_count[level] = count;
786 ctx->printers[level] = info;
789 for (i=1;i<ARRAY_SIZE(levels);i++) {
790 int level = levels[i];
791 int old_level = levels[i-1];
792 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
793 "EnumPrinters invalid value");
796 for (i=0;i<ARRAY_SIZE(levels);i++) {
797 int level = levels[i];
798 for (j=0;j<ctx->printer_count[level];j++) {
799 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
800 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
801 switch (level) {
802 case 0:
803 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
804 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
805 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
806 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
807 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
808 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
809 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
810 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
811 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
812 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
813 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
814 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
815 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
816 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
817 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
818 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
819 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
820 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
821 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
822 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
823 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
824 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
825 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
826 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
827 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
828 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
829 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
830 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
831 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
832 break;
833 case 1:
834 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
835 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
836 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
837 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
838 break;
839 case 2:
840 /* level 2 is our reference, and it makes no sense to compare it to itself */
841 break;
842 case 4:
843 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
844 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
845 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
846 break;
847 case 5:
848 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
849 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
850 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
851 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
852 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
853 break;
858 /* TODO:
859 * - verify that the port of a printer was in the list returned by EnumPorts
862 return true;
865 static bool test_GetPrinterDriver2(struct torture_context *tctx,
866 struct dcerpc_pipe *p,
867 struct policy_handle *handle,
868 const char *driver_name);
870 bool test_GetPrinter_level(struct torture_context *tctx,
871 struct dcerpc_pipe *p,
872 struct policy_handle *handle,
873 uint32_t level,
874 union spoolss_PrinterInfo *info)
876 struct spoolss_GetPrinter r;
877 uint32_t needed;
879 r.in.handle = handle;
880 r.in.level = level;
881 r.in.buffer = NULL;
882 r.in.offered = 0;
883 r.out.needed = &needed;
885 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
887 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
888 "GetPrinter failed");
890 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
891 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
892 data_blob_clear(&blob);
893 r.in.buffer = &blob;
894 r.in.offered = needed;
896 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
897 "GetPrinter failed");
900 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
902 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
904 if (info && r.out.info) {
905 *info = *r.out.info;
908 return true;
912 static bool test_GetPrinter(struct torture_context *tctx,
913 struct dcerpc_pipe *p,
914 struct policy_handle *handle)
916 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
917 int i;
919 for (i=0;i<ARRAY_SIZE(levels);i++) {
921 union spoolss_PrinterInfo info;
923 ZERO_STRUCT(info);
925 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
926 "failed to call GetPrinter");
928 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
929 torture_assert(tctx,
930 test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername),
931 "failed to call test_GetPrinterDriver2");
935 return true;
938 static bool test_SetPrinter(struct torture_context *tctx,
939 struct dcerpc_pipe *p,
940 struct policy_handle *handle,
941 struct spoolss_SetPrinterInfoCtr *info_ctr,
942 struct spoolss_DevmodeContainer *devmode_ctr,
943 struct sec_desc_buf *secdesc_ctr,
944 enum spoolss_PrinterControl command)
946 struct spoolss_SetPrinter r;
948 r.in.handle = handle;
949 r.in.info_ctr = info_ctr;
950 r.in.devmode_ctr = devmode_ctr;
951 r.in.secdesc_ctr = secdesc_ctr;
952 r.in.command = command;
954 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
956 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
957 "failed to call SetPrinter");
958 torture_assert_werr_ok(tctx, r.out.result,
959 "failed to call SetPrinter");
961 return true;
964 static bool test_SetPrinter_errors(struct torture_context *tctx,
965 struct dcerpc_pipe *p,
966 struct policy_handle *handle)
968 struct spoolss_SetPrinter r;
969 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
970 int i;
972 struct spoolss_SetPrinterInfoCtr info_ctr;
973 struct spoolss_DevmodeContainer devmode_ctr;
974 struct sec_desc_buf secdesc_ctr;
976 info_ctr.level = 0;
977 info_ctr.info.info0 = NULL;
979 ZERO_STRUCT(devmode_ctr);
980 ZERO_STRUCT(secdesc_ctr);
982 r.in.handle = handle;
983 r.in.info_ctr = &info_ctr;
984 r.in.devmode_ctr = &devmode_ctr;
985 r.in.secdesc_ctr = &secdesc_ctr;
986 r.in.command = 0;
988 torture_comment(tctx, "Testing SetPrinter all zero\n");
990 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
991 "failed to call SetPrinter");
992 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
993 "failed to call SetPrinter");
995 again:
996 for (i=0; i < ARRAY_SIZE(levels); i++) {
998 struct spoolss_SetPrinterInfo0 info0;
999 struct spoolss_SetPrinterInfo1 info1;
1000 struct spoolss_SetPrinterInfo2 info2;
1001 struct spoolss_SetPrinterInfo3 info3;
1002 struct spoolss_SetPrinterInfo4 info4;
1003 struct spoolss_SetPrinterInfo5 info5;
1004 struct spoolss_SetPrinterInfo6 info6;
1005 struct spoolss_SetPrinterInfo7 info7;
1006 struct spoolss_SetPrinterInfo8 info8;
1007 struct spoolss_SetPrinterInfo9 info9;
1010 info_ctr.level = levels[i];
1011 switch (levels[i]) {
1012 case 0:
1013 ZERO_STRUCT(info0);
1014 info_ctr.info.info0 = &info0;
1015 break;
1016 case 1:
1017 ZERO_STRUCT(info1);
1018 info_ctr.info.info1 = &info1;
1019 break;
1020 case 2:
1021 ZERO_STRUCT(info2);
1022 info_ctr.info.info2 = &info2;
1023 break;
1024 case 3:
1025 ZERO_STRUCT(info3);
1026 info_ctr.info.info3 = &info3;
1027 break;
1028 case 4:
1029 ZERO_STRUCT(info4);
1030 info_ctr.info.info4 = &info4;
1031 break;
1032 case 5:
1033 ZERO_STRUCT(info5);
1034 info_ctr.info.info5 = &info5;
1035 break;
1036 case 6:
1037 ZERO_STRUCT(info6);
1038 info_ctr.info.info6 = &info6;
1039 break;
1040 case 7:
1041 ZERO_STRUCT(info7);
1042 info_ctr.info.info7 = &info7;
1043 break;
1044 case 8:
1045 ZERO_STRUCT(info8);
1046 info_ctr.info.info8 = &info8;
1047 break;
1048 case 9:
1049 ZERO_STRUCT(info9);
1050 info_ctr.info.info9 = &info9;
1051 break;
1054 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1055 info_ctr.level, r.in.command);
1057 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1058 "failed to call SetPrinter");
1060 switch (r.in.command) {
1061 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1062 /* is ignored for all levels other then 0 */
1063 if (info_ctr.level > 0) {
1064 /* ignored then */
1065 break;
1067 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1068 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1069 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1070 if (info_ctr.level > 0) {
1071 /* is invalid for all levels other then 0 */
1072 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1073 "unexpected error code returned");
1074 continue;
1075 } else {
1076 torture_assert_werr_ok(tctx, r.out.result,
1077 "failed to call SetPrinter with non 0 command");
1078 continue;
1080 break;
1082 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1083 /* FIXME: gd needs further investigation */
1084 default:
1085 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1086 "unexpected error code returned");
1087 continue;
1090 switch (info_ctr.level) {
1091 case 1:
1092 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1093 "unexpected error code returned");
1094 break;
1095 case 2:
1096 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1097 "unexpected error code returned");
1098 break;
1099 case 3:
1100 case 4:
1101 case 5:
1102 case 7:
1103 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1104 "unexpected error code returned");
1105 break;
1106 case 9:
1107 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1108 "unexpected error code returned");
1109 break;
1110 default:
1111 torture_assert_werr_ok(tctx, r.out.result,
1112 "failed to call SetPrinter");
1113 break;
1117 if (r.in.command < 5) {
1118 r.in.command++;
1119 goto again;
1122 return true;
1125 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1127 if ((r->level == 2) && (r->info.info2)) {
1128 r->info.info2->secdesc_ptr = 0;
1129 r->info.info2->devmode_ptr = 0;
1133 static bool test_PrinterInfo(struct torture_context *tctx,
1134 struct dcerpc_pipe *p,
1135 struct policy_handle *handle)
1137 NTSTATUS status;
1138 struct spoolss_SetPrinter s;
1139 struct spoolss_GetPrinter q;
1140 struct spoolss_GetPrinter q0;
1141 struct spoolss_SetPrinterInfoCtr info_ctr;
1142 union spoolss_PrinterInfo info;
1143 struct spoolss_DevmodeContainer devmode_ctr;
1144 struct sec_desc_buf secdesc_ctr;
1145 uint32_t needed;
1146 bool ret = true;
1147 int i;
1149 uint32_t status_list[] = {
1150 /* these do not stick
1151 PRINTER_STATUS_PAUSED,
1152 PRINTER_STATUS_ERROR,
1153 PRINTER_STATUS_PENDING_DELETION, */
1154 PRINTER_STATUS_PAPER_JAM,
1155 PRINTER_STATUS_PAPER_OUT,
1156 PRINTER_STATUS_MANUAL_FEED,
1157 PRINTER_STATUS_PAPER_PROBLEM,
1158 PRINTER_STATUS_OFFLINE,
1159 PRINTER_STATUS_IO_ACTIVE,
1160 PRINTER_STATUS_BUSY,
1161 PRINTER_STATUS_PRINTING,
1162 PRINTER_STATUS_OUTPUT_BIN_FULL,
1163 PRINTER_STATUS_NOT_AVAILABLE,
1164 PRINTER_STATUS_WAITING,
1165 PRINTER_STATUS_PROCESSING,
1166 PRINTER_STATUS_INITIALIZING,
1167 PRINTER_STATUS_WARMING_UP,
1168 PRINTER_STATUS_TONER_LOW,
1169 PRINTER_STATUS_NO_TONER,
1170 PRINTER_STATUS_PAGE_PUNT,
1171 PRINTER_STATUS_USER_INTERVENTION,
1172 PRINTER_STATUS_OUT_OF_MEMORY,
1173 PRINTER_STATUS_DOOR_OPEN,
1174 PRINTER_STATUS_SERVER_UNKNOWN,
1175 PRINTER_STATUS_POWER_SAVE,
1176 /* these do not stick
1177 0x02000000,
1178 0x04000000,
1179 0x08000000,
1180 0x10000000,
1181 0x20000000,
1182 0x40000000,
1183 0x80000000 */
1185 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1186 uint32_t attribute_list[] = {
1187 PRINTER_ATTRIBUTE_QUEUED,
1188 /* fails with WERR_INVALID_DATATYPE:
1189 PRINTER_ATTRIBUTE_DIRECT, */
1190 /* does not stick
1191 PRINTER_ATTRIBUTE_DEFAULT, */
1192 PRINTER_ATTRIBUTE_SHARED,
1193 /* does not stick
1194 PRINTER_ATTRIBUTE_NETWORK, */
1195 PRINTER_ATTRIBUTE_HIDDEN,
1196 PRINTER_ATTRIBUTE_LOCAL,
1197 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1198 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1199 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1200 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1201 /* does not stick
1202 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1203 /* fails with WERR_INVALID_DATATYPE:
1204 PRINTER_ATTRIBUTE_RAW_ONLY, */
1205 /* these do not stick
1206 PRINTER_ATTRIBUTE_PUBLISHED,
1207 PRINTER_ATTRIBUTE_FAX,
1208 PRINTER_ATTRIBUTE_TS,
1209 0x00010000,
1210 0x00020000,
1211 0x00040000,
1212 0x00080000,
1213 0x00100000,
1214 0x00200000,
1215 0x00400000,
1216 0x00800000,
1217 0x01000000,
1218 0x02000000,
1219 0x04000000,
1220 0x08000000,
1221 0x10000000,
1222 0x20000000,
1223 0x40000000,
1224 0x80000000 */
1227 ZERO_STRUCT(devmode_ctr);
1228 ZERO_STRUCT(secdesc_ctr);
1230 s.in.handle = handle;
1231 s.in.command = 0;
1232 s.in.info_ctr = &info_ctr;
1233 s.in.devmode_ctr = &devmode_ctr;
1234 s.in.secdesc_ctr = &secdesc_ctr;
1236 q.in.handle = handle;
1237 q.out.info = &info;
1238 q0 = q;
1240 #define TESTGETCALL(call, r) \
1241 r.in.buffer = NULL; \
1242 r.in.offered = 0;\
1243 r.out.needed = &needed; \
1244 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1245 if (!NT_STATUS_IS_OK(status)) { \
1246 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1247 r.in.level, nt_errstr(status), __location__); \
1248 ret = false; \
1249 break; \
1251 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1252 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1253 data_blob_clear(&blob); \
1254 r.in.buffer = &blob; \
1255 r.in.offered = needed; \
1257 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1258 if (!NT_STATUS_IS_OK(status)) { \
1259 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1260 r.in.level, nt_errstr(status), __location__); \
1261 ret = false; \
1262 break; \
1264 if (!W_ERROR_IS_OK(r.out.result)) { \
1265 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1266 r.in.level, win_errstr(r.out.result), __location__); \
1267 ret = false; \
1268 break; \
1272 #define TESTSETCALL_EXP(call, r, err) \
1273 clear_info2(&info_ctr);\
1274 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1275 if (!NT_STATUS_IS_OK(status)) { \
1276 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1277 r.in.info_ctr->level, nt_errstr(status), __location__); \
1278 ret = false; \
1279 break; \
1281 if (!W_ERROR_IS_OK(err)) { \
1282 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1283 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1284 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1285 ret = false; \
1287 break; \
1289 if (!W_ERROR_IS_OK(r.out.result)) { \
1290 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1291 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1292 ret = false; \
1293 break; \
1296 #define TESTSETCALL(call, r) \
1297 TESTSETCALL_EXP(call, r, WERR_OK)
1299 #define STRING_EQUAL(s1, s2, field) \
1300 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1301 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1302 #field, s2, __location__); \
1303 ret = false; \
1304 break; \
1307 #define MEM_EQUAL(s1, s2, length, field) \
1308 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1309 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1310 #field, (const char *)s2, __location__); \
1311 ret = false; \
1312 break; \
1315 #define INT_EQUAL(i1, i2, field) \
1316 if (i1 != i2) { \
1317 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1318 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1319 ret = false; \
1320 break; \
1323 #define SD_EQUAL(sd1, sd2, field) \
1324 if (!security_descriptor_equal(sd1, sd2)) { \
1325 torture_comment(tctx, "Failed to set %s (%s)\n", \
1326 #field, __location__); \
1327 ret = false; \
1328 break; \
1331 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1332 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1333 q.in.level = lvl1; \
1334 TESTGETCALL(GetPrinter, q) \
1335 info_ctr.level = lvl1; \
1336 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1337 info_ctr.info.info ## lvl1->field1 = value;\
1338 TESTSETCALL_EXP(SetPrinter, s, err) \
1339 info_ctr.info.info ## lvl1->field1 = ""; \
1340 TESTGETCALL(GetPrinter, q) \
1341 info_ctr.info.info ## lvl1->field1 = value; \
1342 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1343 q.in.level = lvl2; \
1344 TESTGETCALL(GetPrinter, q) \
1345 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1346 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1347 } while (0)
1349 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1350 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1351 } while (0);
1353 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1354 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1355 q.in.level = lvl1; \
1356 TESTGETCALL(GetPrinter, q) \
1357 info_ctr.level = lvl1; \
1358 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1359 info_ctr.info.info ## lvl1->field1 = value; \
1360 TESTSETCALL(SetPrinter, s) \
1361 info_ctr.info.info ## lvl1->field1 = 0; \
1362 TESTGETCALL(GetPrinter, q) \
1363 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1364 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1365 q.in.level = lvl2; \
1366 TESTGETCALL(GetPrinter, q) \
1367 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1368 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1369 } while (0)
1371 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1372 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1373 } while (0)
1375 q0.in.level = 0;
1376 do { TESTGETCALL(GetPrinter, q0) } while (0);
1378 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1379 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1381 /* level 0 printername does not stick */
1382 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1383 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1384 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1385 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1386 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1387 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1388 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1389 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1390 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1391 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1392 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1393 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1394 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1395 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1396 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1398 /* servername can be set but does not stick
1399 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1400 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1401 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1404 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1405 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1406 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1407 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1408 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1410 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1411 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1412 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1413 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1414 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1415 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1416 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1417 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1418 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1419 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1421 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1422 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1423 attribute_list[i],
1424 (attribute_list[i] | default_attribute)
1425 ); */
1426 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1427 attribute_list[i],
1428 (attribute_list[i] | default_attribute)
1430 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1431 attribute_list[i],
1432 (attribute_list[i] | default_attribute)
1434 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1435 attribute_list[i],
1436 (attribute_list[i] | default_attribute)
1438 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1439 attribute_list[i],
1440 (attribute_list[i] | default_attribute)
1441 ); */
1442 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1443 attribute_list[i],
1444 (attribute_list[i] | default_attribute)
1446 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1447 attribute_list[i],
1448 (attribute_list[i] | default_attribute)
1450 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1451 attribute_list[i],
1452 (attribute_list[i] | default_attribute)
1454 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1455 attribute_list[i],
1456 (attribute_list[i] | default_attribute)
1457 ); */
1458 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1459 attribute_list[i],
1460 (attribute_list[i] | default_attribute)
1462 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1463 attribute_list[i],
1464 (attribute_list[i] | default_attribute)
1466 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1467 attribute_list[i],
1468 (attribute_list[i] | default_attribute)
1472 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1473 /* level 2 sets do not stick
1474 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1475 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1476 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1477 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1478 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1479 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1482 /* priorities need to be between 0 and 99
1483 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1484 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1485 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1486 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1487 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1488 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1489 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1490 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1491 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1493 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1494 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1496 /* does not stick
1497 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1498 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1500 /* does not stick
1501 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1502 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1504 /* FIXME: gd also test devmode and secdesc behavior */
1507 /* verify composition of level 1 description field */
1508 const char *description;
1509 const char *tmp;
1511 q0.in.level = 1;
1512 do { TESTGETCALL(GetPrinter, q0) } while (0);
1514 description = talloc_strdup(tctx, q0.out.info->info1.description);
1516 q0.in.level = 2;
1517 do { TESTGETCALL(GetPrinter, q0) } while (0);
1519 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1520 q0.out.info->info2.printername,
1521 q0.out.info->info2.drivername,
1522 q0.out.info->info2.location);
1524 do { STRING_EQUAL(description, tmp, "description")} while (0);
1527 return ret;
1530 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1531 do { struct dom_sid *__got = (got), *__expected = (expected); \
1532 if (!dom_sid_equal(__got, __expected)) { \
1533 torture_result(torture_ctx, TORTURE_FAIL, \
1534 __location__": "#got" was %s, expected %s: %s", \
1535 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1536 return false; \
1538 } while(0)
1540 static bool test_security_descriptor_equal(struct torture_context *tctx,
1541 const struct security_descriptor *sd1,
1542 const struct security_descriptor *sd2)
1544 if (sd1 == sd2) {
1545 return true;
1548 if (!sd1 || !sd2) {
1549 torture_comment(tctx, "%s\n", __location__);
1550 return false;
1553 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1554 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1556 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1557 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1559 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1560 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1561 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1562 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1563 return false;
1565 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1566 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1567 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1568 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1569 return false;
1572 return true;
1575 static bool test_sd_set_level(struct torture_context *tctx,
1576 struct dcerpc_pipe *p,
1577 struct policy_handle *handle,
1578 uint32_t level,
1579 struct security_descriptor *sd)
1581 struct spoolss_SetPrinterInfoCtr info_ctr;
1582 struct spoolss_DevmodeContainer devmode_ctr;
1583 struct sec_desc_buf secdesc_ctr;
1585 ZERO_STRUCT(devmode_ctr);
1586 ZERO_STRUCT(secdesc_ctr);
1588 switch (level) {
1589 case 2: {
1590 union spoolss_PrinterInfo info;
1591 struct spoolss_SetPrinterInfo2 info2;
1592 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1594 info2.servername = info.info2.servername;
1595 info2.printername = info.info2.printername;
1596 info2.sharename = info.info2.sharename;
1597 info2.portname = info.info2.portname;
1598 info2.drivername = info.info2.drivername;
1599 info2.comment = info.info2.comment;
1600 info2.location = info.info2.location;
1601 info2.devmode_ptr = 0;
1602 info2.sepfile = info.info2.sepfile;
1603 info2.printprocessor = info.info2.printprocessor;
1604 info2.datatype = info.info2.datatype;
1605 info2.parameters = info.info2.parameters;
1606 info2.secdesc_ptr = 0;
1607 info2.attributes = info.info2.attributes;
1608 info2.priority = info.info2.priority;
1609 info2.defaultpriority = info.info2.defaultpriority;
1610 info2.starttime = info.info2.starttime;
1611 info2.untiltime = info.info2.untiltime;
1612 info2.status = info.info2.status;
1613 info2.cjobs = info.info2.cjobs;
1614 info2.averageppm = info.info2.averageppm;
1616 info_ctr.level = 2;
1617 info_ctr.info.info2 = &info2;
1619 break;
1621 case 3: {
1622 struct spoolss_SetPrinterInfo3 info3;
1624 info3.sec_desc_ptr = 0;
1626 info_ctr.level = 3;
1627 info_ctr.info.info3 = &info3;
1629 break;
1631 default:
1632 return false;
1635 secdesc_ctr.sd = sd;
1637 torture_assert(tctx,
1638 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1640 return true;
1643 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1644 struct dcerpc_pipe *p,
1645 struct policy_handle *handle)
1647 union spoolss_PrinterInfo info;
1648 struct security_descriptor *sd1, *sd2;
1649 int i;
1651 /* just compare level 2 and level 3 */
1653 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1655 sd1 = info.info2.secdesc;
1657 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 3, &info), "");
1659 sd2 = info.info3.secdesc;
1661 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
1664 /* query level 2, set level 2, query level 2 */
1666 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1668 sd1 = info.info2.secdesc;
1670 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
1672 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1674 sd2 = info.info2.secdesc;
1675 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1676 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1677 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1680 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
1683 /* query level 2, set level 3, query level 2 */
1685 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1687 sd1 = info.info2.secdesc;
1689 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1691 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1693 sd2 = info.info2.secdesc;
1695 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
1698 /* set modified sd level 3, query level 2 */
1700 for (i=0; i < 93; i++) {
1701 struct security_ace a;
1702 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1703 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1704 a.flags = 0;
1705 a.size = 0; /* autogenerated */
1706 a.access_mask = 0;
1707 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1708 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1711 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1713 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1714 sd2 = info.info2.secdesc;
1716 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1717 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1718 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1721 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2), "");
1723 return true;
1727 * wrapper call that saves original sd, runs tests, and restores sd
1730 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1731 struct dcerpc_pipe *p,
1732 struct policy_handle *handle)
1734 union spoolss_PrinterInfo info;
1735 struct spoolss_SetPrinterInfo3 info3;
1736 struct spoolss_SetPrinterInfoCtr info_ctr;
1737 struct spoolss_DevmodeContainer devmode_ctr;
1738 struct sec_desc_buf secdesc_ctr;
1739 struct security_descriptor *sd;
1740 bool ret = true;
1742 /* save original sd */
1744 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1746 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1748 /* run tests */
1750 ret = test_PrinterInfo_SDs(tctx, p, handle);
1752 /* restore original sd */
1754 ZERO_STRUCT(devmode_ctr);
1755 ZERO_STRUCT(secdesc_ctr);
1757 info3.sec_desc_ptr = 0;
1759 info_ctr.level = 3;
1760 info_ctr.info.info3 = &info3;
1762 secdesc_ctr.sd = sd;
1764 torture_assert(tctx,
1765 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1767 return ret;
1770 static bool test_devicemode_equal(struct torture_context *tctx,
1771 const struct spoolss_DeviceMode *d1,
1772 const struct spoolss_DeviceMode *d2)
1774 if (d1 == d2) {
1775 return true;
1778 if (!d1 || !d2) {
1779 torture_comment(tctx, "%s\n", __location__);
1780 return false;
1782 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1783 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1784 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1785 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1786 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1787 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1788 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1789 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1790 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1791 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1792 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1793 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1794 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1795 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1796 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1797 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1798 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1799 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1800 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1801 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1802 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1803 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1804 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1805 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1806 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1807 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1808 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1809 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1810 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1811 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1812 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1813 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1814 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1815 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1816 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1818 return true;
1821 static bool call_OpenPrinterEx(struct torture_context *tctx,
1822 struct dcerpc_pipe *p,
1823 const char *name,
1824 struct spoolss_DeviceMode *devmode,
1825 struct policy_handle *handle);
1827 static bool test_ClosePrinter(struct torture_context *tctx,
1828 struct dcerpc_pipe *p,
1829 struct policy_handle *handle);
1831 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
1832 struct dcerpc_pipe *p,
1833 struct policy_handle *handle,
1834 const char *name)
1836 union spoolss_PrinterInfo info;
1837 struct spoolss_DeviceMode *devmode;
1838 struct spoolss_DeviceMode *devmode2;
1839 struct policy_handle handle_devmode;
1841 /* simply compare level8 and level2 devmode */
1843 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
1845 devmode = info.info8.devmode;
1847 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1849 devmode2 = info.info2.devmode;
1851 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2), "");
1854 /* change formname upon open and see if it persists in getprinter calls */
1856 devmode->formname = talloc_strdup(tctx, "A4");
1858 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
1859 "failed to open printer handle");
1861 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 8, &info), "");
1863 devmode2 = info.info8.devmode;
1865 if (strequal(devmode->devicename, devmode2->devicename)) {
1866 torture_fail(tctx, "devicename is the same");
1869 if (strequal(devmode->formname, devmode2->formname)) {
1870 torture_fail(tctx, "formname is the same");
1873 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 2, &info), "");
1875 devmode2 = info.info2.devmode;
1877 if (strequal(devmode->devicename, devmode2->devicename)) {
1878 torture_fail(tctx, "devicename is the same");
1881 if (strequal(devmode->formname, devmode2->formname)) {
1882 torture_fail(tctx, "formname is the same");
1885 test_ClosePrinter(tctx, p, &handle_devmode);
1888 /* set devicemode and see if it persists */
1890 devmode->copies = 93;
1891 devmode->formname = talloc_strdup(tctx, "Legal");
1894 struct spoolss_SetPrinterInfoCtr info_ctr;
1895 struct spoolss_SetPrinterInfo8 info8;
1896 struct spoolss_DevmodeContainer devmode_ctr;
1897 struct sec_desc_buf secdesc_ctr;
1899 info8.devmode_ptr = 0;
1901 info_ctr.level = 8;
1902 info_ctr.info.info8 = &info8;
1904 devmode_ctr.devmode = devmode;
1906 ZERO_STRUCT(secdesc_ctr);
1908 torture_assert(tctx,
1909 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1912 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
1914 devmode2 = info.info8.devmode;
1916 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2), "");
1918 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1920 devmode2 = info.info2.devmode;
1922 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2), "");
1924 return true;
1928 * wrapper call that saves original devmode, runs tests, and restores devmode
1931 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
1932 struct dcerpc_pipe *p,
1933 struct policy_handle *handle,
1934 const char *name)
1936 union spoolss_PrinterInfo info;
1937 struct spoolss_SetPrinterInfo8 info8;
1938 struct spoolss_SetPrinterInfoCtr info_ctr;
1939 struct spoolss_DevmodeContainer devmode_ctr;
1940 struct sec_desc_buf secdesc_ctr;
1941 struct spoolss_DeviceMode *devmode;
1942 bool ret = true;
1944 /* save original devmode */
1946 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
1948 devmode = info.info8.devmode;
1950 /* run tests */
1952 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
1954 /* restore original devmode */
1956 ZERO_STRUCT(devmode_ctr);
1957 ZERO_STRUCT(secdesc_ctr);
1959 info8.devmode_ptr = 0;
1961 info_ctr.level = 8;
1962 info_ctr.info.info8 = &info8;
1964 devmode_ctr.devmode = devmode;
1966 torture_assert(tctx,
1967 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1969 return ret;
1972 static bool test_ClosePrinter(struct torture_context *tctx,
1973 struct dcerpc_pipe *p,
1974 struct policy_handle *handle)
1976 NTSTATUS status;
1977 struct spoolss_ClosePrinter r;
1979 r.in.handle = handle;
1980 r.out.handle = handle;
1982 torture_comment(tctx, "Testing ClosePrinter\n");
1984 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1985 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1986 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1988 return true;
1991 static bool test_GetForm(struct torture_context *tctx,
1992 struct dcerpc_pipe *p,
1993 struct policy_handle *handle,
1994 const char *form_name,
1995 uint32_t level)
1997 NTSTATUS status;
1998 struct spoolss_GetForm r;
1999 uint32_t needed;
2001 r.in.handle = handle;
2002 r.in.form_name = form_name;
2003 r.in.level = level;
2004 r.in.buffer = NULL;
2005 r.in.offered = 0;
2006 r.out.needed = &needed;
2008 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
2010 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2011 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2013 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2014 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2015 data_blob_clear(&blob);
2016 r.in.buffer = &blob;
2017 r.in.offered = needed;
2018 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2019 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2021 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2023 torture_assert(tctx, r.out.info, "No form info returned");
2026 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2028 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2030 return true;
2033 static bool test_EnumForms(struct torture_context *tctx,
2034 struct dcerpc_pipe *p,
2035 struct policy_handle *handle, bool print_server)
2037 NTSTATUS status;
2038 struct spoolss_EnumForms r;
2039 bool ret = true;
2040 uint32_t needed;
2041 uint32_t count;
2042 uint32_t levels[] = { 1, 2 };
2043 int i;
2045 for (i=0; i<ARRAY_SIZE(levels); i++) {
2047 union spoolss_FormInfo *info;
2049 r.in.handle = handle;
2050 r.in.level = levels[i];
2051 r.in.buffer = NULL;
2052 r.in.offered = 0;
2053 r.out.needed = &needed;
2054 r.out.count = &count;
2055 r.out.info = &info;
2057 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
2059 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2060 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2062 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2063 break;
2066 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
2067 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2069 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2070 int j;
2071 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2072 data_blob_clear(&blob);
2073 r.in.buffer = &blob;
2074 r.in.offered = needed;
2076 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2078 torture_assert(tctx, info, "No forms returned");
2080 for (j = 0; j < count; j++) {
2081 if (!print_server)
2082 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
2086 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2088 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2090 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2093 return true;
2096 static bool test_DeleteForm(struct torture_context *tctx,
2097 struct dcerpc_pipe *p,
2098 struct policy_handle *handle,
2099 const char *form_name)
2101 NTSTATUS status;
2102 struct spoolss_DeleteForm r;
2104 r.in.handle = handle;
2105 r.in.form_name = form_name;
2107 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
2109 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
2111 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
2113 return true;
2116 static bool test_AddForm(struct torture_context *tctx,
2117 struct dcerpc_pipe *p,
2118 struct policy_handle *handle, bool print_server)
2120 struct spoolss_AddForm r;
2121 struct spoolss_AddFormInfo1 addform;
2122 const char *form_name = "testform3";
2123 NTSTATUS status;
2124 bool ret = true;
2126 r.in.handle = handle;
2127 r.in.level = 1;
2128 r.in.info.info1 = &addform;
2129 addform.flags = SPOOLSS_FORM_USER;
2130 addform.form_name = form_name;
2131 addform.size.width = 50;
2132 addform.size.height = 25;
2133 addform.area.left = 5;
2134 addform.area.top = 10;
2135 addform.area.right = 45;
2136 addform.area.bottom = 15;
2138 status = dcerpc_spoolss_AddForm(p, tctx, &r);
2140 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
2142 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
2144 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2147 struct spoolss_SetForm sf;
2148 struct spoolss_AddFormInfo1 setform;
2150 sf.in.handle = handle;
2151 sf.in.form_name = form_name;
2152 sf.in.level = 1;
2153 sf.in.info.info1= &setform;
2154 setform.flags = addform.flags;
2155 setform.form_name = addform.form_name;
2156 setform.size = addform.size;
2157 setform.area = addform.area;
2159 setform.size.width = 1234;
2161 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
2163 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
2165 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
2168 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2171 struct spoolss_EnumForms e;
2172 union spoolss_FormInfo *info;
2173 uint32_t needed;
2174 uint32_t count;
2175 bool found = false;
2177 e.in.handle = handle;
2178 e.in.level = 1;
2179 e.in.buffer = NULL;
2180 e.in.offered = 0;
2181 e.out.needed = &needed;
2182 e.out.count = &count;
2183 e.out.info = &info;
2185 torture_comment(tctx, "Testing EnumForms level 1\n");
2187 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2188 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2190 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
2191 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2193 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2194 int j;
2195 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2196 data_blob_clear(&blob);
2197 e.in.buffer = &blob;
2198 e.in.offered = needed;
2200 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2202 torture_assert(tctx, info, "No forms returned");
2204 for (j = 0; j < count; j++) {
2205 if (strequal(form_name, info[j].info1.form_name)) {
2206 found = true;
2207 break;
2211 torture_assert(tctx, found, "Newly added form not found in enum call");
2214 if (!test_DeleteForm(tctx, p, handle, form_name)) {
2215 ret = false;
2218 return ret;
2221 static bool test_EnumPorts_old(struct torture_context *tctx,
2222 struct dcerpc_pipe *p)
2224 NTSTATUS status;
2225 struct spoolss_EnumPorts r;
2226 uint32_t needed;
2227 uint32_t count;
2228 union spoolss_PortInfo *info;
2230 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2231 dcerpc_server_name(p));
2232 r.in.level = 2;
2233 r.in.buffer = NULL;
2234 r.in.offered = 0;
2235 r.out.needed = &needed;
2236 r.out.count = &count;
2237 r.out.info = &info;
2239 torture_comment(tctx, "Testing EnumPorts\n");
2241 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2243 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2245 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2246 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2247 data_blob_clear(&blob);
2248 r.in.buffer = &blob;
2249 r.in.offered = needed;
2251 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2252 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2253 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2255 torture_assert(tctx, info, "No ports returned");
2258 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2260 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2262 return true;
2265 static bool test_AddPort(struct torture_context *tctx,
2266 struct dcerpc_pipe *p)
2268 NTSTATUS status;
2269 struct spoolss_AddPort r;
2271 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2272 dcerpc_server_name(p));
2273 r.in.unknown = 0;
2274 r.in.monitor_name = "foo";
2276 torture_comment(tctx, "Testing AddPort\n");
2278 status = dcerpc_spoolss_AddPort(p, tctx, &r);
2280 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2282 /* win2k3 returns WERR_NOT_SUPPORTED */
2284 #if 0
2286 if (!W_ERROR_IS_OK(r.out.result)) {
2287 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2288 return false;
2291 #endif
2293 return true;
2296 static bool test_GetJob(struct torture_context *tctx,
2297 struct dcerpc_pipe *p,
2298 struct policy_handle *handle, uint32_t job_id)
2300 NTSTATUS status;
2301 struct spoolss_GetJob r;
2302 union spoolss_JobInfo info;
2303 uint32_t needed;
2304 uint32_t levels[] = {1, 2 /* 3, 4 */};
2305 uint32_t i;
2307 r.in.handle = handle;
2308 r.in.job_id = job_id;
2309 r.in.level = 0;
2310 r.in.buffer = NULL;
2311 r.in.offered = 0;
2312 r.out.needed = &needed;
2313 r.out.info = &info;
2315 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2317 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2318 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2320 for (i = 0; i < ARRAY_SIZE(levels); i++) {
2322 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2324 needed = 0;
2326 r.in.level = levels[i];
2327 r.in.offered = 0;
2328 r.in.buffer = NULL;
2330 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2331 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2333 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2334 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2335 data_blob_clear(&blob);
2336 r.in.buffer = &blob;
2337 r.in.offered = needed;
2339 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2340 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2343 torture_assert(tctx, r.out.info, "No job info returned");
2344 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2346 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2349 return true;
2352 static bool test_SetJob(struct torture_context *tctx,
2353 struct dcerpc_pipe *p,
2354 struct policy_handle *handle, uint32_t job_id,
2355 enum spoolss_JobControl command)
2357 NTSTATUS status;
2358 struct spoolss_SetJob r;
2360 r.in.handle = handle;
2361 r.in.job_id = job_id;
2362 r.in.ctr = NULL;
2363 r.in.command = command;
2365 switch (command) {
2366 case SPOOLSS_JOB_CONTROL_PAUSE:
2367 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2368 break;
2369 case SPOOLSS_JOB_CONTROL_RESUME:
2370 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2371 break;
2372 case SPOOLSS_JOB_CONTROL_CANCEL:
2373 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2374 break;
2375 case SPOOLSS_JOB_CONTROL_RESTART:
2376 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2377 break;
2378 case SPOOLSS_JOB_CONTROL_DELETE:
2379 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2380 break;
2381 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2382 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2383 break;
2384 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2385 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2386 break;
2387 case SPOOLSS_JOB_CONTROL_RETAIN:
2388 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2389 break;
2390 case SPOOLSS_JOB_CONTROL_RELEASE:
2391 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2392 break;
2393 default:
2394 torture_comment(tctx, "Testing SetJob\n");
2395 break;
2398 status = dcerpc_spoolss_SetJob(p, tctx, &r);
2399 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2400 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2402 return true;
2405 static bool test_AddJob(struct torture_context *tctx,
2406 struct dcerpc_pipe *p,
2407 struct policy_handle *handle)
2409 NTSTATUS status;
2410 struct spoolss_AddJob r;
2411 uint32_t needed;
2413 r.in.level = 0;
2414 r.in.handle = handle;
2415 r.in.offered = 0;
2416 r.out.needed = &needed;
2417 r.in.buffer = r.out.buffer = NULL;
2419 torture_comment(tctx, "Testing AddJob\n");
2421 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2422 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2424 r.in.level = 1;
2426 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2427 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2429 return true;
2433 static bool test_EnumJobs(struct torture_context *tctx,
2434 struct dcerpc_pipe *p,
2435 struct policy_handle *handle)
2437 NTSTATUS status;
2438 struct spoolss_EnumJobs r;
2439 uint32_t needed;
2440 uint32_t count;
2441 union spoolss_JobInfo *info;
2443 r.in.handle = handle;
2444 r.in.firstjob = 0;
2445 r.in.numjobs = 0xffffffff;
2446 r.in.level = 1;
2447 r.in.buffer = NULL;
2448 r.in.offered = 0;
2449 r.out.needed = &needed;
2450 r.out.count = &count;
2451 r.out.info = &info;
2453 torture_comment(tctx, "Testing EnumJobs\n");
2455 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2457 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2459 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2460 int j;
2461 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2462 data_blob_clear(&blob);
2463 r.in.buffer = &blob;
2464 r.in.offered = needed;
2466 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2468 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2469 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2470 torture_assert(tctx, info, "No jobs returned");
2472 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2474 for (j = 0; j < count; j++) {
2476 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2477 "failed to call test_GetJob");
2479 /* FIXME - gd */
2480 if (!torture_setting_bool(tctx, "samba3", false)) {
2481 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2482 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2486 } else {
2487 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2490 return true;
2493 static bool test_DoPrintTest(struct torture_context *tctx,
2494 struct dcerpc_pipe *p,
2495 struct policy_handle *handle)
2497 bool ret = true;
2498 NTSTATUS status;
2499 struct spoolss_StartDocPrinter s;
2500 struct spoolss_DocumentInfo1 info1;
2501 struct spoolss_StartPagePrinter sp;
2502 struct spoolss_WritePrinter w;
2503 struct spoolss_EndPagePrinter ep;
2504 struct spoolss_EndDocPrinter e;
2505 int i;
2506 uint32_t job_id;
2507 uint32_t num_written;
2509 torture_comment(tctx, "Testing StartDocPrinter\n");
2511 s.in.handle = handle;
2512 s.in.level = 1;
2513 s.in.info.info1 = &info1;
2514 s.out.job_id = &job_id;
2515 info1.document_name = "TorturePrintJob";
2516 info1.output_file = NULL;
2517 info1.datatype = "RAW";
2519 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2520 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2521 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2523 for (i=1; i < 4; i++) {
2524 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2526 sp.in.handle = handle;
2528 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2529 torture_assert_ntstatus_ok(tctx, status,
2530 "dcerpc_spoolss_StartPagePrinter failed");
2531 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2533 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2535 w.in.handle = handle;
2536 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2537 w.out.num_written = &num_written;
2539 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2540 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2541 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2543 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2545 ep.in.handle = handle;
2547 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2548 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2549 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2552 torture_comment(tctx, "Testing EndDocPrinter\n");
2554 e.in.handle = handle;
2556 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2557 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2558 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2560 ret &= test_AddJob(tctx, p, handle);
2561 ret &= test_EnumJobs(tctx, p, handle);
2563 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2565 return ret;
2568 static bool test_PausePrinter(struct torture_context *tctx,
2569 struct dcerpc_pipe *p,
2570 struct policy_handle *handle)
2572 NTSTATUS status;
2573 struct spoolss_SetPrinter r;
2574 struct spoolss_SetPrinterInfoCtr info_ctr;
2575 struct spoolss_DevmodeContainer devmode_ctr;
2576 struct sec_desc_buf secdesc_ctr;
2578 info_ctr.level = 0;
2579 info_ctr.info.info0 = NULL;
2581 ZERO_STRUCT(devmode_ctr);
2582 ZERO_STRUCT(secdesc_ctr);
2584 r.in.handle = handle;
2585 r.in.info_ctr = &info_ctr;
2586 r.in.devmode_ctr = &devmode_ctr;
2587 r.in.secdesc_ctr = &secdesc_ctr;
2588 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2590 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2592 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2594 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2596 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2598 return true;
2601 static bool test_ResumePrinter(struct torture_context *tctx,
2602 struct dcerpc_pipe *p,
2603 struct policy_handle *handle)
2605 NTSTATUS status;
2606 struct spoolss_SetPrinter r;
2607 struct spoolss_SetPrinterInfoCtr info_ctr;
2608 struct spoolss_DevmodeContainer devmode_ctr;
2609 struct sec_desc_buf secdesc_ctr;
2611 info_ctr.level = 0;
2612 info_ctr.info.info0 = NULL;
2614 ZERO_STRUCT(devmode_ctr);
2615 ZERO_STRUCT(secdesc_ctr);
2617 r.in.handle = handle;
2618 r.in.info_ctr = &info_ctr;
2619 r.in.devmode_ctr = &devmode_ctr;
2620 r.in.secdesc_ctr = &secdesc_ctr;
2621 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2623 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2625 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2627 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2629 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2631 return true;
2634 static bool test_GetPrinterData(struct torture_context *tctx,
2635 struct dcerpc_pipe *p,
2636 struct policy_handle *handle,
2637 const char *value_name,
2638 enum winreg_Type *type_p,
2639 union spoolss_PrinterData *data_p)
2641 NTSTATUS status;
2642 struct spoolss_GetPrinterData r;
2643 uint32_t needed;
2644 enum winreg_Type type;
2645 union spoolss_PrinterData data;
2647 r.in.handle = handle;
2648 r.in.value_name = value_name;
2649 r.in.offered = 0;
2650 r.out.needed = &needed;
2651 r.out.type = &type;
2652 r.out.data = &data;
2654 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2656 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2657 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2659 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2660 r.in.offered = needed;
2662 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2663 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2666 torture_assert_werr_ok(tctx, r.out.result,
2667 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2669 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2671 if (type_p) {
2672 *type_p = type;
2675 if (data_p) {
2676 *data_p = data;
2679 return true;
2682 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2683 struct dcerpc_pipe *p,
2684 struct policy_handle *handle,
2685 const char *key_name,
2686 const char *value_name,
2687 enum winreg_Type *type_p,
2688 union spoolss_PrinterData *data_p)
2690 NTSTATUS status;
2691 struct spoolss_GetPrinterDataEx r;
2692 enum winreg_Type type;
2693 uint32_t needed;
2694 union spoolss_PrinterData data;
2696 r.in.handle = handle;
2697 r.in.key_name = key_name;
2698 r.in.value_name = value_name;
2699 r.in.offered = 0;
2700 r.out.type = &type;
2701 r.out.needed = &needed;
2702 r.out.data = &data;
2704 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2705 r.in.key_name, r.in.value_name);
2707 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2710 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2711 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2713 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2716 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2717 r.in.offered = needed;
2718 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2719 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2722 torture_assert_werr_ok(tctx, r.out.result,
2723 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2725 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2727 if (type_p) {
2728 *type_p = type;
2731 if (data_p) {
2732 *data_p = data;
2735 return true;
2738 static bool test_GetPrinterData_list(struct torture_context *tctx,
2739 struct dcerpc_pipe *p,
2740 struct policy_handle *handle)
2742 const char *list[] = {
2743 "W3SvcInstalled",
2744 "BeepEnabled",
2745 "EventLog",
2746 /* "NetPopup", not on w2k8 */
2747 /* "NetPopupToComputer", not on w2k8 */
2748 "MajorVersion",
2749 "MinorVersion",
2750 "DefaultSpoolDirectory",
2751 "Architecture",
2752 "DsPresent",
2753 "OSVersion",
2754 /* "OSVersionEx", not on s3 */
2755 "DNSMachineName"
2757 int i;
2759 for (i=0; i < ARRAY_SIZE(list); i++) {
2760 enum winreg_Type type, type_ex;
2761 union spoolss_PrinterData data, data_ex;
2763 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2764 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2765 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2766 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2767 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2768 switch (type) {
2769 case REG_SZ:
2770 torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2771 break;
2772 case REG_DWORD:
2773 torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2774 break;
2775 case REG_BINARY:
2776 torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2777 break;
2778 default:
2779 break;
2783 return true;
2786 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2787 struct policy_handle *handle)
2789 NTSTATUS status;
2790 struct spoolss_EnumPrinterData r;
2792 ZERO_STRUCT(r);
2793 r.in.handle = handle;
2794 r.in.enum_index = 0;
2796 do {
2797 uint32_t value_size = 0;
2798 uint32_t data_size = 0;
2799 enum winreg_Type type = 0;
2801 r.in.value_offered = value_size;
2802 r.out.value_needed = &value_size;
2803 r.in.data_offered = data_size;
2804 r.out.data_needed = &data_size;
2806 r.out.type = &type;
2807 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2809 torture_comment(tctx, "Testing EnumPrinterData\n");
2811 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2813 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2814 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2815 break;
2817 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2819 r.in.value_offered = value_size;
2820 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2821 r.in.data_offered = data_size;
2822 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2824 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2826 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2827 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2828 break;
2831 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2833 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2834 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2836 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2837 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2839 r.in.enum_index++;
2841 } while (W_ERROR_IS_OK(r.out.result));
2843 return true;
2846 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2847 struct dcerpc_pipe *p,
2848 struct policy_handle *handle,
2849 const char *key_name)
2851 struct spoolss_EnumPrinterDataEx r;
2852 struct spoolss_PrinterEnumValues *info;
2853 uint32_t needed;
2854 uint32_t count;
2856 r.in.handle = handle;
2857 r.in.key_name = key_name;
2858 r.in.offered = 0;
2859 r.out.needed = &needed;
2860 r.out.count = &count;
2861 r.out.info = &info;
2863 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2865 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2866 "EnumPrinterDataEx failed");
2867 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2868 r.in.offered = needed;
2869 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2870 "EnumPrinterDataEx failed");
2873 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2875 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2877 return true;
2881 static bool test_DeletePrinterData(struct torture_context *tctx,
2882 struct dcerpc_pipe *p,
2883 struct policy_handle *handle,
2884 const char *value_name)
2886 NTSTATUS status;
2887 struct spoolss_DeletePrinterData r;
2889 r.in.handle = handle;
2890 r.in.value_name = value_name;
2892 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2893 r.in.value_name);
2895 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2897 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2898 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2900 return true;
2903 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2904 struct dcerpc_pipe *p,
2905 struct policy_handle *handle,
2906 const char *key_name,
2907 const char *value_name)
2909 struct spoolss_DeletePrinterDataEx r;
2911 r.in.handle = handle;
2912 r.in.key_name = key_name;
2913 r.in.value_name = value_name;
2915 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2916 r.in.key_name, r.in.value_name);
2918 torture_assert_ntstatus_ok(tctx,
2919 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2920 "DeletePrinterDataEx failed");
2921 torture_assert_werr_ok(tctx, r.out.result,
2922 "DeletePrinterDataEx failed");
2924 return true;
2927 static bool test_DeletePrinterKey(struct torture_context *tctx,
2928 struct dcerpc_pipe *p,
2929 struct policy_handle *handle,
2930 const char *key_name)
2932 struct spoolss_DeletePrinterKey r;
2934 r.in.handle = handle;
2935 r.in.key_name = key_name;
2937 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2939 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2940 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2941 return true;
2944 torture_assert_ntstatus_ok(tctx,
2945 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2946 "DeletePrinterKey failed");
2947 torture_assert_werr_ok(tctx, r.out.result,
2948 "DeletePrinterKey failed");
2950 return true;
2953 static bool test_SetPrinterData(struct torture_context *tctx,
2954 struct dcerpc_pipe *p,
2955 struct policy_handle *handle)
2957 NTSTATUS status;
2958 struct spoolss_SetPrinterData r;
2959 const char *values[] = {
2960 "spootyfoot",
2961 "spooty\\foot",
2962 #if 0
2963 /* FIXME: not working with s3 atm. */
2964 "spooty,foot",
2965 "spooty,fo,ot",
2966 #endif
2967 "spooty foot",
2968 #if 0
2969 /* FIXME: not working with s3 atm. */
2970 "spooty\\fo,ot",
2971 "spooty,fo\\ot"
2972 #endif
2974 int i;
2976 for (i=0; i < ARRAY_SIZE(values); i++) {
2978 enum winreg_Type type;
2979 union spoolss_PrinterData data;
2981 r.in.handle = handle;
2982 r.in.value_name = values[i];
2983 r.in.type = REG_SZ;
2984 r.in.data.string = "dog";
2986 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2987 r.in.value_name);
2989 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2991 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2992 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2994 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2995 return false;
2998 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2999 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
3001 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
3002 return false;
3006 return true;
3009 static bool test_EnumPrinterKey(struct torture_context *tctx,
3010 struct dcerpc_pipe *p,
3011 struct policy_handle *handle,
3012 const char *key_name,
3013 const char ***array);
3015 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3016 struct dcerpc_pipe *p,
3017 struct policy_handle *handle)
3019 NTSTATUS status;
3020 struct spoolss_SetPrinterDataEx r;
3021 const char *value_name = "dog";
3022 const char *keys[] = {
3023 "torturedataex",
3024 "torture data ex",
3025 #if 0
3026 /* FIXME: not working with s3 atm. */
3027 "torturedataex_with_subkey\\subkey",
3028 "torturedataex_with_subkey\\subkey:0",
3029 "torturedataex_with_subkey\\subkey:1",
3030 "torturedataex_with_subkey\\subkey\\subsubkey",
3031 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3032 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3033 #endif
3034 "torture,data",
3035 #if 0
3036 /* FIXME: not working with s3 atm. */
3038 "torture,data,ex",
3039 "torture,data\\ex",
3040 "torture\\data,ex"
3041 #endif
3043 int i;
3044 DATA_BLOB blob = data_blob_string_const("catfoobar");
3047 for (i=0; i < ARRAY_SIZE(keys); i++) {
3049 char *c;
3050 const char *key;
3051 enum winreg_Type type;
3052 const char **subkeys;
3053 union spoolss_PrinterData data;
3055 r.in.handle = handle;
3056 r.in.key_name = keys[i];
3057 r.in.value_name = value_name;
3058 r.in.type = REG_BINARY;
3059 r.in.data.binary = blob;
3061 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
3063 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3065 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3066 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3068 key = talloc_strdup(tctx, r.in.key_name);
3070 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
3071 return false;
3074 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
3075 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
3077 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
3078 return false;
3081 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
3082 return false;
3085 c = strchr(key, '\\');
3086 if (c) {
3087 int i;
3089 /* we have subkeys */
3091 *c = 0;
3093 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3094 return false;
3097 for (i=0; subkeys && subkeys[i]; i++) {
3099 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
3101 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3102 return false;
3106 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3107 return false;
3110 } else {
3111 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3112 return false;
3117 return true;
3120 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3121 struct dcerpc_pipe *p,
3122 struct policy_handle *handle,
3123 uint32_t *change_id)
3125 enum winreg_Type type;
3126 union spoolss_PrinterData data;
3128 torture_assert(tctx,
3129 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data),
3130 "failed to call GetPrinterData");
3132 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3134 *change_id = data.value;
3136 return true;
3139 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3140 struct dcerpc_pipe *p,
3141 struct policy_handle *handle,
3142 uint32_t *change_id)
3144 enum winreg_Type type;
3145 union spoolss_PrinterData data;
3147 torture_assert(tctx,
3148 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data),
3149 "failed to call GetPrinterData");
3151 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3153 *change_id = data.value;
3155 return true;
3158 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3159 struct dcerpc_pipe *p,
3160 struct policy_handle *handle,
3161 uint32_t *change_id)
3163 union spoolss_PrinterInfo info;
3165 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3166 "failed to query Printer level 0");
3168 *change_id = info.info0.change_id;
3170 return true;
3173 static bool test_ChangeID(struct torture_context *tctx,
3174 struct dcerpc_pipe *p,
3175 struct policy_handle *handle)
3177 uint32_t change_id, change_id_ex, change_id_info;
3178 uint32_t change_id2, change_id_ex2, change_id_info2;
3179 union spoolss_PrinterInfo info;
3180 const char *comment;
3183 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3185 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3186 "failed to query for ChangeID");
3187 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3188 "failed to query for ChangeID");
3189 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3190 "failed to query for ChangeID");
3192 torture_assert_int_equal(tctx, change_id, change_id_ex,
3193 "change_ids should all be equal");
3194 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3195 "change_ids should all be equal");
3198 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3200 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3201 "failed to query for ChangeID");
3202 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3203 "failed to query Printer level 2");
3204 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3205 "failed to query for ChangeID");
3206 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3207 "failed to query for ChangeID");
3208 torture_assert_int_equal(tctx, change_id, change_id_ex,
3209 "change_id should not have changed");
3210 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3211 "change_id should not have changed");
3214 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3216 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3217 "failed to query for ChangeID");
3218 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3219 "failed to query for ChangeID");
3220 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3221 "failed to query for ChangeID");
3222 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3223 "failed to query Printer level 2");
3224 comment = talloc_strdup(tctx, info.info2.comment);
3227 struct spoolss_SetPrinterInfoCtr info_ctr;
3228 struct spoolss_DevmodeContainer devmode_ctr;
3229 struct sec_desc_buf secdesc_ctr;
3230 struct spoolss_SetPrinterInfo2 info2;
3232 ZERO_STRUCT(info_ctr);
3233 ZERO_STRUCT(devmode_ctr);
3234 ZERO_STRUCT(secdesc_ctr);
3236 info2.servername = info.info2.servername;
3237 info2.printername = info.info2.printername;
3238 info2.sharename = info.info2.sharename;
3239 info2.portname = info.info2.portname;
3240 info2.drivername = info.info2.drivername;
3241 info2.comment = "torture_comment";
3242 info2.location = info.info2.location;
3243 info2.devmode_ptr = 0;
3244 info2.sepfile = info.info2.sepfile;
3245 info2.printprocessor = info.info2.printprocessor;
3246 info2.datatype = info.info2.datatype;
3247 info2.parameters = info.info2.parameters;
3248 info2.secdesc_ptr = 0;
3249 info2.attributes = info.info2.attributes;
3250 info2.priority = info.info2.priority;
3251 info2.defaultpriority = info.info2.defaultpriority;
3252 info2.starttime = info.info2.starttime;
3253 info2.untiltime = info.info2.untiltime;
3254 info2.status = info.info2.status;
3255 info2.cjobs = info.info2.cjobs;
3256 info2.averageppm = info.info2.averageppm;
3258 info_ctr.level = 2;
3259 info_ctr.info.info2 = &info2;
3261 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3262 "failed to call SetPrinter");
3264 info2.comment = comment;
3266 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3267 "failed to call SetPrinter");
3271 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3272 "failed to query for ChangeID");
3273 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3274 "failed to query for ChangeID");
3275 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3276 "failed to query for ChangeID");
3278 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3279 "change_ids should all be equal");
3280 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3281 "change_ids should all be equal");
3283 torture_assert(tctx, (change_id < change_id2),
3284 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3285 change_id2, change_id));
3286 torture_assert(tctx, (change_id_ex < change_id_ex2),
3287 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3288 change_id_ex2, change_id_ex));
3289 torture_assert(tctx, (change_id_info < change_id_info2),
3290 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3291 change_id_info2, change_id_info));
3293 return true;
3296 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3297 struct dcerpc_pipe *p,
3298 struct policy_handle *handle)
3300 NTSTATUS status;
3301 struct dcerpc_binding *b;
3302 struct dcerpc_pipe *p2;
3303 struct spoolss_ClosePrinter cp;
3305 /* only makes sense on SMB */
3306 if (p->conn->transport.transport != NCACN_NP) {
3307 return true;
3310 torture_comment(tctx, "testing close on secondary pipe\n");
3312 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3313 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3315 status = dcerpc_secondary_connection(p, &p2, b);
3316 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3318 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3319 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3321 cp.in.handle = handle;
3322 cp.out.handle = handle;
3324 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3325 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3326 "ERROR: Allowed close on secondary connection");
3328 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3329 "Unexpected fault code");
3331 talloc_free(p2);
3333 return true;
3336 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3337 struct dcerpc_pipe *p, const char *name)
3339 NTSTATUS status;
3340 struct spoolss_OpenPrinter op;
3341 struct spoolss_OpenPrinterEx opEx;
3342 struct policy_handle handle;
3343 bool ret = true;
3345 op.in.printername = name;
3346 op.in.datatype = NULL;
3347 op.in.devmode_ctr.devmode= NULL;
3348 op.in.access_mask = 0;
3349 op.out.handle = &handle;
3351 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
3353 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
3354 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3355 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
3356 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
3357 name, win_errstr(op.out.result));
3360 if (W_ERROR_IS_OK(op.out.result)) {
3361 ret &=test_ClosePrinter(tctx, p, &handle);
3364 opEx.in.printername = name;
3365 opEx.in.datatype = NULL;
3366 opEx.in.devmode_ctr.devmode = NULL;
3367 opEx.in.access_mask = 0;
3368 opEx.in.level = 1;
3369 opEx.in.userlevel.level1 = NULL;
3370 opEx.out.handle = &handle;
3372 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
3374 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
3375 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3376 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
3377 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
3378 name, win_errstr(opEx.out.result));
3381 if (W_ERROR_IS_OK(opEx.out.result)) {
3382 ret &=test_ClosePrinter(tctx, p, &handle);
3385 return ret;
3388 static bool test_OpenPrinter(struct torture_context *tctx,
3389 struct dcerpc_pipe *p,
3390 const char *name)
3392 NTSTATUS status;
3393 struct spoolss_OpenPrinter r;
3394 struct policy_handle handle;
3395 bool ret = true;
3397 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
3398 r.in.datatype = NULL;
3399 r.in.devmode_ctr.devmode= NULL;
3400 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3401 r.out.handle = &handle;
3403 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
3405 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
3407 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3409 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
3411 if (!test_GetPrinter(tctx, p, &handle)) {
3412 ret = false;
3415 if (!torture_setting_bool(tctx, "samba3", false)) {
3416 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3417 ret = false;
3421 if (!test_ClosePrinter(tctx, p, &handle)) {
3422 ret = false;
3425 return ret;
3428 static bool call_OpenPrinterEx(struct torture_context *tctx,
3429 struct dcerpc_pipe *p,
3430 const char *name,
3431 struct spoolss_DeviceMode *devmode,
3432 struct policy_handle *handle)
3434 struct spoolss_OpenPrinterEx r;
3435 struct spoolss_UserLevel1 userlevel1;
3436 NTSTATUS status;
3438 if (name && name[0]) {
3439 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
3440 dcerpc_server_name(p), name);
3441 } else {
3442 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
3443 dcerpc_server_name(p));
3446 r.in.datatype = NULL;
3447 r.in.devmode_ctr.devmode= devmode;
3448 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3449 r.in.level = 1;
3450 r.in.userlevel.level1 = &userlevel1;
3451 r.out.handle = handle;
3453 userlevel1.size = 1234;
3454 userlevel1.client = "hello";
3455 userlevel1.user = "spottyfoot!";
3456 userlevel1.build = 1;
3457 userlevel1.major = 2;
3458 userlevel1.minor = 3;
3459 userlevel1.processor = 4;
3461 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3463 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3465 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3467 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3469 return true;
3472 static bool test_OpenPrinterEx(struct torture_context *tctx,
3473 struct dcerpc_pipe *p,
3474 const char *name)
3476 struct policy_handle handle;
3477 bool ret = true;
3479 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
3480 return false;
3483 if (!test_PrinterInfo_SD(tctx, p, &handle)) {
3484 ret = false;
3487 if (!test_GetPrinter(tctx, p, &handle)) {
3488 ret = false;
3491 if (!test_EnumForms(tctx, p, &handle, false)) {
3492 ret = false;
3495 if (!test_AddForm(tctx, p, &handle, false)) {
3496 ret = false;
3499 if (!test_EnumPrinterData(tctx, p, &handle)) {
3500 ret = false;
3503 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
3504 ret = false;
3507 if (!test_printer_keys(tctx, p, &handle)) {
3508 ret = false;
3511 if (!test_PausePrinter(tctx, p, &handle)) {
3512 ret = false;
3515 if (!test_DoPrintTest(tctx, p, &handle)) {
3516 ret = false;
3519 if (!test_ResumePrinter(tctx, p, &handle)) {
3520 ret = false;
3523 if (!test_SetPrinterData(tctx, p, &handle)) {
3524 ret = false;
3527 if (!test_SetPrinterDataEx(tctx, p, &handle)) {
3528 ret = false;
3531 if (!test_ChangeID(tctx, p, &handle)) {
3532 ret = false;
3535 if (!torture_setting_bool(tctx, "samba3", false)) {
3536 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3537 ret = false;
3541 if (!test_ClosePrinter(tctx, p, &handle)) {
3542 ret = false;
3545 return ret;
3548 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
3550 struct spoolss_EnumPrinters r;
3551 NTSTATUS status;
3552 uint16_t levels[] = {1, 2, 4, 5};
3553 int i;
3554 bool ret = true;
3556 for (i=0;i<ARRAY_SIZE(levels);i++) {
3557 union spoolss_PrinterInfo *info;
3558 int j;
3559 uint32_t needed;
3560 uint32_t count;
3562 r.in.flags = PRINTER_ENUM_LOCAL;
3563 r.in.server = "";
3564 r.in.level = levels[i];
3565 r.in.buffer = NULL;
3566 r.in.offered = 0;
3567 r.out.needed = &needed;
3568 r.out.count = &count;
3569 r.out.info = &info;
3571 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
3573 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3574 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3576 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3577 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3578 data_blob_clear(&blob);
3579 r.in.buffer = &blob;
3580 r.in.offered = needed;
3581 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3584 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3586 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
3588 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3590 if (!info) {
3591 torture_comment(tctx, "No printers returned\n");
3592 return true;
3595 for (j=0;j<count;j++) {
3596 if (r.in.level == 1) {
3597 char *unc = talloc_strdup(tctx, info[j].info1.name);
3598 char *slash, *name;
3599 name = unc;
3600 if (unc[0] == '\\' && unc[1] == '\\') {
3601 unc +=2;
3603 slash = strchr(unc, '\\');
3604 if (slash) {
3605 slash++;
3606 name = slash;
3608 if (!test_OpenPrinter(tctx, p, name)) {
3609 ret = false;
3611 if (!test_OpenPrinterEx(tctx, p, name)) {
3612 ret = false;
3618 return ret;
3621 static bool test_GetPrinterDriver(struct torture_context *tctx,
3622 struct dcerpc_pipe *p,
3623 struct policy_handle *handle,
3624 const char *driver_name)
3626 struct spoolss_GetPrinterDriver r;
3627 uint32_t needed;
3629 r.in.handle = handle;
3630 r.in.architecture = "W32X86";
3631 r.in.level = 1;
3632 r.in.buffer = NULL;
3633 r.in.offered = 0;
3634 r.out.needed = &needed;
3636 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
3638 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3639 "failed to call GetPrinterDriver");
3640 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3641 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3642 data_blob_clear(&blob);
3643 r.in.buffer = &blob;
3644 r.in.offered = needed;
3645 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3646 "failed to call GetPrinterDriver");
3649 torture_assert_werr_ok(tctx, r.out.result,
3650 "failed to call GetPrinterDriver");
3652 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3654 return true;
3657 static bool test_GetPrinterDriver2(struct torture_context *tctx,
3658 struct dcerpc_pipe *p,
3659 struct policy_handle *handle,
3660 const char *driver_name)
3662 struct spoolss_GetPrinterDriver2 r;
3663 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
3664 uint32_t needed;
3665 uint32_t server_major_version;
3666 uint32_t server_minor_version;
3667 int i;
3669 r.in.handle = handle;
3670 r.in.architecture = SPOOLSS_ARCHITECTURE_NT_X86;
3671 r.in.client_major_version = 3;
3672 r.in.client_minor_version = 0;
3673 r.out.needed = &needed;
3674 r.out.server_major_version = &server_major_version;
3675 r.out.server_minor_version = &server_minor_version;
3677 for (i=0;i<ARRAY_SIZE(levels);i++) {
3679 r.in.buffer = NULL;
3680 r.in.offered = 0;
3681 r.in.level = levels[i];
3683 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
3684 driver_name, r.in.level);
3686 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3687 "failed to call GetPrinterDriver2");
3688 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3689 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3690 data_blob_clear(&blob);
3691 r.in.buffer = &blob;
3692 r.in.offered = needed;
3693 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3694 "failed to call GetPrinterDriver2");
3697 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
3698 switch (r.in.level) {
3699 case 101:
3700 case 8:
3701 continue;
3702 default:
3703 break;
3707 torture_assert_werr_ok(tctx, r.out.result,
3708 "failed to call GetPrinterDriver2");
3710 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3713 return true;
3716 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3717 struct dcerpc_pipe *p)
3719 struct spoolss_EnumPrinterDrivers r;
3720 NTSTATUS status;
3721 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3722 int i;
3724 for (i=0;i<ARRAY_SIZE(levels);i++) {
3726 uint32_t needed;
3727 uint32_t count;
3728 union spoolss_DriverInfo *info;
3730 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3731 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
3732 r.in.level = levels[i];
3733 r.in.buffer = NULL;
3734 r.in.offered = 0;
3735 r.out.needed = &needed;
3736 r.out.count = &count;
3737 r.out.info = &info;
3739 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
3741 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3743 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3745 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3746 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3747 data_blob_clear(&blob);
3748 r.in.buffer = &blob;
3749 r.in.offered = needed;
3750 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3753 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3755 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
3757 if (!info) {
3758 torture_comment(tctx, "No printer drivers returned\n");
3759 break;
3762 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3765 return true;
3768 static bool test_DeletePrinter(struct torture_context *tctx,
3769 struct dcerpc_pipe *p,
3770 struct policy_handle *handle)
3772 struct spoolss_DeletePrinter r;
3774 torture_comment(tctx, "Testing DeletePrinter\n");
3776 r.in.handle = handle;
3778 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
3779 "failed to delete printer");
3780 torture_assert_werr_ok(tctx, r.out.result,
3781 "failed to delete printer");
3783 return true;
3786 static bool test_EnumPrinters_findname(struct torture_context *tctx,
3787 struct dcerpc_pipe *p,
3788 uint32_t flags,
3789 uint32_t level,
3790 const char *name,
3791 bool *found)
3793 struct spoolss_EnumPrinters e;
3794 uint32_t count;
3795 union spoolss_PrinterInfo *info;
3796 uint32_t needed;
3797 int i;
3799 *found = false;
3801 e.in.flags = flags;
3802 e.in.server = NULL;
3803 e.in.level = level;
3804 e.in.buffer = NULL;
3805 e.in.offered = 0;
3806 e.out.count = &count;
3807 e.out.info = &info;
3808 e.out.needed = &needed;
3810 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3811 "failed to enum printers");
3813 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
3814 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3815 data_blob_clear(&blob);
3816 e.in.buffer = &blob;
3817 e.in.offered = needed;
3819 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3820 "failed to enum printers");
3823 torture_assert_werr_ok(tctx, e.out.result,
3824 "failed to enum printers");
3826 for (i=0; i < count; i++) {
3828 const char *current = NULL;
3830 switch (level) {
3831 case 1:
3832 current = info[i].info1.name;
3833 break;
3836 if (strequal(current, name)) {
3837 *found = true;
3838 break;
3842 return true;
3845 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
3846 struct dcerpc_pipe *p,
3847 const char *printername,
3848 bool ex)
3850 WERROR result;
3851 struct spoolss_AddPrinter r;
3852 struct spoolss_AddPrinterEx rex;
3853 struct spoolss_SetPrinterInfoCtr info_ctr;
3854 struct spoolss_SetPrinterInfo1 info1;
3855 struct spoolss_DevmodeContainer devmode_ctr;
3856 struct sec_desc_buf secdesc_ctr;
3857 struct spoolss_UserLevelCtr userlevel_ctr;
3858 struct policy_handle handle;
3859 bool found = false;
3861 ZERO_STRUCT(devmode_ctr);
3862 ZERO_STRUCT(secdesc_ctr);
3863 ZERO_STRUCT(userlevel_ctr);
3864 ZERO_STRUCT(info1);
3866 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3868 /* try to add printer to wellknown printer list (level 1) */
3870 userlevel_ctr.level = 1;
3872 info_ctr.info.info1 = &info1;
3873 info_ctr.level = 1;
3875 rex.in.server = NULL;
3876 rex.in.info_ctr = &info_ctr;
3877 rex.in.devmode_ctr = &devmode_ctr;
3878 rex.in.secdesc_ctr = &secdesc_ctr;
3879 rex.in.userlevel_ctr = &userlevel_ctr;
3880 rex.out.handle = &handle;
3882 r.in.server = NULL;
3883 r.in.info_ctr = &info_ctr;
3884 r.in.devmode_ctr = &devmode_ctr;
3885 r.in.secdesc_ctr = &secdesc_ctr;
3886 r.out.handle = &handle;
3888 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3889 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3890 "failed to add printer");
3891 result = ex ? rex.out.result : r.out.result;
3892 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3893 "unexpected result code");
3895 info1.name = printername;
3896 info1.flags = PRINTER_ATTRIBUTE_SHARED;
3898 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3899 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3900 "failed to add printer");
3901 result = ex ? rex.out.result : r.out.result;
3902 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3903 "unexpected result code");
3905 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3906 better do a real check to see the printer is really there */
3908 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3909 PRINTER_ENUM_NETWORK, 1,
3910 printername,
3911 &found),
3912 "failed to enum printers");
3914 torture_assert(tctx, found, "failed to find newly added printer");
3916 info1.flags = 0;
3918 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3919 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3920 "failed to add printer");
3921 result = ex ? rex.out.result : r.out.result;
3922 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3923 "unexpected result code");
3925 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3926 better do a real check to see the printer has really been removed
3927 from the well known printer list */
3929 found = false;
3931 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3932 PRINTER_ENUM_NETWORK, 1,
3933 printername,
3934 &found),
3935 "failed to enum printers");
3936 #if 0
3937 torture_assert(tctx, !found, "printer still in well known printer list");
3938 #endif
3939 return true;
3942 static bool test_AddPrinter_normal(struct torture_context *tctx,
3943 struct dcerpc_pipe *p,
3944 struct policy_handle *handle_p,
3945 const char *printername,
3946 const char *drivername,
3947 const char *portname,
3948 bool ex)
3950 WERROR result;
3951 struct spoolss_AddPrinter r;
3952 struct spoolss_AddPrinterEx rex;
3953 struct spoolss_SetPrinterInfoCtr info_ctr;
3954 struct spoolss_SetPrinterInfo2 info2;
3955 struct spoolss_DevmodeContainer devmode_ctr;
3956 struct sec_desc_buf secdesc_ctr;
3957 struct spoolss_UserLevelCtr userlevel_ctr;
3958 struct policy_handle handle;
3959 bool found = false;
3961 ZERO_STRUCT(devmode_ctr);
3962 ZERO_STRUCT(secdesc_ctr);
3963 ZERO_STRUCT(userlevel_ctr);
3965 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3967 userlevel_ctr.level = 1;
3969 rex.in.server = NULL;
3970 rex.in.info_ctr = &info_ctr;
3971 rex.in.devmode_ctr = &devmode_ctr;
3972 rex.in.secdesc_ctr = &secdesc_ctr;
3973 rex.in.userlevel_ctr = &userlevel_ctr;
3974 rex.out.handle = &handle;
3976 r.in.server = NULL;
3977 r.in.info_ctr = &info_ctr;
3978 r.in.devmode_ctr = &devmode_ctr;
3979 r.in.secdesc_ctr = &secdesc_ctr;
3980 r.out.handle = &handle;
3982 again:
3984 /* try to add printer to printer list (level 2) */
3986 ZERO_STRUCT(info2);
3988 info_ctr.info.info2 = &info2;
3989 info_ctr.level = 2;
3991 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3992 dcerpc_spoolss_AddPrinter(p, tctx, &r),
3993 "failed to add printer");
3994 result = ex ? rex.out.result : r.out.result;
3995 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3996 "unexpected result code");
3998 info2.printername = printername;
4000 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4001 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4002 "failed to add printer");
4003 result = ex ? rex.out.result : r.out.result;
4005 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4006 struct policy_handle printer_handle;
4008 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4009 "failed to open printer handle");
4011 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4012 "failed to delete printer");
4014 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4015 "failed to close server handle");
4017 goto again;
4020 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4021 "unexpected result code");
4023 info2.portname = portname;
4025 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4026 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4027 "failed to add printer");
4028 result = ex ? rex.out.result : r.out.result;
4029 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4030 "unexpected result code");
4032 info2.drivername = drivername;
4034 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4035 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4036 "failed to add printer");
4037 result = ex ? rex.out.result : r.out.result;
4039 /* w2k8r2 allows to add printer w/o defining printprocessor */
4041 if (!W_ERROR_IS_OK(result)) {
4042 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4043 "unexpected result code");
4045 info2.printprocessor = "winprint";
4047 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4048 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4049 "failed to add printer");
4050 result = ex ? rex.out.result : r.out.result;
4051 torture_assert_werr_ok(tctx, result,
4052 "failed to add printer");
4055 *handle_p = handle;
4057 /* we are paranoid, really check if the printer is there now */
4059 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4060 PRINTER_ENUM_LOCAL, 1,
4061 printername,
4062 &found),
4063 "failed to enum printers");
4064 torture_assert(tctx, found, "failed to find newly added printer");
4066 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4067 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4068 "failed to add printer");
4069 result = ex ? rex.out.result : r.out.result;
4070 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4071 "unexpected result code");
4073 return true;
4076 static bool test_AddPrinterEx(struct torture_context *tctx,
4077 struct dcerpc_pipe *p,
4078 struct policy_handle *handle_p,
4079 const char *printername,
4080 const char *drivername,
4081 const char *portname)
4083 bool ret = true;
4085 if (!torture_setting_bool(tctx, "samba3", false)) {
4086 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4087 torture_comment(tctx, "failed to add printer to well known list\n");
4088 ret = false;
4092 if (!test_AddPrinter_normal(tctx, p, handle_p,
4093 printername, drivername, portname,
4094 true)) {
4095 torture_comment(tctx, "failed to add printer to printer list\n");
4096 ret = false;
4099 return ret;
4102 static bool test_AddPrinter(struct torture_context *tctx,
4103 struct dcerpc_pipe *p,
4104 struct policy_handle *handle_p,
4105 const char *printername,
4106 const char *drivername,
4107 const char *portname)
4109 bool ret = true;
4111 if (!torture_setting_bool(tctx, "samba3", false)) {
4112 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4113 torture_comment(tctx, "failed to add printer to well known list\n");
4114 ret = false;
4118 if (!test_AddPrinter_normal(tctx, p, handle_p,
4119 printername, drivername, portname,
4120 false)) {
4121 torture_comment(tctx, "failed to add printer to printer list\n");
4122 ret = false;
4125 return ret;
4128 static bool test_printer_info(struct torture_context *tctx,
4129 struct dcerpc_pipe *p,
4130 struct policy_handle *handle)
4132 bool ret = true;
4134 if (!test_PrinterInfo(tctx, p, handle)) {
4135 ret = false;
4138 if (!test_SetPrinter_errors(tctx, p, handle)) {
4139 ret = false;
4142 return ret;
4145 static bool test_EnumPrinterKey(struct torture_context *tctx,
4146 struct dcerpc_pipe *p,
4147 struct policy_handle *handle,
4148 const char *key_name,
4149 const char ***array)
4151 struct spoolss_EnumPrinterKey r;
4152 uint32_t needed = 0;
4153 union spoolss_KeyNames key_buffer;
4154 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4155 uint32_t _ndr_size;
4156 int i;
4158 r.in.handle = handle;
4159 r.in.key_name = key_name;
4160 r.out.key_buffer = &key_buffer;
4161 r.out.needed = &needed;
4162 r.out._ndr_size = &_ndr_size;
4164 for (i=0; i < ARRAY_SIZE(offered); i++) {
4166 if (offered[i] < 0 && needed) {
4167 if (needed <= 4) {
4168 continue;
4170 r.in.offered = needed + offered[i];
4171 } else {
4172 r.in.offered = offered[i];
4175 ZERO_STRUCT(key_buffer);
4177 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4179 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4180 "failed to call EnumPrinterKey");
4181 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4183 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4184 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4185 _ndr_size, r.in.offered/2));
4187 r.in.offered = needed;
4188 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4189 "failed to call EnumPrinterKey");
4192 if (offered[i] > 0) {
4193 torture_assert_werr_ok(tctx, r.out.result,
4194 "failed to call EnumPrinterKey");
4197 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4198 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4199 _ndr_size, r.in.offered/2));
4201 torture_assert(tctx, (*r.out.needed <= r.in.offered),
4202 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
4204 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
4205 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
4207 if (key_buffer.string_array) {
4208 uint32_t calc_needed = 0;
4209 int s;
4210 for (s=0; key_buffer.string_array[s]; s++) {
4211 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
4213 if (!key_buffer.string_array[0]) {
4214 calc_needed += 2;
4216 calc_needed += 2;
4218 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
4219 "EnumPrinterKey unexpected size");
4223 if (array) {
4224 *array = key_buffer.string_array;
4227 return true;
4230 bool test_printer_keys(struct torture_context *tctx,
4231 struct dcerpc_pipe *p,
4232 struct policy_handle *handle)
4234 const char **key_array = NULL;
4235 int i;
4237 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4238 "failed to call test_EnumPrinterKey");
4240 for (i=0; key_array && key_array[i]; i++) {
4241 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4242 "failed to call test_EnumPrinterKey");
4244 for (i=0; key_array && key_array[i]; i++) {
4245 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
4246 "failed to call test_EnumPrinterDataEx");
4249 return true;
4252 static bool test_printer(struct torture_context *tctx,
4253 struct dcerpc_pipe *p)
4255 bool ret = true;
4256 struct policy_handle handle[2];
4257 bool found = false;
4258 const char *drivername = "Microsoft XPS Document Writer";
4259 const char *portname = "LPT1:";
4261 /* test printer created via AddPrinter */
4263 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
4264 return false;
4267 if (!test_printer_info(tctx, p, &handle[0])) {
4268 ret = false;
4271 if (!test_PrinterInfo_SD(tctx, p, &handle[0])) {
4272 ret = false;
4275 if (!test_PrinterInfo_DevMode(tctx, p, &handle[0], TORTURE_PRINTER)) {
4276 ret = false;
4279 if (!test_printer_keys(tctx, p, &handle[0])) {
4280 ret = false;
4283 if (!test_DeletePrinter(tctx, p, &handle[0])) {
4284 ret = false;
4287 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4288 TORTURE_PRINTER, &found)) {
4289 ret = false;
4292 torture_assert(tctx, !found, "deleted printer still there");
4294 /* test printer created via AddPrinterEx */
4296 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
4297 return false;
4300 if (!test_printer_info(tctx, p, &handle[1])) {
4301 ret = false;
4304 if (!test_printer_keys(tctx, p, &handle[1])) {
4305 ret = false;
4308 if (!test_DeletePrinter(tctx, p, &handle[1])) {
4309 ret = false;
4312 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4313 TORTURE_PRINTER_EX, &found)) {
4314 ret = false;
4317 torture_assert(tctx, !found, "deleted printer still there");
4319 return ret;
4322 bool torture_rpc_spoolss(struct torture_context *torture)
4324 NTSTATUS status;
4325 struct dcerpc_pipe *p;
4326 bool ret = true;
4327 struct test_spoolss_context *ctx;
4329 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
4330 if (!NT_STATUS_IS_OK(status)) {
4331 return false;
4334 ctx = talloc_zero(torture, struct test_spoolss_context);
4336 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
4337 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
4338 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
4339 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
4340 ret &= test_EnumPorts(torture, p, ctx);
4341 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
4342 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
4343 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
4344 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
4345 ret &= test_EnumMonitors(torture, p, ctx);
4346 ret &= test_EnumPrintProcessors(torture, p, ctx);
4347 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
4348 ret &= test_EnumPrinters(torture, p, ctx);
4349 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
4350 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
4351 ret &= test_OpenPrinter_badname(torture, p, "");
4352 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
4353 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
4354 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
4355 ret &= test_OpenPrinter_badname(torture, p,
4356 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
4359 ret &= test_AddPort(torture, p);
4360 ret &= test_EnumPorts_old(torture, p);
4361 ret &= test_EnumPrinters_old(torture, p);
4362 ret &= test_EnumPrinterDrivers_old(torture, p);
4364 return ret;
4367 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
4369 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
4371 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
4372 "printer", &ndr_table_spoolss);
4374 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
4376 return suite;