s4-smbtorture: fix test_SetPrinterDataEx_matrix() call. sorry...
[Samba/nascimento.git] / source4 / torture / rpc / spoolss.c
blob909c37246dd4ebb5d7b854c2ee252d1a1406697d
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_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
36 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
37 #define TORTURE_PRINTER "torture_printer"
38 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
39 #define TORTURE_PRINTER_EX "torture_printer_ex"
41 struct test_spoolss_context {
42 /* print server handle */
43 struct policy_handle server_handle;
45 /* for EnumPorts */
46 uint32_t port_count[3];
47 union spoolss_PortInfo *ports[3];
49 /* for EnumPrinterDrivers */
50 uint32_t driver_count[8];
51 union spoolss_DriverInfo *drivers[8];
53 /* for EnumMonitors */
54 uint32_t monitor_count[3];
55 union spoolss_MonitorInfo *monitors[3];
57 /* for EnumPrintProcessors */
58 uint32_t print_processor_count[2];
59 union spoolss_PrintProcessorInfo *print_processors[2];
61 /* for EnumPrinters */
62 uint32_t printer_count[6];
63 union spoolss_PrinterInfo *printers[6];
66 #define COMPARE_STRING(tctx, c,r,e) \
67 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
69 /* not every compiler supports __typeof__() */
70 #if (__GNUC__ >= 3)
71 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
72 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
73 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
75 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
76 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
78 } while(0)
79 #else
80 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
81 #endif
83 #define COMPARE_UINT32(tctx, c, r, e) do {\
84 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
85 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
86 } while(0)
88 #define COMPARE_UINT64(tctx, c, r, e) do {\
89 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
90 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
91 } while(0)
94 #define COMPARE_NTTIME(tctx, c, r, e) do {\
95 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
96 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
97 } while(0)
99 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
100 int __i; \
101 if (!c.e && !r.e) { \
102 break; \
104 if (c.e && !r.e) { \
105 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
107 if (!c.e && r.e) { \
108 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
110 for (__i=0;c.e[__i] != NULL; __i++) { \
111 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
113 } while(0)
115 #define CHECK_ALIGN(size, n) do {\
116 if (size % n) {\
117 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
118 size, n, size + n - (size % n));\
120 } while(0)
122 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
124 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
125 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
126 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
127 uint32_t round_size = DO_ROUND(size, align);\
128 if (round_size != needed) {\
129 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
130 CHECK_ALIGN(size, align);\
133 } while(0)
135 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
136 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
137 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
138 uint32_t round_size = DO_ROUND(size, align);\
139 if (round_size != needed) {\
140 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
141 CHECK_ALIGN(size, align);\
144 } while(0)
146 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
147 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
148 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
149 uint32_t round_size = DO_ROUND(size, align);\
150 if (round_size != needed) {\
151 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
152 CHECK_ALIGN(size, align);\
155 } while(0)
157 static bool test_OpenPrinter_server(struct torture_context *tctx,
158 struct dcerpc_pipe *p,
159 struct policy_handle *server_handle)
161 NTSTATUS status;
162 struct spoolss_OpenPrinter op;
164 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
165 op.in.datatype = NULL;
166 op.in.devmode_ctr.devmode= NULL;
167 op.in.access_mask = 0;
168 op.out.handle = server_handle;
170 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
172 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
173 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
174 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
176 return true;
179 static bool test_EnumPorts(struct torture_context *tctx,
180 struct dcerpc_pipe *p,
181 struct test_spoolss_context *ctx)
183 NTSTATUS status;
184 struct spoolss_EnumPorts r;
185 uint16_t levels[] = { 1, 2 };
186 int i, j;
188 for (i=0;i<ARRAY_SIZE(levels);i++) {
189 int level = levels[i];
190 DATA_BLOB blob;
191 uint32_t needed;
192 uint32_t count;
193 union spoolss_PortInfo *info;
195 r.in.servername = "";
196 r.in.level = level;
197 r.in.buffer = NULL;
198 r.in.offered = 0;
199 r.out.needed = &needed;
200 r.out.count = &count;
201 r.out.info = &info;
203 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
205 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
206 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
207 if (W_ERROR_IS_OK(r.out.result)) {
208 /* TODO: do some more checks here */
209 continue;
211 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
212 "EnumPorts unexpected return code");
214 blob = data_blob_talloc(ctx, NULL, needed);
215 data_blob_clear(&blob);
216 r.in.buffer = &blob;
217 r.in.offered = needed;
219 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
220 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
222 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
224 torture_assert(tctx, info, "EnumPorts returned no info");
226 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
228 ctx->port_count[level] = count;
229 ctx->ports[level] = info;
232 for (i=1;i<ARRAY_SIZE(levels);i++) {
233 int level = levels[i];
234 int old_level = levels[i-1];
235 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
236 "EnumPorts invalid value");
238 /* if the array sizes are not the same we would maybe segfault in the following code */
240 for (i=0;i<ARRAY_SIZE(levels);i++) {
241 int level = levels[i];
242 for (j=0;j<ctx->port_count[level];j++) {
243 union spoolss_PortInfo *cur = &ctx->ports[level][j];
244 union spoolss_PortInfo *ref = &ctx->ports[2][j];
245 switch (level) {
246 case 1:
247 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
248 break;
249 case 2:
250 /* level 2 is our reference, and it makes no sense to compare it to itself */
251 break;
256 return true;
259 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
260 struct dcerpc_pipe *p,
261 struct test_spoolss_context *ctx,
262 const char *environment)
264 NTSTATUS status;
265 struct spoolss_GetPrintProcessorDirectory r;
266 struct {
267 uint16_t level;
268 const char *server;
269 } levels[] = {{
270 .level = 1,
271 .server = NULL
273 .level = 1,
274 .server = ""
276 .level = 78,
277 .server = ""
279 .level = 1,
280 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
282 .level = 1024,
283 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
286 int i;
287 uint32_t needed;
289 for (i=0;i<ARRAY_SIZE(levels);i++) {
290 int level = levels[i].level;
291 DATA_BLOB blob;
293 r.in.server = levels[i].server;
294 r.in.environment = environment;
295 r.in.level = level;
296 r.in.buffer = NULL;
297 r.in.offered = 0;
298 r.out.needed = &needed;
300 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
302 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
303 torture_assert_ntstatus_ok(tctx, status,
304 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
305 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
306 "GetPrintProcessorDirectory unexpected return code");
308 blob = data_blob_talloc(ctx, NULL, needed);
309 data_blob_clear(&blob);
310 r.in.buffer = &blob;
311 r.in.offered = needed;
313 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
314 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
316 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
318 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
321 return true;
325 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
326 struct dcerpc_pipe *p,
327 struct test_spoolss_context *ctx,
328 const char *environment)
330 NTSTATUS status;
331 struct spoolss_GetPrinterDriverDirectory r;
332 struct {
333 uint16_t level;
334 const char *server;
335 } levels[] = {{
336 .level = 1,
337 .server = NULL
339 .level = 1,
340 .server = ""
342 .level = 78,
343 .server = ""
345 .level = 1,
346 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
348 .level = 1024,
349 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
352 int i;
353 uint32_t needed;
355 for (i=0;i<ARRAY_SIZE(levels);i++) {
356 int level = levels[i].level;
357 DATA_BLOB blob;
359 r.in.server = levels[i].server;
360 r.in.environment = environment;
361 r.in.level = level;
362 r.in.buffer = NULL;
363 r.in.offered = 0;
364 r.out.needed = &needed;
366 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
368 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
369 torture_assert_ntstatus_ok(tctx, status,
370 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
371 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
372 "GetPrinterDriverDirectory unexpected return code");
374 blob = data_blob_talloc(ctx, NULL, needed);
375 data_blob_clear(&blob);
376 r.in.buffer = &blob;
377 r.in.offered = needed;
379 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
380 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
382 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
384 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
387 return true;
390 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
391 struct dcerpc_pipe *p,
392 struct test_spoolss_context *ctx,
393 const char *architecture)
395 NTSTATUS status;
396 struct spoolss_EnumPrinterDrivers r;
397 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
398 int i, j;
400 for (i=0;i<ARRAY_SIZE(levels);i++) {
401 int level = levels[i];
402 DATA_BLOB blob;
403 uint32_t needed;
404 uint32_t count;
405 union spoolss_DriverInfo *info;
407 /* FIXME: gd, come back and fix "" as server, and handle
408 * priority of returned error codes in torture test and samba 3
409 * server */
411 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
412 r.in.environment = architecture;
413 r.in.level = level;
414 r.in.buffer = NULL;
415 r.in.offered = 0;
416 r.out.needed = &needed;
417 r.out.count = &count;
418 r.out.info = &info;
420 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
422 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
423 torture_assert_ntstatus_ok(tctx, status,
424 "dcerpc_spoolss_EnumPrinterDrivers failed");
425 if (W_ERROR_IS_OK(r.out.result)) {
426 /* TODO: do some more checks here */
427 continue;
429 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
430 blob = data_blob_talloc(ctx, NULL, needed);
431 data_blob_clear(&blob);
432 r.in.buffer = &blob;
433 r.in.offered = needed;
435 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
436 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
439 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
441 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
443 ctx->driver_count[level] = count;
444 ctx->drivers[level] = info;
447 for (i=1;i<ARRAY_SIZE(levels);i++) {
448 int level = levels[i];
449 int old_level = levels[i-1];
451 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
452 "EnumPrinterDrivers invalid value");
455 for (i=0;i<ARRAY_SIZE(levels);i++) {
456 int level = levels[i];
458 for (j=0;j<ctx->driver_count[level];j++) {
459 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
460 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
462 switch (level) {
463 case 1:
464 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
465 break;
466 case 2:
467 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
468 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
469 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
470 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
471 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
472 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
473 break;
474 case 3:
475 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
476 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
477 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
478 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
479 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
480 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
481 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
482 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
483 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
484 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
485 break;
486 case 4:
487 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
488 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
489 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
490 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
491 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
492 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
493 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
494 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
495 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
496 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
497 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
498 break;
499 case 5:
500 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
501 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
502 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
503 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
504 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
505 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
506 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
507 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
508 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
509 break;
510 case 6:
511 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
512 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
513 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
514 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
515 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
516 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
517 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
518 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
519 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
520 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
521 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
522 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
523 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
524 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
525 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
526 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
527 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
528 break;
529 case 8:
530 /* level 8 is our reference, and it makes no sense to compare it to itself */
531 break;
536 return true;
539 static bool test_EnumMonitors(struct torture_context *tctx,
540 struct dcerpc_pipe *p,
541 struct test_spoolss_context *ctx)
543 NTSTATUS status;
544 struct spoolss_EnumMonitors r;
545 uint16_t levels[] = { 1, 2 };
546 int i, j;
548 for (i=0;i<ARRAY_SIZE(levels);i++) {
549 int level = levels[i];
550 DATA_BLOB blob;
551 uint32_t needed;
552 uint32_t count;
553 union spoolss_MonitorInfo *info;
555 r.in.servername = "";
556 r.in.level = level;
557 r.in.buffer = NULL;
558 r.in.offered = 0;
559 r.out.needed = &needed;
560 r.out.count = &count;
561 r.out.info = &info;
563 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
565 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
566 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
567 if (W_ERROR_IS_OK(r.out.result)) {
568 /* TODO: do some more checks here */
569 continue;
571 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
572 "EnumMonitors failed");
574 blob = data_blob_talloc(ctx, NULL, needed);
575 data_blob_clear(&blob);
576 r.in.buffer = &blob;
577 r.in.offered = needed;
579 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
580 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
582 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
584 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
586 ctx->monitor_count[level] = count;
587 ctx->monitors[level] = info;
590 for (i=1;i<ARRAY_SIZE(levels);i++) {
591 int level = levels[i];
592 int old_level = levels[i-1];
593 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
594 "EnumMonitors invalid value");
597 for (i=0;i<ARRAY_SIZE(levels);i++) {
598 int level = levels[i];
599 for (j=0;j<ctx->monitor_count[level];j++) {
600 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
601 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
602 switch (level) {
603 case 1:
604 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
605 break;
606 case 2:
607 /* level 2 is our reference, and it makes no sense to compare it to itself */
608 break;
613 return true;
616 static bool test_EnumPrintProcessors(struct torture_context *tctx,
617 struct dcerpc_pipe *p,
618 struct test_spoolss_context *ctx,
619 const char *environment)
621 NTSTATUS status;
622 struct spoolss_EnumPrintProcessors r;
623 uint16_t levels[] = { 1 };
624 int i, j;
626 for (i=0;i<ARRAY_SIZE(levels);i++) {
627 int level = levels[i];
628 DATA_BLOB blob;
629 uint32_t needed;
630 uint32_t count;
631 union spoolss_PrintProcessorInfo *info;
633 r.in.servername = "";
634 r.in.environment = environment;
635 r.in.level = level;
636 r.in.buffer = NULL;
637 r.in.offered = 0;
638 r.out.needed = &needed;
639 r.out.count = &count;
640 r.out.info = &info;
642 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
644 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
645 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
646 if (W_ERROR_IS_OK(r.out.result)) {
647 /* TODO: do some more checks here */
648 continue;
650 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
651 "EnumPrintProcessors unexpected return code");
653 blob = data_blob_talloc(ctx, NULL, needed);
654 data_blob_clear(&blob);
655 r.in.buffer = &blob;
656 r.in.offered = needed;
658 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
659 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
661 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
663 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
665 ctx->print_processor_count[level] = count;
666 ctx->print_processors[level] = info;
669 for (i=1;i<ARRAY_SIZE(levels);i++) {
670 int level = levels[i];
671 int old_level = levels[i-1];
672 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
673 "EnumPrintProcessors failed");
676 for (i=0;i<ARRAY_SIZE(levels);i++) {
677 int level = levels[i];
678 for (j=0;j<ctx->print_processor_count[level];j++) {
679 #if 0
680 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
681 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
682 #endif
683 switch (level) {
684 case 1:
685 /* level 1 is our reference, and it makes no sense to compare it to itself */
686 break;
691 return true;
694 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
695 struct dcerpc_pipe *p,
696 struct test_spoolss_context *ctx)
698 NTSTATUS status;
699 struct spoolss_EnumPrintProcDataTypes r;
700 uint16_t levels[] = { 1 };
701 int i;
703 for (i=0;i<ARRAY_SIZE(levels);i++) {
704 int level = levels[i];
705 DATA_BLOB blob;
706 uint32_t needed;
707 uint32_t count;
708 union spoolss_PrintProcDataTypesInfo *info;
710 r.in.servername = "";
711 r.in.print_processor_name = "winprint";
712 r.in.level = level;
713 r.in.buffer = NULL;
714 r.in.offered = 0;
715 r.out.needed = &needed;
716 r.out.count = &count;
717 r.out.info = &info;
719 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
721 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
722 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
723 if (W_ERROR_IS_OK(r.out.result)) {
724 /* TODO: do some more checks here */
725 continue;
727 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
728 "EnumPrintProcDataTypes unexpected return code");
730 blob = data_blob_talloc(ctx, NULL, needed);
731 data_blob_clear(&blob);
732 r.in.buffer = &blob;
733 r.in.offered = needed;
735 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
736 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
738 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
740 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
744 return true;
748 static bool test_EnumPrinters(struct torture_context *tctx,
749 struct dcerpc_pipe *p,
750 struct test_spoolss_context *ctx)
752 struct spoolss_EnumPrinters r;
753 NTSTATUS status;
754 uint16_t levels[] = { 0, 1, 2, 4, 5 };
755 int i, j;
757 for (i=0;i<ARRAY_SIZE(levels);i++) {
758 int level = levels[i];
759 DATA_BLOB blob;
760 uint32_t needed;
761 uint32_t count;
762 union spoolss_PrinterInfo *info;
764 r.in.flags = PRINTER_ENUM_LOCAL;
765 r.in.server = "";
766 r.in.level = level;
767 r.in.buffer = NULL;
768 r.in.offered = 0;
769 r.out.needed = &needed;
770 r.out.count = &count;
771 r.out.info = &info;
773 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
775 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
776 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
777 if (W_ERROR_IS_OK(r.out.result)) {
778 /* TODO: do some more checks here */
779 continue;
781 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
782 "EnumPrinters unexpected return code");
784 blob = data_blob_talloc(ctx, NULL, needed);
785 data_blob_clear(&blob);
786 r.in.buffer = &blob;
787 r.in.offered = needed;
789 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
790 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
792 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
794 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
796 ctx->printer_count[level] = count;
797 ctx->printers[level] = info;
800 for (i=1;i<ARRAY_SIZE(levels);i++) {
801 int level = levels[i];
802 int old_level = levels[i-1];
803 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
804 "EnumPrinters invalid value");
807 for (i=0;i<ARRAY_SIZE(levels);i++) {
808 int level = levels[i];
809 for (j=0;j<ctx->printer_count[level];j++) {
810 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
811 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
812 switch (level) {
813 case 0:
814 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
815 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
816 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
817 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
818 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
819 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
820 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
821 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
822 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
823 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
824 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
825 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
826 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
827 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
828 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
829 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
830 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
831 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
832 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
833 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
834 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
835 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
836 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
837 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
838 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
839 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
840 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
841 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
842 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
843 break;
844 case 1:
845 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
846 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
847 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
848 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
849 break;
850 case 2:
851 /* level 2 is our reference, and it makes no sense to compare it to itself */
852 break;
853 case 4:
854 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
855 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
856 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
857 break;
858 case 5:
859 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
860 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
861 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
862 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
863 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
864 break;
869 /* TODO:
870 * - verify that the port of a printer was in the list returned by EnumPorts
873 return true;
876 static bool test_GetPrinterDriver2(struct torture_context *tctx,
877 struct dcerpc_pipe *p,
878 struct policy_handle *handle,
879 const char *driver_name,
880 const char *environment);
882 bool test_GetPrinter_level(struct torture_context *tctx,
883 struct dcerpc_pipe *p,
884 struct policy_handle *handle,
885 uint32_t level,
886 union spoolss_PrinterInfo *info)
888 struct spoolss_GetPrinter r;
889 uint32_t needed;
891 r.in.handle = handle;
892 r.in.level = level;
893 r.in.buffer = NULL;
894 r.in.offered = 0;
895 r.out.needed = &needed;
897 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
899 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
900 "GetPrinter failed");
902 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
903 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
904 data_blob_clear(&blob);
905 r.in.buffer = &blob;
906 r.in.offered = needed;
908 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
909 "GetPrinter failed");
912 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
914 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
916 if (info && r.out.info) {
917 *info = *r.out.info;
920 return true;
924 static bool test_GetPrinter(struct torture_context *tctx,
925 struct dcerpc_pipe *p,
926 struct policy_handle *handle,
927 const char *environment)
929 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
930 int i;
932 for (i=0;i<ARRAY_SIZE(levels);i++) {
934 union spoolss_PrinterInfo info;
936 ZERO_STRUCT(info);
938 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
939 "failed to call GetPrinter");
941 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
942 torture_assert(tctx,
943 test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername, environment),
944 "failed to call test_GetPrinterDriver2");
948 return true;
951 static bool test_SetPrinter(struct torture_context *tctx,
952 struct dcerpc_pipe *p,
953 struct policy_handle *handle,
954 struct spoolss_SetPrinterInfoCtr *info_ctr,
955 struct spoolss_DevmodeContainer *devmode_ctr,
956 struct sec_desc_buf *secdesc_ctr,
957 enum spoolss_PrinterControl command)
959 struct spoolss_SetPrinter r;
961 r.in.handle = handle;
962 r.in.info_ctr = info_ctr;
963 r.in.devmode_ctr = devmode_ctr;
964 r.in.secdesc_ctr = secdesc_ctr;
965 r.in.command = command;
967 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
969 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
970 "failed to call SetPrinter");
971 torture_assert_werr_ok(tctx, r.out.result,
972 "failed to call SetPrinter");
974 return true;
977 static bool test_SetPrinter_errors(struct torture_context *tctx,
978 struct dcerpc_pipe *p,
979 struct policy_handle *handle)
981 struct spoolss_SetPrinter r;
982 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
983 int i;
985 struct spoolss_SetPrinterInfoCtr info_ctr;
986 struct spoolss_DevmodeContainer devmode_ctr;
987 struct sec_desc_buf secdesc_ctr;
989 info_ctr.level = 0;
990 info_ctr.info.info0 = NULL;
992 ZERO_STRUCT(devmode_ctr);
993 ZERO_STRUCT(secdesc_ctr);
995 r.in.handle = handle;
996 r.in.info_ctr = &info_ctr;
997 r.in.devmode_ctr = &devmode_ctr;
998 r.in.secdesc_ctr = &secdesc_ctr;
999 r.in.command = 0;
1001 torture_comment(tctx, "Testing SetPrinter all zero\n");
1003 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1004 "failed to call SetPrinter");
1005 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1006 "failed to call SetPrinter");
1008 again:
1009 for (i=0; i < ARRAY_SIZE(levels); i++) {
1011 struct spoolss_SetPrinterInfo0 info0;
1012 struct spoolss_SetPrinterInfo1 info1;
1013 struct spoolss_SetPrinterInfo2 info2;
1014 struct spoolss_SetPrinterInfo3 info3;
1015 struct spoolss_SetPrinterInfo4 info4;
1016 struct spoolss_SetPrinterInfo5 info5;
1017 struct spoolss_SetPrinterInfo6 info6;
1018 struct spoolss_SetPrinterInfo7 info7;
1019 struct spoolss_SetPrinterInfo8 info8;
1020 struct spoolss_SetPrinterInfo9 info9;
1023 info_ctr.level = levels[i];
1024 switch (levels[i]) {
1025 case 0:
1026 ZERO_STRUCT(info0);
1027 info_ctr.info.info0 = &info0;
1028 break;
1029 case 1:
1030 ZERO_STRUCT(info1);
1031 info_ctr.info.info1 = &info1;
1032 break;
1033 case 2:
1034 ZERO_STRUCT(info2);
1035 info_ctr.info.info2 = &info2;
1036 break;
1037 case 3:
1038 ZERO_STRUCT(info3);
1039 info_ctr.info.info3 = &info3;
1040 break;
1041 case 4:
1042 ZERO_STRUCT(info4);
1043 info_ctr.info.info4 = &info4;
1044 break;
1045 case 5:
1046 ZERO_STRUCT(info5);
1047 info_ctr.info.info5 = &info5;
1048 break;
1049 case 6:
1050 ZERO_STRUCT(info6);
1051 info_ctr.info.info6 = &info6;
1052 break;
1053 case 7:
1054 ZERO_STRUCT(info7);
1055 info_ctr.info.info7 = &info7;
1056 break;
1057 case 8:
1058 ZERO_STRUCT(info8);
1059 info_ctr.info.info8 = &info8;
1060 break;
1061 case 9:
1062 ZERO_STRUCT(info9);
1063 info_ctr.info.info9 = &info9;
1064 break;
1067 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1068 info_ctr.level, r.in.command);
1070 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1071 "failed to call SetPrinter");
1073 switch (r.in.command) {
1074 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1075 /* is ignored for all levels other then 0 */
1076 if (info_ctr.level > 0) {
1077 /* ignored then */
1078 break;
1080 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1081 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1082 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1083 if (info_ctr.level > 0) {
1084 /* is invalid for all levels other then 0 */
1085 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1086 "unexpected error code returned");
1087 continue;
1088 } else {
1089 torture_assert_werr_ok(tctx, r.out.result,
1090 "failed to call SetPrinter with non 0 command");
1091 continue;
1093 break;
1095 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1096 /* FIXME: gd needs further investigation */
1097 default:
1098 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1099 "unexpected error code returned");
1100 continue;
1103 switch (info_ctr.level) {
1104 case 1:
1105 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1106 "unexpected error code returned");
1107 break;
1108 case 2:
1109 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1110 "unexpected error code returned");
1111 break;
1112 case 3:
1113 case 4:
1114 case 5:
1115 case 7:
1116 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1117 "unexpected error code returned");
1118 break;
1119 case 9:
1120 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1121 "unexpected error code returned");
1122 break;
1123 default:
1124 torture_assert_werr_ok(tctx, r.out.result,
1125 "failed to call SetPrinter");
1126 break;
1130 if (r.in.command < 5) {
1131 r.in.command++;
1132 goto again;
1135 return true;
1138 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1140 if ((r->level == 2) && (r->info.info2)) {
1141 r->info.info2->secdesc_ptr = 0;
1142 r->info.info2->devmode_ptr = 0;
1146 static bool test_PrinterInfo(struct torture_context *tctx,
1147 struct dcerpc_pipe *p,
1148 struct policy_handle *handle)
1150 NTSTATUS status;
1151 struct spoolss_SetPrinter s;
1152 struct spoolss_GetPrinter q;
1153 struct spoolss_GetPrinter q0;
1154 struct spoolss_SetPrinterInfoCtr info_ctr;
1155 union spoolss_PrinterInfo info;
1156 struct spoolss_DevmodeContainer devmode_ctr;
1157 struct sec_desc_buf secdesc_ctr;
1158 uint32_t needed;
1159 bool ret = true;
1160 int i;
1162 uint32_t status_list[] = {
1163 /* these do not stick
1164 PRINTER_STATUS_PAUSED,
1165 PRINTER_STATUS_ERROR,
1166 PRINTER_STATUS_PENDING_DELETION, */
1167 PRINTER_STATUS_PAPER_JAM,
1168 PRINTER_STATUS_PAPER_OUT,
1169 PRINTER_STATUS_MANUAL_FEED,
1170 PRINTER_STATUS_PAPER_PROBLEM,
1171 PRINTER_STATUS_OFFLINE,
1172 PRINTER_STATUS_IO_ACTIVE,
1173 PRINTER_STATUS_BUSY,
1174 PRINTER_STATUS_PRINTING,
1175 PRINTER_STATUS_OUTPUT_BIN_FULL,
1176 PRINTER_STATUS_NOT_AVAILABLE,
1177 PRINTER_STATUS_WAITING,
1178 PRINTER_STATUS_PROCESSING,
1179 PRINTER_STATUS_INITIALIZING,
1180 PRINTER_STATUS_WARMING_UP,
1181 PRINTER_STATUS_TONER_LOW,
1182 PRINTER_STATUS_NO_TONER,
1183 PRINTER_STATUS_PAGE_PUNT,
1184 PRINTER_STATUS_USER_INTERVENTION,
1185 PRINTER_STATUS_OUT_OF_MEMORY,
1186 PRINTER_STATUS_DOOR_OPEN,
1187 PRINTER_STATUS_SERVER_UNKNOWN,
1188 PRINTER_STATUS_POWER_SAVE,
1189 /* these do not stick
1190 0x02000000,
1191 0x04000000,
1192 0x08000000,
1193 0x10000000,
1194 0x20000000,
1195 0x40000000,
1196 0x80000000 */
1198 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1199 uint32_t attribute_list[] = {
1200 PRINTER_ATTRIBUTE_QUEUED,
1201 /* fails with WERR_INVALID_DATATYPE:
1202 PRINTER_ATTRIBUTE_DIRECT, */
1203 /* does not stick
1204 PRINTER_ATTRIBUTE_DEFAULT, */
1205 PRINTER_ATTRIBUTE_SHARED,
1206 /* does not stick
1207 PRINTER_ATTRIBUTE_NETWORK, */
1208 PRINTER_ATTRIBUTE_HIDDEN,
1209 PRINTER_ATTRIBUTE_LOCAL,
1210 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1211 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1212 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1213 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1214 /* does not stick
1215 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1216 /* fails with WERR_INVALID_DATATYPE:
1217 PRINTER_ATTRIBUTE_RAW_ONLY, */
1218 /* these do not stick
1219 PRINTER_ATTRIBUTE_PUBLISHED,
1220 PRINTER_ATTRIBUTE_FAX,
1221 PRINTER_ATTRIBUTE_TS,
1222 0x00010000,
1223 0x00020000,
1224 0x00040000,
1225 0x00080000,
1226 0x00100000,
1227 0x00200000,
1228 0x00400000,
1229 0x00800000,
1230 0x01000000,
1231 0x02000000,
1232 0x04000000,
1233 0x08000000,
1234 0x10000000,
1235 0x20000000,
1236 0x40000000,
1237 0x80000000 */
1240 ZERO_STRUCT(devmode_ctr);
1241 ZERO_STRUCT(secdesc_ctr);
1243 s.in.handle = handle;
1244 s.in.command = 0;
1245 s.in.info_ctr = &info_ctr;
1246 s.in.devmode_ctr = &devmode_ctr;
1247 s.in.secdesc_ctr = &secdesc_ctr;
1249 q.in.handle = handle;
1250 q.out.info = &info;
1251 q0 = q;
1253 #define TESTGETCALL(call, r) \
1254 r.in.buffer = NULL; \
1255 r.in.offered = 0;\
1256 r.out.needed = &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_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1265 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1266 data_blob_clear(&blob); \
1267 r.in.buffer = &blob; \
1268 r.in.offered = needed; \
1270 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1271 if (!NT_STATUS_IS_OK(status)) { \
1272 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1273 r.in.level, nt_errstr(status), __location__); \
1274 ret = false; \
1275 break; \
1277 if (!W_ERROR_IS_OK(r.out.result)) { \
1278 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1279 r.in.level, win_errstr(r.out.result), __location__); \
1280 ret = false; \
1281 break; \
1285 #define TESTSETCALL_EXP(call, r, err) \
1286 clear_info2(&info_ctr);\
1287 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1288 if (!NT_STATUS_IS_OK(status)) { \
1289 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1290 r.in.info_ctr->level, nt_errstr(status), __location__); \
1291 ret = false; \
1292 break; \
1294 if (!W_ERROR_IS_OK(err)) { \
1295 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1296 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1297 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1298 ret = false; \
1300 break; \
1302 if (!W_ERROR_IS_OK(r.out.result)) { \
1303 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1304 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1305 ret = false; \
1306 break; \
1309 #define TESTSETCALL(call, r) \
1310 TESTSETCALL_EXP(call, r, WERR_OK)
1312 #define STRING_EQUAL(s1, s2, field) \
1313 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1314 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1315 #field, s2, __location__); \
1316 ret = false; \
1317 break; \
1320 #define MEM_EQUAL(s1, s2, length, field) \
1321 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1322 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1323 #field, (const char *)s2, __location__); \
1324 ret = false; \
1325 break; \
1328 #define INT_EQUAL(i1, i2, field) \
1329 if (i1 != i2) { \
1330 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1331 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1332 ret = false; \
1333 break; \
1336 #define SD_EQUAL(sd1, sd2, field) \
1337 if (!security_descriptor_equal(sd1, sd2)) { \
1338 torture_comment(tctx, "Failed to set %s (%s)\n", \
1339 #field, __location__); \
1340 ret = false; \
1341 break; \
1344 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1345 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1346 q.in.level = lvl1; \
1347 TESTGETCALL(GetPrinter, q) \
1348 info_ctr.level = lvl1; \
1349 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1350 info_ctr.info.info ## lvl1->field1 = value;\
1351 TESTSETCALL_EXP(SetPrinter, s, err) \
1352 info_ctr.info.info ## lvl1->field1 = ""; \
1353 TESTGETCALL(GetPrinter, q) \
1354 info_ctr.info.info ## lvl1->field1 = value; \
1355 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1356 q.in.level = lvl2; \
1357 TESTGETCALL(GetPrinter, q) \
1358 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1359 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1360 } while (0)
1362 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1363 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1364 } while (0);
1366 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1367 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1368 q.in.level = lvl1; \
1369 TESTGETCALL(GetPrinter, q) \
1370 info_ctr.level = lvl1; \
1371 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1372 info_ctr.info.info ## lvl1->field1 = value; \
1373 TESTSETCALL(SetPrinter, s) \
1374 info_ctr.info.info ## lvl1->field1 = 0; \
1375 TESTGETCALL(GetPrinter, q) \
1376 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1377 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1378 q.in.level = lvl2; \
1379 TESTGETCALL(GetPrinter, q) \
1380 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1381 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1382 } while (0)
1384 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1385 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1386 } while (0)
1388 q0.in.level = 0;
1389 do { TESTGETCALL(GetPrinter, q0) } while (0);
1391 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1392 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1394 /* level 0 printername does not stick */
1395 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1396 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1397 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1398 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1399 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1400 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1401 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1402 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1403 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1404 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1405 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1406 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1407 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1408 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1409 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1411 /* servername can be set but does not stick
1412 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1413 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1414 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1417 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1418 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1419 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1420 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1421 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1423 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1424 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1425 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1426 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1427 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1428 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1429 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1430 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1431 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1432 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1434 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1435 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1436 attribute_list[i],
1437 (attribute_list[i] | default_attribute)
1438 ); */
1439 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1440 attribute_list[i],
1441 (attribute_list[i] | default_attribute)
1443 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1444 attribute_list[i],
1445 (attribute_list[i] | default_attribute)
1447 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1448 attribute_list[i],
1449 (attribute_list[i] | default_attribute)
1451 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1452 attribute_list[i],
1453 (attribute_list[i] | default_attribute)
1454 ); */
1455 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1456 attribute_list[i],
1457 (attribute_list[i] | default_attribute)
1459 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1460 attribute_list[i],
1461 (attribute_list[i] | default_attribute)
1463 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1464 attribute_list[i],
1465 (attribute_list[i] | default_attribute)
1467 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1468 attribute_list[i],
1469 (attribute_list[i] | default_attribute)
1470 ); */
1471 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1472 attribute_list[i],
1473 (attribute_list[i] | default_attribute)
1475 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1476 attribute_list[i],
1477 (attribute_list[i] | default_attribute)
1479 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1480 attribute_list[i],
1481 (attribute_list[i] | default_attribute)
1485 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1486 /* level 2 sets do not stick
1487 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1488 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1489 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1490 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1491 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1492 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1495 /* priorities need to be between 0 and 99
1496 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1497 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1498 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1499 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1500 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1501 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1502 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1503 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1504 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1506 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1507 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1509 /* does not stick
1510 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1511 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1513 /* does not stick
1514 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1515 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1517 /* FIXME: gd also test devmode and secdesc behavior */
1520 /* verify composition of level 1 description field */
1521 const char *description;
1522 const char *tmp;
1524 q0.in.level = 1;
1525 do { TESTGETCALL(GetPrinter, q0) } while (0);
1527 description = talloc_strdup(tctx, q0.out.info->info1.description);
1529 q0.in.level = 2;
1530 do { TESTGETCALL(GetPrinter, q0) } while (0);
1532 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1533 q0.out.info->info2.printername,
1534 q0.out.info->info2.drivername,
1535 q0.out.info->info2.location);
1537 do { STRING_EQUAL(description, tmp, "description")} while (0);
1540 return ret;
1543 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1544 do { struct dom_sid *__got = (got), *__expected = (expected); \
1545 if (!dom_sid_equal(__got, __expected)) { \
1546 torture_result(torture_ctx, TORTURE_FAIL, \
1547 __location__": "#got" was %s, expected %s: %s", \
1548 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1549 return false; \
1551 } while(0)
1553 static bool test_security_descriptor_equal(struct torture_context *tctx,
1554 const struct security_descriptor *sd1,
1555 const struct security_descriptor *sd2)
1557 if (sd1 == sd2) {
1558 return true;
1561 if (!sd1 || !sd2) {
1562 torture_comment(tctx, "%s\n", __location__);
1563 return false;
1566 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1567 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1569 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1570 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1572 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1573 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1574 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1575 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1576 return false;
1578 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1579 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1580 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1581 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1582 return false;
1585 return true;
1588 static bool test_sd_set_level(struct torture_context *tctx,
1589 struct dcerpc_pipe *p,
1590 struct policy_handle *handle,
1591 uint32_t level,
1592 struct security_descriptor *sd)
1594 struct spoolss_SetPrinterInfoCtr info_ctr;
1595 struct spoolss_DevmodeContainer devmode_ctr;
1596 struct sec_desc_buf secdesc_ctr;
1598 ZERO_STRUCT(devmode_ctr);
1599 ZERO_STRUCT(secdesc_ctr);
1601 switch (level) {
1602 case 2: {
1603 union spoolss_PrinterInfo info;
1604 struct spoolss_SetPrinterInfo2 info2;
1605 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1607 info2.servername = info.info2.servername;
1608 info2.printername = info.info2.printername;
1609 info2.sharename = info.info2.sharename;
1610 info2.portname = info.info2.portname;
1611 info2.drivername = info.info2.drivername;
1612 info2.comment = info.info2.comment;
1613 info2.location = info.info2.location;
1614 info2.devmode_ptr = 0;
1615 info2.sepfile = info.info2.sepfile;
1616 info2.printprocessor = info.info2.printprocessor;
1617 info2.datatype = info.info2.datatype;
1618 info2.parameters = info.info2.parameters;
1619 info2.secdesc_ptr = 0;
1620 info2.attributes = info.info2.attributes;
1621 info2.priority = info.info2.priority;
1622 info2.defaultpriority = info.info2.defaultpriority;
1623 info2.starttime = info.info2.starttime;
1624 info2.untiltime = info.info2.untiltime;
1625 info2.status = info.info2.status;
1626 info2.cjobs = info.info2.cjobs;
1627 info2.averageppm = info.info2.averageppm;
1629 info_ctr.level = 2;
1630 info_ctr.info.info2 = &info2;
1632 break;
1634 case 3: {
1635 struct spoolss_SetPrinterInfo3 info3;
1637 info3.sec_desc_ptr = 0;
1639 info_ctr.level = 3;
1640 info_ctr.info.info3 = &info3;
1642 break;
1644 default:
1645 return false;
1648 secdesc_ctr.sd = sd;
1650 torture_assert(tctx,
1651 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1653 return true;
1656 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1657 struct dcerpc_pipe *p,
1658 struct policy_handle *handle)
1660 union spoolss_PrinterInfo info;
1661 struct security_descriptor *sd1, *sd2;
1662 int i;
1664 /* just compare level 2 and level 3 */
1666 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1668 sd1 = info.info2.secdesc;
1670 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 3, &info), "");
1672 sd2 = info.info3.secdesc;
1674 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1675 "SD level 2 != SD level 3");
1678 /* query level 2, set level 2, query level 2 */
1680 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1682 sd1 = info.info2.secdesc;
1684 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
1686 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1688 sd2 = info.info2.secdesc;
1689 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1690 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1691 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1694 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1695 "SD level 2 != SD level 2 after SD has been set via level 2");
1698 /* query level 2, set level 3, query level 2 */
1700 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1702 sd1 = info.info2.secdesc;
1704 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1706 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1708 sd2 = info.info2.secdesc;
1710 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1711 "SD level 2 != SD level 2 after SD has been set via level 3");
1713 /* set modified sd level 3, query level 2 */
1715 for (i=0; i < 93; i++) {
1716 struct security_ace a;
1717 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1718 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1719 a.flags = 0;
1720 a.size = 0; /* autogenerated */
1721 a.access_mask = 0;
1722 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1723 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1726 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1728 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1729 sd2 = info.info2.secdesc;
1731 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1732 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1733 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1736 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1737 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1740 return true;
1744 * wrapper call that saves original sd, runs tests, and restores sd
1747 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1748 struct dcerpc_pipe *p,
1749 struct policy_handle *handle)
1751 union spoolss_PrinterInfo info;
1752 struct security_descriptor *sd;
1753 bool ret = true;
1755 torture_comment(tctx, "\nTesting Printer Security Descriptors\n");
1757 /* save original sd */
1759 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
1760 "failed to get initial security descriptor");
1762 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1764 /* run tests */
1766 ret = test_PrinterInfo_SDs(tctx, p, handle);
1768 /* restore original sd */
1770 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd),
1771 "failed to restore initial security descriptor");
1773 torture_comment(tctx, "Printer Security Descriptors test %s\n",
1774 ret ? "succeeded" : "failed");
1777 return ret;
1780 static bool test_devmode_set_level(struct torture_context *tctx,
1781 struct dcerpc_pipe *p,
1782 struct policy_handle *handle,
1783 uint32_t level,
1784 struct spoolss_DeviceMode *devmode)
1786 struct spoolss_SetPrinterInfoCtr info_ctr;
1787 struct spoolss_DevmodeContainer devmode_ctr;
1788 struct sec_desc_buf secdesc_ctr;
1790 ZERO_STRUCT(devmode_ctr);
1791 ZERO_STRUCT(secdesc_ctr);
1793 switch (level) {
1794 case 2: {
1795 union spoolss_PrinterInfo info;
1796 struct spoolss_SetPrinterInfo2 info2;
1797 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1799 info2.servername = info.info2.servername;
1800 info2.printername = info.info2.printername;
1801 info2.sharename = info.info2.sharename;
1802 info2.portname = info.info2.portname;
1803 info2.drivername = info.info2.drivername;
1804 info2.comment = info.info2.comment;
1805 info2.location = info.info2.location;
1806 info2.devmode_ptr = 0;
1807 info2.sepfile = info.info2.sepfile;
1808 info2.printprocessor = info.info2.printprocessor;
1809 info2.datatype = info.info2.datatype;
1810 info2.parameters = info.info2.parameters;
1811 info2.secdesc_ptr = 0;
1812 info2.attributes = info.info2.attributes;
1813 info2.priority = info.info2.priority;
1814 info2.defaultpriority = info.info2.defaultpriority;
1815 info2.starttime = info.info2.starttime;
1816 info2.untiltime = info.info2.untiltime;
1817 info2.status = info.info2.status;
1818 info2.cjobs = info.info2.cjobs;
1819 info2.averageppm = info.info2.averageppm;
1821 info_ctr.level = 2;
1822 info_ctr.info.info2 = &info2;
1824 break;
1826 case 8: {
1827 struct spoolss_SetPrinterInfo8 info8;
1829 info8.devmode_ptr = 0;
1831 info_ctr.level = 8;
1832 info_ctr.info.info8 = &info8;
1834 break;
1836 default:
1837 return false;
1840 devmode_ctr.devmode = devmode;
1842 torture_assert(tctx,
1843 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1845 return true;
1849 static bool test_devicemode_equal(struct torture_context *tctx,
1850 const struct spoolss_DeviceMode *d1,
1851 const struct spoolss_DeviceMode *d2)
1853 if (d1 == d2) {
1854 return true;
1857 if (!d1 || !d2) {
1858 torture_comment(tctx, "%s\n", __location__);
1859 return false;
1861 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1862 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1863 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1864 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1865 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1866 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1867 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1868 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1869 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1870 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1871 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1872 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1873 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1874 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1875 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1876 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1877 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1878 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1879 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1880 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1881 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1882 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1883 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1884 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1885 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1886 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1887 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1888 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1889 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1890 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1891 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1892 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1893 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1894 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1895 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1897 return true;
1900 static bool test_devicemode_full(struct torture_context *tctx,
1901 struct dcerpc_pipe *p,
1902 struct policy_handle *handle)
1904 struct spoolss_SetPrinter s;
1905 struct spoolss_GetPrinter q;
1906 struct spoolss_GetPrinter q0;
1907 struct spoolss_SetPrinterInfoCtr info_ctr;
1908 struct spoolss_SetPrinterInfo8 info8;
1909 union spoolss_PrinterInfo info;
1910 struct spoolss_DevmodeContainer devmode_ctr;
1911 struct sec_desc_buf secdesc_ctr;
1912 uint32_t needed;
1913 bool ret = true;
1914 NTSTATUS status;
1916 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1917 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1918 q.in.level = lvl1; \
1919 TESTGETCALL(GetPrinter, q) \
1920 info_ctr.level = lvl1; \
1921 if (lvl1 == 2) {\
1922 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1923 } else if (lvl1 == 8) {\
1924 info_ctr.info.info ## lvl1 = &info8; \
1926 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1927 devmode_ctr.devmode->field1 = value; \
1928 TESTSETCALL(SetPrinter, s) \
1929 TESTGETCALL(GetPrinter, q) \
1930 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1931 q.in.level = lvl2; \
1932 TESTGETCALL(GetPrinter, q) \
1933 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1934 } while (0)
1936 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1937 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1938 } while (0)
1940 ZERO_STRUCT(devmode_ctr);
1941 ZERO_STRUCT(secdesc_ctr);
1942 ZERO_STRUCT(info8);
1944 s.in.handle = handle;
1945 s.in.command = 0;
1946 s.in.info_ctr = &info_ctr;
1947 s.in.devmode_ctr = &devmode_ctr;
1948 s.in.secdesc_ctr = &secdesc_ctr;
1950 q.in.handle = handle;
1951 q.out.info = &info;
1952 q0 = q;
1954 #if 0
1955 const char *devicename;/* [charset(UTF16)] */
1956 enum spoolss_DeviceModeSpecVersion specversion;
1957 uint16_t driverversion;
1958 uint16_t size;
1959 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1960 uint32_t fields;
1961 #endif
1963 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
1964 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
1965 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
1966 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
1967 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
1968 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
1969 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
1970 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
1971 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
1972 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
1973 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
1974 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
1975 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
1976 #if 0
1977 const char *formname;/* [charset(UTF16)] */
1978 #endif
1979 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
1980 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
1981 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
1982 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
1983 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
1984 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
1985 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
1986 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
1987 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
1988 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
1989 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
1990 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
1991 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
1992 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
1994 return ret;
1997 static bool call_OpenPrinterEx(struct torture_context *tctx,
1998 struct dcerpc_pipe *p,
1999 const char *name,
2000 struct spoolss_DeviceMode *devmode,
2001 struct policy_handle *handle);
2003 static bool test_ClosePrinter(struct torture_context *tctx,
2004 struct dcerpc_pipe *p,
2005 struct policy_handle *handle);
2007 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2008 struct dcerpc_pipe *p,
2009 struct policy_handle *handle,
2010 const char *name)
2012 union spoolss_PrinterInfo info;
2013 struct spoolss_DeviceMode *devmode;
2014 struct spoolss_DeviceMode *devmode2;
2015 struct policy_handle handle_devmode;
2017 /* simply compare level8 and level2 devmode */
2019 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2021 devmode = info.info8.devmode;
2023 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2025 devmode2 = info.info2.devmode;
2027 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2028 "DM level 8 != DM level 2");
2031 /* set devicemode level 8 and see if it persists */
2033 devmode->copies = 93;
2034 devmode->formname = talloc_strdup(tctx, "Legal");
2036 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode), "");
2038 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2040 devmode2 = info.info8.devmode;
2042 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2043 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2045 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2047 devmode2 = info.info2.devmode;
2049 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2050 "modified DM level 8 != DM level 2");
2053 /* set devicemode level 2 and see if it persists */
2055 devmode->copies = 39;
2056 devmode->formname = talloc_strdup(tctx, "Executive");
2058 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 2, devmode), "");
2060 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2062 devmode2 = info.info8.devmode;
2064 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2065 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2067 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2069 devmode2 = info.info2.devmode;
2071 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2072 "modified DM level 8 != DM level 2");
2075 /* check every single bit in public part of devicemode */
2077 torture_assert(tctx, test_devicemode_full(tctx, p, handle),
2078 "failed to set every single devicemode component");
2081 /* change formname upon open and see if it persists in getprinter calls */
2083 devmode->formname = talloc_strdup(tctx, "A4");
2084 devmode->copies = 42;
2086 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2087 "failed to open printer handle");
2089 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 8, &info), "");
2091 devmode2 = info.info8.devmode;
2093 if (strequal(devmode->devicename, devmode2->devicename)) {
2094 torture_comment(tctx, "devicenames are the same\n");
2095 } else {
2096 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2097 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2100 if (strequal(devmode->formname, devmode2->formname)) {
2101 torture_warning(tctx, "formname are the same\n");
2102 } else {
2103 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2104 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2107 if (devmode->copies == devmode2->copies) {
2108 torture_warning(tctx, "copies are the same\n");
2109 } else {
2110 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2111 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2114 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 2, &info), "");
2116 devmode2 = info.info2.devmode;
2118 if (strequal(devmode->devicename, devmode2->devicename)) {
2119 torture_comment(tctx, "devicenames are the same\n");
2120 } else {
2121 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2122 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2125 if (strequal(devmode->formname, devmode2->formname)) {
2126 torture_warning(tctx, "formname is the same\n");
2127 } else {
2128 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2129 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2132 if (devmode->copies == devmode2->copies) {
2133 torture_warning(tctx, "copies are the same\n");
2134 } else {
2135 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2136 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2139 test_ClosePrinter(tctx, p, &handle_devmode);
2141 return true;
2145 * wrapper call that saves original devmode, runs tests, and restores devmode
2148 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2149 struct dcerpc_pipe *p,
2150 struct policy_handle *handle,
2151 const char *name)
2153 union spoolss_PrinterInfo info;
2154 struct spoolss_DeviceMode *devmode;
2155 bool ret = true;
2157 torture_comment(tctx, "\nTesting Printer Devicemodes\n");
2159 /* save original devmode */
2161 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info),
2162 "failed to get initial global devicemode");
2164 devmode = info.info8.devmode;
2166 /* run tests */
2168 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2170 /* restore original devmode */
2172 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode),
2173 "failed to restore initial global device mode");
2175 torture_comment(tctx, "Printer Devicemodes test %s\n",
2176 ret ? "succeeded" : "failed");
2179 return ret;
2182 static bool test_ClosePrinter(struct torture_context *tctx,
2183 struct dcerpc_pipe *p,
2184 struct policy_handle *handle)
2186 NTSTATUS status;
2187 struct spoolss_ClosePrinter r;
2189 r.in.handle = handle;
2190 r.out.handle = handle;
2192 torture_comment(tctx, "Testing ClosePrinter\n");
2194 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
2195 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2196 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2198 return true;
2201 static bool test_GetForm(struct torture_context *tctx,
2202 struct dcerpc_pipe *p,
2203 struct policy_handle *handle,
2204 const char *form_name,
2205 uint32_t level)
2207 NTSTATUS status;
2208 struct spoolss_GetForm r;
2209 uint32_t needed;
2211 r.in.handle = handle;
2212 r.in.form_name = form_name;
2213 r.in.level = level;
2214 r.in.buffer = NULL;
2215 r.in.offered = 0;
2216 r.out.needed = &needed;
2218 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
2220 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2221 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2223 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2224 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2225 data_blob_clear(&blob);
2226 r.in.buffer = &blob;
2227 r.in.offered = needed;
2228 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2229 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2231 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2233 torture_assert(tctx, r.out.info, "No form info returned");
2236 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2238 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2240 return true;
2243 static bool test_EnumForms(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 struct policy_handle *handle, bool print_server)
2247 NTSTATUS status;
2248 struct spoolss_EnumForms r;
2249 bool ret = true;
2250 uint32_t needed;
2251 uint32_t count;
2252 uint32_t levels[] = { 1, 2 };
2253 int i;
2255 for (i=0; i<ARRAY_SIZE(levels); i++) {
2257 union spoolss_FormInfo *info;
2259 r.in.handle = handle;
2260 r.in.level = levels[i];
2261 r.in.buffer = NULL;
2262 r.in.offered = 0;
2263 r.out.needed = &needed;
2264 r.out.count = &count;
2265 r.out.info = &info;
2267 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
2269 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2270 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2272 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2273 break;
2276 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
2277 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2279 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2280 int j;
2281 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2282 data_blob_clear(&blob);
2283 r.in.buffer = &blob;
2284 r.in.offered = needed;
2286 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2288 torture_assert(tctx, info, "No forms returned");
2290 for (j = 0; j < count; j++) {
2291 if (!print_server)
2292 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
2296 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2298 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2300 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2303 return true;
2306 static bool test_DeleteForm(struct torture_context *tctx,
2307 struct dcerpc_pipe *p,
2308 struct policy_handle *handle,
2309 const char *form_name)
2311 NTSTATUS status;
2312 struct spoolss_DeleteForm r;
2314 r.in.handle = handle;
2315 r.in.form_name = form_name;
2317 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
2319 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
2321 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
2323 return true;
2326 static bool test_AddForm(struct torture_context *tctx,
2327 struct dcerpc_pipe *p,
2328 struct policy_handle *handle, bool print_server)
2330 struct spoolss_AddForm r;
2331 struct spoolss_AddFormInfo1 addform;
2332 const char *form_name = "testform3";
2333 NTSTATUS status;
2334 bool ret = true;
2336 r.in.handle = handle;
2337 r.in.level = 1;
2338 r.in.info.info1 = &addform;
2339 addform.flags = SPOOLSS_FORM_USER;
2340 addform.form_name = form_name;
2341 addform.size.width = 50;
2342 addform.size.height = 25;
2343 addform.area.left = 5;
2344 addform.area.top = 10;
2345 addform.area.right = 45;
2346 addform.area.bottom = 15;
2348 status = dcerpc_spoolss_AddForm(p, tctx, &r);
2350 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
2352 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
2354 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2357 struct spoolss_SetForm sf;
2358 struct spoolss_AddFormInfo1 setform;
2360 sf.in.handle = handle;
2361 sf.in.form_name = form_name;
2362 sf.in.level = 1;
2363 sf.in.info.info1= &setform;
2364 setform.flags = addform.flags;
2365 setform.form_name = addform.form_name;
2366 setform.size = addform.size;
2367 setform.area = addform.area;
2369 setform.size.width = 1234;
2371 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
2373 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
2375 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
2378 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2381 struct spoolss_EnumForms e;
2382 union spoolss_FormInfo *info;
2383 uint32_t needed;
2384 uint32_t count;
2385 bool found = false;
2387 e.in.handle = handle;
2388 e.in.level = 1;
2389 e.in.buffer = NULL;
2390 e.in.offered = 0;
2391 e.out.needed = &needed;
2392 e.out.count = &count;
2393 e.out.info = &info;
2395 torture_comment(tctx, "Testing EnumForms level 1\n");
2397 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2398 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2400 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
2401 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2403 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2404 int j;
2405 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2406 data_blob_clear(&blob);
2407 e.in.buffer = &blob;
2408 e.in.offered = needed;
2410 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2412 torture_assert(tctx, info, "No forms returned");
2414 for (j = 0; j < count; j++) {
2415 if (strequal(form_name, info[j].info1.form_name)) {
2416 found = true;
2417 break;
2421 torture_assert(tctx, found, "Newly added form not found in enum call");
2424 if (!test_DeleteForm(tctx, p, handle, form_name)) {
2425 ret = false;
2428 return ret;
2431 static bool test_EnumPorts_old(struct torture_context *tctx,
2432 struct dcerpc_pipe *p)
2434 NTSTATUS status;
2435 struct spoolss_EnumPorts r;
2436 uint32_t needed;
2437 uint32_t count;
2438 union spoolss_PortInfo *info;
2440 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2441 dcerpc_server_name(p));
2442 r.in.level = 2;
2443 r.in.buffer = NULL;
2444 r.in.offered = 0;
2445 r.out.needed = &needed;
2446 r.out.count = &count;
2447 r.out.info = &info;
2449 torture_comment(tctx, "Testing EnumPorts\n");
2451 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2453 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2455 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2456 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2457 data_blob_clear(&blob);
2458 r.in.buffer = &blob;
2459 r.in.offered = needed;
2461 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2462 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2463 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2465 torture_assert(tctx, info, "No ports returned");
2468 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2470 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2472 return true;
2475 static bool test_AddPort(struct torture_context *tctx,
2476 struct dcerpc_pipe *p)
2478 NTSTATUS status;
2479 struct spoolss_AddPort r;
2481 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2482 dcerpc_server_name(p));
2483 r.in.unknown = 0;
2484 r.in.monitor_name = "foo";
2486 torture_comment(tctx, "Testing AddPort\n");
2488 status = dcerpc_spoolss_AddPort(p, tctx, &r);
2490 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2492 /* win2k3 returns WERR_NOT_SUPPORTED */
2494 #if 0
2496 if (!W_ERROR_IS_OK(r.out.result)) {
2497 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2498 return false;
2501 #endif
2503 return true;
2506 static bool test_GetJob(struct torture_context *tctx,
2507 struct dcerpc_pipe *p,
2508 struct policy_handle *handle, uint32_t job_id)
2510 NTSTATUS status;
2511 struct spoolss_GetJob r;
2512 union spoolss_JobInfo info;
2513 uint32_t needed;
2514 uint32_t levels[] = {1, 2 /* 3, 4 */};
2515 uint32_t i;
2517 r.in.handle = handle;
2518 r.in.job_id = job_id;
2519 r.in.level = 0;
2520 r.in.buffer = NULL;
2521 r.in.offered = 0;
2522 r.out.needed = &needed;
2523 r.out.info = &info;
2525 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2527 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2528 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2530 for (i = 0; i < ARRAY_SIZE(levels); i++) {
2532 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2534 needed = 0;
2536 r.in.level = levels[i];
2537 r.in.offered = 0;
2538 r.in.buffer = NULL;
2540 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2541 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2543 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2544 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2545 data_blob_clear(&blob);
2546 r.in.buffer = &blob;
2547 r.in.offered = needed;
2549 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2550 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2553 torture_assert(tctx, r.out.info, "No job info returned");
2554 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2556 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2559 return true;
2562 static bool test_SetJob(struct torture_context *tctx,
2563 struct dcerpc_pipe *p,
2564 struct policy_handle *handle, uint32_t job_id,
2565 enum spoolss_JobControl command)
2567 NTSTATUS status;
2568 struct spoolss_SetJob r;
2570 r.in.handle = handle;
2571 r.in.job_id = job_id;
2572 r.in.ctr = NULL;
2573 r.in.command = command;
2575 switch (command) {
2576 case SPOOLSS_JOB_CONTROL_PAUSE:
2577 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2578 break;
2579 case SPOOLSS_JOB_CONTROL_RESUME:
2580 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2581 break;
2582 case SPOOLSS_JOB_CONTROL_CANCEL:
2583 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2584 break;
2585 case SPOOLSS_JOB_CONTROL_RESTART:
2586 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2587 break;
2588 case SPOOLSS_JOB_CONTROL_DELETE:
2589 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2590 break;
2591 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2592 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2593 break;
2594 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2595 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2596 break;
2597 case SPOOLSS_JOB_CONTROL_RETAIN:
2598 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2599 break;
2600 case SPOOLSS_JOB_CONTROL_RELEASE:
2601 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2602 break;
2603 default:
2604 torture_comment(tctx, "Testing SetJob\n");
2605 break;
2608 status = dcerpc_spoolss_SetJob(p, tctx, &r);
2609 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2610 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2612 return true;
2615 static bool test_AddJob(struct torture_context *tctx,
2616 struct dcerpc_pipe *p,
2617 struct policy_handle *handle)
2619 NTSTATUS status;
2620 struct spoolss_AddJob r;
2621 uint32_t needed;
2623 r.in.level = 0;
2624 r.in.handle = handle;
2625 r.in.offered = 0;
2626 r.out.needed = &needed;
2627 r.in.buffer = r.out.buffer = NULL;
2629 torture_comment(tctx, "Testing AddJob\n");
2631 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2632 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2634 r.in.level = 1;
2636 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2637 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2639 return true;
2643 static bool test_EnumJobs(struct torture_context *tctx,
2644 struct dcerpc_pipe *p,
2645 struct policy_handle *handle)
2647 NTSTATUS status;
2648 struct spoolss_EnumJobs r;
2649 uint32_t needed;
2650 uint32_t count;
2651 union spoolss_JobInfo *info;
2653 r.in.handle = handle;
2654 r.in.firstjob = 0;
2655 r.in.numjobs = 0xffffffff;
2656 r.in.level = 1;
2657 r.in.buffer = NULL;
2658 r.in.offered = 0;
2659 r.out.needed = &needed;
2660 r.out.count = &count;
2661 r.out.info = &info;
2663 torture_comment(tctx, "Testing EnumJobs\n");
2665 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2667 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2669 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2670 int j;
2671 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2672 data_blob_clear(&blob);
2673 r.in.buffer = &blob;
2674 r.in.offered = needed;
2676 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2678 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2679 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2680 torture_assert(tctx, info, "No jobs returned");
2682 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2684 for (j = 0; j < count; j++) {
2686 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2687 "failed to call test_GetJob");
2689 /* FIXME - gd */
2690 if (!torture_setting_bool(tctx, "samba3", false)) {
2691 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2692 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2696 } else {
2697 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2700 return true;
2703 static bool test_DoPrintTest(struct torture_context *tctx,
2704 struct dcerpc_pipe *p,
2705 struct policy_handle *handle)
2707 bool ret = true;
2708 NTSTATUS status;
2709 struct spoolss_StartDocPrinter s;
2710 struct spoolss_DocumentInfo1 info1;
2711 struct spoolss_StartPagePrinter sp;
2712 struct spoolss_WritePrinter w;
2713 struct spoolss_EndPagePrinter ep;
2714 struct spoolss_EndDocPrinter e;
2715 int i;
2716 uint32_t job_id;
2717 uint32_t num_written;
2719 torture_comment(tctx, "Testing StartDocPrinter\n");
2721 s.in.handle = handle;
2722 s.in.level = 1;
2723 s.in.info.info1 = &info1;
2724 s.out.job_id = &job_id;
2725 info1.document_name = "TorturePrintJob";
2726 info1.output_file = NULL;
2727 info1.datatype = "RAW";
2729 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2730 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2731 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2733 for (i=1; i < 4; i++) {
2734 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2736 sp.in.handle = handle;
2738 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2739 torture_assert_ntstatus_ok(tctx, status,
2740 "dcerpc_spoolss_StartPagePrinter failed");
2741 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2743 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2745 w.in.handle = handle;
2746 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2747 w.out.num_written = &num_written;
2749 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2750 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2751 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2753 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2755 ep.in.handle = handle;
2757 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2758 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2759 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2762 torture_comment(tctx, "Testing EndDocPrinter\n");
2764 e.in.handle = handle;
2766 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2767 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2768 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2770 ret &= test_AddJob(tctx, p, handle);
2771 ret &= test_EnumJobs(tctx, p, handle);
2773 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2775 return ret;
2778 static bool test_PausePrinter(struct torture_context *tctx,
2779 struct dcerpc_pipe *p,
2780 struct policy_handle *handle)
2782 NTSTATUS status;
2783 struct spoolss_SetPrinter r;
2784 struct spoolss_SetPrinterInfoCtr info_ctr;
2785 struct spoolss_DevmodeContainer devmode_ctr;
2786 struct sec_desc_buf secdesc_ctr;
2788 info_ctr.level = 0;
2789 info_ctr.info.info0 = NULL;
2791 ZERO_STRUCT(devmode_ctr);
2792 ZERO_STRUCT(secdesc_ctr);
2794 r.in.handle = handle;
2795 r.in.info_ctr = &info_ctr;
2796 r.in.devmode_ctr = &devmode_ctr;
2797 r.in.secdesc_ctr = &secdesc_ctr;
2798 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2800 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2802 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2804 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2806 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2808 return true;
2811 static bool test_ResumePrinter(struct torture_context *tctx,
2812 struct dcerpc_pipe *p,
2813 struct policy_handle *handle)
2815 NTSTATUS status;
2816 struct spoolss_SetPrinter r;
2817 struct spoolss_SetPrinterInfoCtr info_ctr;
2818 struct spoolss_DevmodeContainer devmode_ctr;
2819 struct sec_desc_buf secdesc_ctr;
2821 info_ctr.level = 0;
2822 info_ctr.info.info0 = NULL;
2824 ZERO_STRUCT(devmode_ctr);
2825 ZERO_STRUCT(secdesc_ctr);
2827 r.in.handle = handle;
2828 r.in.info_ctr = &info_ctr;
2829 r.in.devmode_ctr = &devmode_ctr;
2830 r.in.secdesc_ctr = &secdesc_ctr;
2831 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2833 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2835 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2837 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2839 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2841 return true;
2844 static bool test_GetPrinterData(struct torture_context *tctx,
2845 struct dcerpc_pipe *p,
2846 struct policy_handle *handle,
2847 const char *value_name,
2848 enum winreg_Type *type_p,
2849 uint8_t **data_p,
2850 uint32_t *needed_p)
2852 NTSTATUS status;
2853 struct spoolss_GetPrinterData r;
2854 uint32_t needed;
2855 enum winreg_Type type;
2856 union spoolss_PrinterData data;
2858 r.in.handle = handle;
2859 r.in.value_name = value_name;
2860 r.in.offered = 0;
2861 r.out.needed = &needed;
2862 r.out.type = &type;
2863 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2865 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2867 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2868 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2870 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2871 r.in.offered = needed;
2872 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2873 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2874 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2877 torture_assert_werr_ok(tctx, r.out.result,
2878 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2880 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2882 if (type_p) {
2883 *type_p = type;
2886 if (data_p) {
2887 *data_p = r.out.data;
2890 if (needed_p) {
2891 *needed_p = needed;
2894 return true;
2897 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2898 struct dcerpc_pipe *p,
2899 struct policy_handle *handle,
2900 const char *key_name,
2901 const char *value_name,
2902 enum winreg_Type *type_p,
2903 uint8_t **data_p,
2904 uint32_t *needed_p)
2906 NTSTATUS status;
2907 struct spoolss_GetPrinterDataEx r;
2908 enum winreg_Type type;
2909 uint32_t needed;
2910 union spoolss_PrinterData data;
2912 r.in.handle = handle;
2913 r.in.key_name = key_name;
2914 r.in.value_name = value_name;
2915 r.in.offered = 0;
2916 r.out.type = &type;
2917 r.out.needed = &needed;
2918 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2920 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2921 r.in.key_name, r.in.value_name);
2923 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2924 if (!NT_STATUS_IS_OK(status)) {
2925 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2926 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2927 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2929 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2932 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2933 r.in.offered = needed;
2934 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2935 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2936 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2939 torture_assert_werr_ok(tctx, r.out.result,
2940 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2942 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2944 if (type_p) {
2945 *type_p = type;
2948 if (data_p) {
2949 *data_p = r.out.data;
2952 if (needed_p) {
2953 *needed_p = needed;
2956 return true;
2959 static bool test_GetPrinterData_list(struct torture_context *tctx,
2960 struct dcerpc_pipe *p,
2961 struct policy_handle *handle)
2963 const char *list[] = {
2964 "W3SvcInstalled",
2965 "BeepEnabled",
2966 "EventLog",
2967 /* "NetPopup", not on w2k8 */
2968 /* "NetPopupToComputer", not on w2k8 */
2969 "MajorVersion",
2970 "MinorVersion",
2971 "DefaultSpoolDirectory",
2972 "Architecture",
2973 "DsPresent",
2974 "OSVersion",
2975 /* "OSVersionEx", not on s3 */
2976 "DNSMachineName"
2978 int i;
2980 for (i=0; i < ARRAY_SIZE(list); i++) {
2981 enum winreg_Type type, type_ex;
2982 uint8_t *data, *data_ex;
2983 uint32_t needed, needed_ex;
2985 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data, &needed),
2986 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2987 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
2988 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2989 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2990 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
2991 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
2994 return true;
2997 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2998 struct policy_handle *handle)
3000 NTSTATUS status;
3001 struct spoolss_EnumPrinterData r;
3003 ZERO_STRUCT(r);
3004 r.in.handle = handle;
3005 r.in.enum_index = 0;
3007 do {
3008 uint32_t value_size = 0;
3009 uint32_t data_size = 0;
3010 enum winreg_Type type = 0;
3012 r.in.value_offered = value_size;
3013 r.out.value_needed = &value_size;
3014 r.in.data_offered = data_size;
3015 r.out.data_needed = &data_size;
3017 r.out.type = &type;
3018 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
3020 torture_comment(tctx, "Testing EnumPrinterData\n");
3022 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
3024 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
3025 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3026 break;
3028 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
3030 r.in.value_offered = value_size;
3031 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
3032 r.in.data_offered = data_size;
3033 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
3035 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
3037 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
3038 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3039 break;
3042 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
3044 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL, NULL),
3045 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
3047 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL, NULL),
3048 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
3050 r.in.enum_index++;
3052 } while (W_ERROR_IS_OK(r.out.result));
3054 return true;
3057 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3058 struct dcerpc_pipe *p,
3059 struct policy_handle *handle,
3060 const char *key_name)
3062 struct spoolss_EnumPrinterDataEx r;
3063 struct spoolss_PrinterEnumValues *info;
3064 uint32_t needed;
3065 uint32_t count;
3067 r.in.handle = handle;
3068 r.in.key_name = key_name;
3069 r.in.offered = 0;
3070 r.out.needed = &needed;
3071 r.out.count = &count;
3072 r.out.info = &info;
3074 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3076 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3077 "EnumPrinterDataEx failed");
3078 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3079 r.in.offered = needed;
3080 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3081 "EnumPrinterDataEx failed");
3084 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3086 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3088 return true;
3092 static bool test_DeletePrinterData(struct torture_context *tctx,
3093 struct dcerpc_pipe *p,
3094 struct policy_handle *handle,
3095 const char *value_name)
3097 NTSTATUS status;
3098 struct spoolss_DeletePrinterData r;
3100 r.in.handle = handle;
3101 r.in.value_name = value_name;
3103 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3104 r.in.value_name);
3106 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3108 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3109 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3111 return true;
3114 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3115 struct dcerpc_pipe *p,
3116 struct policy_handle *handle,
3117 const char *key_name,
3118 const char *value_name)
3120 struct spoolss_DeletePrinterDataEx r;
3122 r.in.handle = handle;
3123 r.in.key_name = key_name;
3124 r.in.value_name = value_name;
3126 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3127 r.in.key_name, r.in.value_name);
3129 torture_assert_ntstatus_ok(tctx,
3130 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3131 "DeletePrinterDataEx failed");
3132 torture_assert_werr_ok(tctx, r.out.result,
3133 "DeletePrinterDataEx failed");
3135 return true;
3138 static bool test_DeletePrinterKey(struct torture_context *tctx,
3139 struct dcerpc_pipe *p,
3140 struct policy_handle *handle,
3141 const char *key_name)
3143 struct spoolss_DeletePrinterKey r;
3145 r.in.handle = handle;
3146 r.in.key_name = key_name;
3148 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3150 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3151 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3152 return true;
3155 torture_assert_ntstatus_ok(tctx,
3156 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3157 "DeletePrinterKey failed");
3158 torture_assert_werr_ok(tctx, r.out.result,
3159 "DeletePrinterKey failed");
3161 return true;
3164 static bool test_SetPrinterData(struct torture_context *tctx,
3165 struct dcerpc_pipe *p,
3166 struct policy_handle *handle)
3168 NTSTATUS status;
3169 struct spoolss_SetPrinterData r;
3170 const char *values[] = {
3171 "spootyfoot",
3172 "spooty\\foot",
3173 #if 0
3174 /* FIXME: not working with s3 atm. */
3175 "spooty,foot",
3176 "spooty,fo,ot",
3177 #endif
3178 "spooty foot",
3179 #if 0
3180 /* FIXME: not working with s3 atm. */
3181 "spooty\\fo,ot",
3182 "spooty,fo\\ot"
3183 #endif
3185 int i;
3187 for (i=0; i < ARRAY_SIZE(values); i++) {
3189 enum winreg_Type type;
3190 uint8_t *data;
3191 DATA_BLOB blob;
3192 uint32_t needed;
3194 torture_assert(tctx,
3195 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3196 "REG_SZ", "dog", &r.in.type, &blob), "");
3198 r.in.handle = handle;
3199 r.in.value_name = values[i];
3200 r.in.data = blob.data;
3201 r.in.offered = blob.length;
3203 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3204 r.in.value_name);
3206 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
3208 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
3209 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
3211 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data, &needed)) {
3212 return false;
3215 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
3216 torture_assert_int_equal(tctx, r.in.offered, needed, "size mismatch");
3217 torture_assert_mem_equal(tctx, blob.data, data, needed, "buffer mismatch");
3219 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
3220 return false;
3224 return true;
3227 static bool test_EnumPrinterKey(struct torture_context *tctx,
3228 struct dcerpc_pipe *p,
3229 struct policy_handle *handle,
3230 const char *key_name,
3231 const char ***array);
3233 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3234 struct dcerpc_pipe *p,
3235 struct policy_handle *handle,
3236 const char *key_name,
3237 const char *value_name,
3238 enum winreg_Type type,
3239 uint8_t *data,
3240 uint32_t offered)
3242 NTSTATUS status;
3243 struct spoolss_SetPrinterDataEx r;
3245 r.in.handle = handle;
3246 r.in.key_name = key_name;
3247 r.in.value_name = value_name;
3248 r.in.type = type;
3249 r.in.data = data;
3250 r.in.offered = offered;
3252 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3253 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3255 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3257 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3258 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3260 return true;
3263 #define TOP_LEVEL_PRINTER_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
3265 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3266 struct dcerpc_pipe *p,
3267 struct policy_handle *handle)
3269 struct winreg_OpenHKLM r;
3271 r.in.system_name = NULL;
3272 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3273 r.out.handle = handle;
3275 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3277 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM(p, tctx, &r), "OpenHKLM failed");
3278 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3280 return true;
3283 static void init_winreg_String(struct winreg_String *name, const char *s)
3285 name->name = s;
3286 if (s) {
3287 name->name_len = 2 * (strlen_m(s) + 1);
3288 name->name_size = name->name_len;
3289 } else {
3290 name->name_len = 0;
3291 name->name_size = 0;
3295 static bool test_winreg_OpenKey(struct torture_context *tctx,
3296 struct dcerpc_pipe *p,
3297 struct policy_handle *hive_handle,
3298 const char *keyname,
3299 struct policy_handle *key_handle)
3301 struct winreg_OpenKey r;
3303 r.in.parent_handle = hive_handle;
3304 init_winreg_String(&r.in.keyname, keyname);
3305 r.in.unknown = 0x00000000;
3306 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3307 r.out.handle = key_handle;
3309 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3311 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r), "OpenKey failed");
3312 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3314 return true;
3317 static bool test_winreg_CloseKey(struct torture_context *tctx,
3318 struct dcerpc_pipe *p,
3319 struct policy_handle *handle)
3321 struct winreg_CloseKey r;
3323 r.in.handle = handle;
3324 r.out.handle = handle;
3326 torture_comment(tctx, "Testing winreg_CloseKey\n");
3328 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), "CloseKey failed");
3329 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3331 return true;
3334 static bool test_winreg_QueryValue(struct torture_context *tctx,
3335 struct dcerpc_pipe *p,
3336 struct policy_handle *handle,
3337 const char *value_name,
3338 enum winreg_Type *type_p,
3339 uint32_t *data_size_p,
3340 uint32_t *data_length_p,
3341 uint8_t **data_p)
3343 struct winreg_QueryValue r;
3344 enum winreg_Type type = REG_NONE;
3345 uint32_t data_size = 0;
3346 uint32_t data_length = 0;
3347 struct winreg_String valuename;
3349 init_winreg_String(&valuename, value_name);
3351 r.in.handle = handle;
3352 r.in.value_name = &valuename;
3353 r.in.type = &type;
3354 r.in.data_size = &data_size;
3355 r.in.data_length = &data_length;
3356 r.out.type = &type;
3357 r.out.data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3358 r.out.data_size = &data_size;
3359 r.out.data_length = &data_length;
3361 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3363 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3364 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3365 *r.in.data_size = *r.out.data_size;
3366 r.out.data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3367 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3369 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3371 if (type_p) {
3372 *type_p = *r.out.type;
3374 if (data_size_p) {
3375 *data_size_p = *r.out.data_size;
3377 if (data_length_p) {
3378 *data_length_p = *r.out.data_length;
3380 if (data_p) {
3381 *data_p = r.out.data;
3384 return true;
3387 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3388 struct dcerpc_pipe *p,
3389 struct policy_handle *handle,
3390 const char *printername,
3391 struct dcerpc_pipe *winreg_pipe,
3392 struct policy_handle *hive_handle)
3394 const char *value_name = "dog";
3395 const char *keys[] = {
3396 "torturedataex",
3397 "torture data ex",
3398 #if 0
3399 /* FIXME: not working with s3 atm. */
3400 "torturedataex_with_subkey\\subkey",
3401 "torturedataex_with_subkey\\subkey:0",
3402 "torturedataex_with_subkey\\subkey:1",
3403 "torturedataex_with_subkey\\subkey\\subsubkey",
3404 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3405 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3406 #endif
3407 "torture,data",
3408 #if 0
3409 /* FIXME: not working with s3 atm. */
3411 "torture,data,ex",
3412 "torture,data\\ex",
3413 "torture\\data,ex"
3414 #endif
3416 enum winreg_Type types[] = {
3417 REG_SZ,
3418 REG_DWORD,
3419 REG_BINARY
3421 const char *str = "abcdefghijklmnopqrstuvwxzy";
3422 int i, t, s;
3425 for (i=0; i < ARRAY_SIZE(keys); i++) {
3426 for (t=0; t < ARRAY_SIZE(types); t++) {
3427 for (s=0; s < strlen(str); s++) {
3429 char *c;
3430 const char *key;
3431 enum winreg_Type type;
3432 const char *string = talloc_strndup(tctx, str, s);
3433 DATA_BLOB blob = data_blob_string_const(string);
3434 const char **subkeys;
3435 DATA_BLOB data;
3436 uint8_t *data_out;
3437 uint32_t needed, offered = 0;
3439 switch (types[t]) {
3440 case REG_BINARY:
3441 case REG_DWORD:
3442 data = blob;
3443 offered = blob.length;
3444 break;
3445 case REG_SZ:
3446 torture_assert(tctx,
3447 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3448 "REG_SZ", string, &type, &data), "");
3449 offered = data.length;
3450 /*strlen_m_term(data.string)*2;*/
3451 break;
3452 default:
3453 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3456 torture_assert(tctx,
3457 test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3458 "failed to call SetPrinterDataEx");
3460 if (!test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed)) {
3461 return false;
3463 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3464 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3465 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3467 if (winreg_pipe && hive_handle) {
3468 const char *printer_key;
3469 struct policy_handle key_handle;
3470 enum winreg_Type w_type;
3471 uint32_t w_size, w_length;
3472 uint8_t *w_data;
3474 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3475 TOP_LEVEL_PRINTER_KEY, printername, keys[i]);
3477 torture_assert(tctx, test_winreg_OpenKey(tctx, winreg_pipe, hive_handle, printer_key, &key_handle), "");
3479 torture_assert(tctx,
3480 test_winreg_QueryValue(tctx, winreg_pipe, &key_handle, value_name, &w_type, &w_size, &w_length, &w_data), "");
3482 test_winreg_CloseKey(tctx, winreg_pipe, &key_handle);
3484 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
3485 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
3486 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
3489 key = talloc_strdup(tctx, keys[i]);
3491 if (!test_EnumPrinterDataEx(tctx, p, handle, keys[i])) {
3492 return false;
3495 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3496 return false;
3499 c = strchr(key, '\\');
3500 if (c) {
3501 int i;
3503 /* we have subkeys */
3505 *c = 0;
3507 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3508 return false;
3511 for (i=0; subkeys && subkeys[i]; i++) {
3513 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
3515 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3516 return false;
3520 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3521 return false;
3524 } else {
3525 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3526 return false;
3533 return true;
3536 static bool test_PrinterData_winreg(struct torture_context *tctx,
3537 struct dcerpc_pipe *p,
3538 struct policy_handle *handle,
3539 const char *printer_name)
3541 struct dcerpc_pipe *p2;
3542 bool ret = true;
3543 struct policy_handle hive_handle;
3545 torture_assert_ntstatus_ok(tctx,
3546 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
3547 "could not open winreg pipe");
3549 torture_assert(tctx, test_winreg_OpenHKLM(tctx, p2, &hive_handle), "");
3551 ret = test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3553 test_winreg_CloseKey(tctx, p2, &hive_handle);
3555 talloc_free(p2);
3557 return ret;
3560 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3561 struct dcerpc_pipe *p,
3562 struct policy_handle *handle,
3563 uint32_t *change_id)
3565 enum winreg_Type type;
3566 uint8_t *data;
3567 uint32_t needed;
3569 torture_assert(tctx,
3570 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3571 "failed to call GetPrinterData");
3573 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3574 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3576 *change_id = IVAL(data, 0);
3578 return true;
3581 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3582 struct dcerpc_pipe *p,
3583 struct policy_handle *handle,
3584 uint32_t *change_id)
3586 enum winreg_Type type;
3587 uint8_t *data;
3588 uint32_t needed;
3590 torture_assert(tctx,
3591 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3592 "failed to call GetPrinterData");
3594 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3595 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3597 *change_id = IVAL(data, 0);
3599 return true;
3602 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3603 struct dcerpc_pipe *p,
3604 struct policy_handle *handle,
3605 uint32_t *change_id)
3607 union spoolss_PrinterInfo info;
3609 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3610 "failed to query Printer level 0");
3612 *change_id = info.info0.change_id;
3614 return true;
3617 static bool test_ChangeID(struct torture_context *tctx,
3618 struct dcerpc_pipe *p,
3619 struct policy_handle *handle)
3621 uint32_t change_id, change_id_ex, change_id_info;
3622 uint32_t change_id2, change_id_ex2, change_id_info2;
3623 union spoolss_PrinterInfo info;
3624 const char *comment;
3627 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3629 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3630 "failed to query for ChangeID");
3631 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3632 "failed to query for ChangeID");
3633 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3634 "failed to query for ChangeID");
3636 torture_assert_int_equal(tctx, change_id, change_id_ex,
3637 "change_ids should all be equal");
3638 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3639 "change_ids should all be equal");
3642 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3644 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3645 "failed to query for ChangeID");
3646 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3647 "failed to query Printer level 2");
3648 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3649 "failed to query for ChangeID");
3650 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3651 "failed to query for ChangeID");
3652 torture_assert_int_equal(tctx, change_id, change_id_ex,
3653 "change_id should not have changed");
3654 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3655 "change_id should not have changed");
3658 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3660 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3661 "failed to query for ChangeID");
3662 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3663 "failed to query for ChangeID");
3664 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3665 "failed to query for ChangeID");
3666 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3667 "failed to query Printer level 2");
3668 comment = talloc_strdup(tctx, info.info2.comment);
3671 struct spoolss_SetPrinterInfoCtr info_ctr;
3672 struct spoolss_DevmodeContainer devmode_ctr;
3673 struct sec_desc_buf secdesc_ctr;
3674 struct spoolss_SetPrinterInfo2 info2;
3676 ZERO_STRUCT(info_ctr);
3677 ZERO_STRUCT(devmode_ctr);
3678 ZERO_STRUCT(secdesc_ctr);
3680 info2.servername = info.info2.servername;
3681 info2.printername = info.info2.printername;
3682 info2.sharename = info.info2.sharename;
3683 info2.portname = info.info2.portname;
3684 info2.drivername = info.info2.drivername;
3685 info2.comment = "torture_comment";
3686 info2.location = info.info2.location;
3687 info2.devmode_ptr = 0;
3688 info2.sepfile = info.info2.sepfile;
3689 info2.printprocessor = info.info2.printprocessor;
3690 info2.datatype = info.info2.datatype;
3691 info2.parameters = info.info2.parameters;
3692 info2.secdesc_ptr = 0;
3693 info2.attributes = info.info2.attributes;
3694 info2.priority = info.info2.priority;
3695 info2.defaultpriority = info.info2.defaultpriority;
3696 info2.starttime = info.info2.starttime;
3697 info2.untiltime = info.info2.untiltime;
3698 info2.status = info.info2.status;
3699 info2.cjobs = info.info2.cjobs;
3700 info2.averageppm = info.info2.averageppm;
3702 info_ctr.level = 2;
3703 info_ctr.info.info2 = &info2;
3705 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3706 "failed to call SetPrinter");
3708 info2.comment = comment;
3710 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3711 "failed to call SetPrinter");
3715 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3716 "failed to query for ChangeID");
3717 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3718 "failed to query for ChangeID");
3719 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3720 "failed to query for ChangeID");
3722 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3723 "change_ids should all be equal");
3724 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3725 "change_ids should all be equal");
3727 torture_assert(tctx, (change_id < change_id2),
3728 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3729 change_id2, change_id));
3730 torture_assert(tctx, (change_id_ex < change_id_ex2),
3731 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3732 change_id_ex2, change_id_ex));
3733 torture_assert(tctx, (change_id_info < change_id_info2),
3734 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3735 change_id_info2, change_id_info));
3737 return true;
3740 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3741 struct dcerpc_pipe *p,
3742 struct policy_handle *handle)
3744 NTSTATUS status;
3745 struct dcerpc_binding *b;
3746 struct dcerpc_pipe *p2;
3747 struct spoolss_ClosePrinter cp;
3749 /* only makes sense on SMB */
3750 if (p->conn->transport.transport != NCACN_NP) {
3751 return true;
3754 torture_comment(tctx, "testing close on secondary pipe\n");
3756 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3757 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3759 status = dcerpc_secondary_connection(p, &p2, b);
3760 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3762 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3763 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3765 cp.in.handle = handle;
3766 cp.out.handle = handle;
3768 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3769 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3770 "ERROR: Allowed close on secondary connection");
3772 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3773 "Unexpected fault code");
3775 talloc_free(p2);
3777 return true;
3780 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3781 struct dcerpc_pipe *p, const char *name)
3783 NTSTATUS status;
3784 struct spoolss_OpenPrinter op;
3785 struct spoolss_OpenPrinterEx opEx;
3786 struct policy_handle handle;
3787 bool ret = true;
3789 op.in.printername = name;
3790 op.in.datatype = NULL;
3791 op.in.devmode_ctr.devmode= NULL;
3792 op.in.access_mask = 0;
3793 op.out.handle = &handle;
3795 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
3797 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
3798 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3799 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
3800 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
3801 name, win_errstr(op.out.result));
3804 if (W_ERROR_IS_OK(op.out.result)) {
3805 ret &=test_ClosePrinter(tctx, p, &handle);
3808 opEx.in.printername = name;
3809 opEx.in.datatype = NULL;
3810 opEx.in.devmode_ctr.devmode = NULL;
3811 opEx.in.access_mask = 0;
3812 opEx.in.level = 1;
3813 opEx.in.userlevel.level1 = NULL;
3814 opEx.out.handle = &handle;
3816 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
3818 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
3819 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3820 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
3821 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
3822 name, win_errstr(opEx.out.result));
3825 if (W_ERROR_IS_OK(opEx.out.result)) {
3826 ret &=test_ClosePrinter(tctx, p, &handle);
3829 return ret;
3832 static bool test_OpenPrinter(struct torture_context *tctx,
3833 struct dcerpc_pipe *p,
3834 const char *name,
3835 const char *environment)
3837 NTSTATUS status;
3838 struct spoolss_OpenPrinter r;
3839 struct policy_handle handle;
3840 bool ret = true;
3842 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
3843 r.in.datatype = NULL;
3844 r.in.devmode_ctr.devmode= NULL;
3845 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3846 r.out.handle = &handle;
3848 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
3850 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
3852 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3854 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
3856 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3857 ret = false;
3860 if (!torture_setting_bool(tctx, "samba3", false)) {
3861 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3862 ret = false;
3866 if (!test_ClosePrinter(tctx, p, &handle)) {
3867 ret = false;
3870 return ret;
3873 static bool call_OpenPrinterEx(struct torture_context *tctx,
3874 struct dcerpc_pipe *p,
3875 const char *name,
3876 struct spoolss_DeviceMode *devmode,
3877 struct policy_handle *handle)
3879 struct spoolss_OpenPrinterEx r;
3880 struct spoolss_UserLevel1 userlevel1;
3881 NTSTATUS status;
3883 if (name && name[0]) {
3884 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
3885 dcerpc_server_name(p), name);
3886 } else {
3887 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
3888 dcerpc_server_name(p));
3891 r.in.datatype = NULL;
3892 r.in.devmode_ctr.devmode= devmode;
3893 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3894 r.in.level = 1;
3895 r.in.userlevel.level1 = &userlevel1;
3896 r.out.handle = handle;
3898 userlevel1.size = 1234;
3899 userlevel1.client = "hello";
3900 userlevel1.user = "spottyfoot!";
3901 userlevel1.build = 1;
3902 userlevel1.major = 2;
3903 userlevel1.minor = 3;
3904 userlevel1.processor = 4;
3906 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3908 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3910 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3912 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3914 return true;
3917 static bool test_OpenPrinterEx(struct torture_context *tctx,
3918 struct dcerpc_pipe *p,
3919 const char *name,
3920 const char *environment)
3922 struct policy_handle handle;
3923 bool ret = true;
3925 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
3926 return false;
3929 if (!test_PrinterInfo_SD(tctx, p, &handle)) {
3930 ret = false;
3933 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3934 ret = false;
3937 if (!test_EnumForms(tctx, p, &handle, false)) {
3938 ret = false;
3941 if (!test_AddForm(tctx, p, &handle, false)) {
3942 ret = false;
3945 if (!test_EnumPrinterData(tctx, p, &handle)) {
3946 ret = false;
3949 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
3950 ret = false;
3953 if (!test_printer_keys(tctx, p, &handle)) {
3954 ret = false;
3957 if (!test_PausePrinter(tctx, p, &handle)) {
3958 ret = false;
3961 if (!test_DoPrintTest(tctx, p, &handle)) {
3962 ret = false;
3965 if (!test_ResumePrinter(tctx, p, &handle)) {
3966 ret = false;
3969 if (!test_SetPrinterData(tctx, p, &handle)) {
3970 ret = false;
3973 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
3974 ret = false;
3977 if (!torture_setting_bool(tctx, "samba3", false)) {
3978 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3979 ret = false;
3983 if (!test_ClosePrinter(tctx, p, &handle)) {
3984 ret = false;
3987 return ret;
3990 static bool test_EnumPrinters_old(struct torture_context *tctx,
3991 struct dcerpc_pipe *p,
3992 const char *environment)
3994 struct spoolss_EnumPrinters r;
3995 NTSTATUS status;
3996 uint16_t levels[] = {1, 2, 4, 5};
3997 int i;
3998 bool ret = true;
4000 for (i=0;i<ARRAY_SIZE(levels);i++) {
4001 union spoolss_PrinterInfo *info;
4002 int j;
4003 uint32_t needed;
4004 uint32_t count;
4006 r.in.flags = PRINTER_ENUM_LOCAL;
4007 r.in.server = "";
4008 r.in.level = levels[i];
4009 r.in.buffer = NULL;
4010 r.in.offered = 0;
4011 r.out.needed = &needed;
4012 r.out.count = &count;
4013 r.out.info = &info;
4015 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4017 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4018 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4020 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4021 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4022 data_blob_clear(&blob);
4023 r.in.buffer = &blob;
4024 r.in.offered = needed;
4025 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4028 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4030 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4032 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4034 if (!info) {
4035 torture_comment(tctx, "No printers returned\n");
4036 return true;
4039 for (j=0;j<count;j++) {
4040 if (r.in.level == 1) {
4041 char *unc = talloc_strdup(tctx, info[j].info1.name);
4042 char *slash, *name;
4043 name = unc;
4044 if (unc[0] == '\\' && unc[1] == '\\') {
4045 unc +=2;
4047 slash = strchr(unc, '\\');
4048 if (slash) {
4049 slash++;
4050 name = slash;
4052 if (!test_OpenPrinter(tctx, p, name, environment)) {
4053 ret = false;
4055 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4056 ret = false;
4062 return ret;
4065 static bool test_GetPrinterDriver(struct torture_context *tctx,
4066 struct dcerpc_pipe *p,
4067 struct policy_handle *handle,
4068 const char *driver_name)
4070 struct spoolss_GetPrinterDriver r;
4071 uint32_t needed;
4073 r.in.handle = handle;
4074 r.in.architecture = "W32X86";
4075 r.in.level = 1;
4076 r.in.buffer = NULL;
4077 r.in.offered = 0;
4078 r.out.needed = &needed;
4080 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4082 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4083 "failed to call GetPrinterDriver");
4084 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4085 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4086 data_blob_clear(&blob);
4087 r.in.buffer = &blob;
4088 r.in.offered = needed;
4089 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4090 "failed to call GetPrinterDriver");
4093 torture_assert_werr_ok(tctx, r.out.result,
4094 "failed to call GetPrinterDriver");
4096 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4098 return true;
4101 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4102 struct dcerpc_pipe *p,
4103 struct policy_handle *handle,
4104 const char *driver_name,
4105 const char *architecture)
4107 struct spoolss_GetPrinterDriver2 r;
4108 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4109 uint32_t needed;
4110 uint32_t server_major_version;
4111 uint32_t server_minor_version;
4112 int i;
4114 r.in.handle = handle;
4115 r.in.architecture = architecture;
4116 r.in.client_major_version = 3;
4117 r.in.client_minor_version = 0;
4118 r.out.needed = &needed;
4119 r.out.server_major_version = &server_major_version;
4120 r.out.server_minor_version = &server_minor_version;
4122 for (i=0;i<ARRAY_SIZE(levels);i++) {
4124 r.in.buffer = NULL;
4125 r.in.offered = 0;
4126 r.in.level = levels[i];
4128 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4129 driver_name, r.in.level);
4131 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4132 "failed to call GetPrinterDriver2");
4133 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4134 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4135 data_blob_clear(&blob);
4136 r.in.buffer = &blob;
4137 r.in.offered = needed;
4138 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4139 "failed to call GetPrinterDriver2");
4142 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4143 switch (r.in.level) {
4144 case 101:
4145 case 8:
4146 continue;
4147 default:
4148 break;
4152 torture_assert_werr_ok(tctx, r.out.result,
4153 "failed to call GetPrinterDriver2");
4155 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4158 return true;
4161 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4162 struct dcerpc_pipe *p,
4163 const char *environment)
4165 struct spoolss_EnumPrinterDrivers r;
4166 NTSTATUS status;
4167 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4168 int i;
4170 for (i=0;i<ARRAY_SIZE(levels);i++) {
4172 uint32_t needed;
4173 uint32_t count;
4174 union spoolss_DriverInfo *info;
4176 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4177 r.in.environment = environment;
4178 r.in.level = levels[i];
4179 r.in.buffer = NULL;
4180 r.in.offered = 0;
4181 r.out.needed = &needed;
4182 r.out.count = &count;
4183 r.out.info = &info;
4185 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4187 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4189 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4191 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4192 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4193 data_blob_clear(&blob);
4194 r.in.buffer = &blob;
4195 r.in.offered = needed;
4196 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4199 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4201 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4203 if (!info) {
4204 torture_comment(tctx, "No printer drivers returned\n");
4205 break;
4208 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4211 return true;
4214 static bool test_DeletePrinter(struct torture_context *tctx,
4215 struct dcerpc_pipe *p,
4216 struct policy_handle *handle)
4218 struct spoolss_DeletePrinter r;
4220 torture_comment(tctx, "Testing DeletePrinter\n");
4222 r.in.handle = handle;
4224 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4225 "failed to delete printer");
4226 torture_assert_werr_ok(tctx, r.out.result,
4227 "failed to delete printer");
4229 return true;
4232 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4233 struct dcerpc_pipe *p,
4234 uint32_t flags,
4235 uint32_t level,
4236 const char *name,
4237 bool *found)
4239 struct spoolss_EnumPrinters e;
4240 uint32_t count;
4241 union spoolss_PrinterInfo *info;
4242 uint32_t needed;
4243 int i;
4245 *found = false;
4247 e.in.flags = flags;
4248 e.in.server = NULL;
4249 e.in.level = level;
4250 e.in.buffer = NULL;
4251 e.in.offered = 0;
4252 e.out.count = &count;
4253 e.out.info = &info;
4254 e.out.needed = &needed;
4256 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4257 "failed to enum printers");
4259 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4260 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4261 data_blob_clear(&blob);
4262 e.in.buffer = &blob;
4263 e.in.offered = needed;
4265 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4266 "failed to enum printers");
4269 torture_assert_werr_ok(tctx, e.out.result,
4270 "failed to enum printers");
4272 for (i=0; i < count; i++) {
4274 const char *current = NULL;
4275 const char *p;
4277 switch (level) {
4278 case 1:
4279 current = info[i].info1.name;
4280 break;
4283 if (strequal(current, name)) {
4284 *found = true;
4285 break;
4288 p = strrchr(current, '\\');
4289 if (p) {
4290 if (!e.in.server) {
4291 torture_warning(tctx,
4292 "server returns printername %s incl. servername although we did not set servername", current);
4294 p++;
4295 if (strequal(p, name)) {
4296 *found = true;
4297 break;
4302 return true;
4305 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4306 struct dcerpc_pipe *p,
4307 const char *printername,
4308 bool ex)
4310 WERROR result;
4311 struct spoolss_AddPrinter r;
4312 struct spoolss_AddPrinterEx rex;
4313 struct spoolss_SetPrinterInfoCtr info_ctr;
4314 struct spoolss_SetPrinterInfo1 info1;
4315 struct spoolss_DevmodeContainer devmode_ctr;
4316 struct sec_desc_buf secdesc_ctr;
4317 struct spoolss_UserLevelCtr userlevel_ctr;
4318 struct policy_handle handle;
4319 bool found = false;
4321 ZERO_STRUCT(devmode_ctr);
4322 ZERO_STRUCT(secdesc_ctr);
4323 ZERO_STRUCT(userlevel_ctr);
4324 ZERO_STRUCT(info1);
4326 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4328 /* try to add printer to wellknown printer list (level 1) */
4330 userlevel_ctr.level = 1;
4332 info_ctr.info.info1 = &info1;
4333 info_ctr.level = 1;
4335 rex.in.server = NULL;
4336 rex.in.info_ctr = &info_ctr;
4337 rex.in.devmode_ctr = &devmode_ctr;
4338 rex.in.secdesc_ctr = &secdesc_ctr;
4339 rex.in.userlevel_ctr = &userlevel_ctr;
4340 rex.out.handle = &handle;
4342 r.in.server = NULL;
4343 r.in.info_ctr = &info_ctr;
4344 r.in.devmode_ctr = &devmode_ctr;
4345 r.in.secdesc_ctr = &secdesc_ctr;
4346 r.out.handle = &handle;
4348 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4349 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4350 "failed to add printer");
4351 result = ex ? rex.out.result : r.out.result;
4352 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4353 "unexpected result code");
4355 info1.name = printername;
4356 info1.flags = PRINTER_ATTRIBUTE_SHARED;
4358 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4359 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4360 "failed to add printer");
4361 result = ex ? rex.out.result : r.out.result;
4362 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4363 "unexpected result code");
4365 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4366 better do a real check to see the printer is really there */
4368 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4369 PRINTER_ENUM_NETWORK, 1,
4370 printername,
4371 &found),
4372 "failed to enum printers");
4374 torture_assert(tctx, found, "failed to find newly added printer");
4376 info1.flags = 0;
4378 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4379 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4380 "failed to add printer");
4381 result = ex ? rex.out.result : r.out.result;
4382 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4383 "unexpected result code");
4385 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4386 better do a real check to see the printer has really been removed
4387 from the well known printer list */
4389 found = false;
4391 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4392 PRINTER_ENUM_NETWORK, 1,
4393 printername,
4394 &found),
4395 "failed to enum printers");
4396 #if 0
4397 torture_assert(tctx, !found, "printer still in well known printer list");
4398 #endif
4399 return true;
4402 static bool test_AddPrinter_normal(struct torture_context *tctx,
4403 struct dcerpc_pipe *p,
4404 struct policy_handle *handle_p,
4405 const char *printername,
4406 const char *drivername,
4407 const char *portname,
4408 bool ex)
4410 WERROR result;
4411 struct spoolss_AddPrinter r;
4412 struct spoolss_AddPrinterEx rex;
4413 struct spoolss_SetPrinterInfoCtr info_ctr;
4414 struct spoolss_SetPrinterInfo2 info2;
4415 struct spoolss_DevmodeContainer devmode_ctr;
4416 struct sec_desc_buf secdesc_ctr;
4417 struct spoolss_UserLevelCtr userlevel_ctr;
4418 struct policy_handle handle;
4419 bool found = false;
4420 bool existing_printer_deleted = false;
4422 ZERO_STRUCT(devmode_ctr);
4423 ZERO_STRUCT(secdesc_ctr);
4424 ZERO_STRUCT(userlevel_ctr);
4426 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4428 userlevel_ctr.level = 1;
4430 rex.in.server = NULL;
4431 rex.in.info_ctr = &info_ctr;
4432 rex.in.devmode_ctr = &devmode_ctr;
4433 rex.in.secdesc_ctr = &secdesc_ctr;
4434 rex.in.userlevel_ctr = &userlevel_ctr;
4435 rex.out.handle = &handle;
4437 r.in.server = NULL;
4438 r.in.info_ctr = &info_ctr;
4439 r.in.devmode_ctr = &devmode_ctr;
4440 r.in.secdesc_ctr = &secdesc_ctr;
4441 r.out.handle = &handle;
4443 again:
4445 /* try to add printer to printer list (level 2) */
4447 ZERO_STRUCT(info2);
4449 info_ctr.info.info2 = &info2;
4450 info_ctr.level = 2;
4452 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4453 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4454 "failed to add printer");
4455 result = ex ? rex.out.result : r.out.result;
4456 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4457 "unexpected result code");
4459 info2.printername = printername;
4461 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4462 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4463 "failed to add printer");
4464 result = ex ? rex.out.result : r.out.result;
4466 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4467 struct policy_handle printer_handle;
4469 if (existing_printer_deleted) {
4470 torture_fail(tctx, "already deleted printer still existing?");
4473 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4474 "failed to open printer handle");
4476 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4477 "failed to delete printer");
4479 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4480 "failed to close server handle");
4482 existing_printer_deleted = true;
4484 goto again;
4487 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4488 "unexpected result code");
4490 info2.portname = portname;
4492 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4493 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4494 "failed to add printer");
4495 result = ex ? rex.out.result : r.out.result;
4496 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4497 "unexpected result code");
4499 info2.drivername = drivername;
4501 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4502 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4503 "failed to add printer");
4504 result = ex ? rex.out.result : r.out.result;
4506 /* w2k8r2 allows to add printer w/o defining printprocessor */
4508 if (!W_ERROR_IS_OK(result)) {
4509 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4510 "unexpected result code");
4512 info2.printprocessor = "winprint";
4514 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4515 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4516 "failed to add printer");
4517 result = ex ? rex.out.result : r.out.result;
4518 torture_assert_werr_ok(tctx, result,
4519 "failed to add printer");
4522 *handle_p = handle;
4524 /* we are paranoid, really check if the printer is there now */
4526 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4527 PRINTER_ENUM_LOCAL, 1,
4528 printername,
4529 &found),
4530 "failed to enum printers");
4531 torture_assert(tctx, found, "failed to find newly added printer");
4533 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4534 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4535 "failed to add printer");
4536 result = ex ? rex.out.result : r.out.result;
4537 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4538 "unexpected result code");
4540 return true;
4543 static bool test_AddPrinterEx(struct torture_context *tctx,
4544 struct dcerpc_pipe *p,
4545 struct policy_handle *handle_p,
4546 const char *printername,
4547 const char *drivername,
4548 const char *portname)
4550 bool ret = true;
4552 if (!torture_setting_bool(tctx, "samba3", false)) {
4553 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4554 torture_comment(tctx, "failed to add printer to well known list\n");
4555 ret = false;
4559 if (!test_AddPrinter_normal(tctx, p, handle_p,
4560 printername, drivername, portname,
4561 true)) {
4562 torture_comment(tctx, "failed to add printer to printer list\n");
4563 ret = false;
4566 return ret;
4569 static bool test_AddPrinter(struct torture_context *tctx,
4570 struct dcerpc_pipe *p,
4571 struct policy_handle *handle_p,
4572 const char *printername,
4573 const char *drivername,
4574 const char *portname)
4576 bool ret = true;
4578 if (!torture_setting_bool(tctx, "samba3", false)) {
4579 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4580 torture_comment(tctx, "failed to add printer to well known list\n");
4581 ret = false;
4585 if (!test_AddPrinter_normal(tctx, p, handle_p,
4586 printername, drivername, portname,
4587 false)) {
4588 torture_comment(tctx, "failed to add printer to printer list\n");
4589 ret = false;
4592 return ret;
4595 static bool test_printer_info(struct torture_context *tctx,
4596 struct dcerpc_pipe *p,
4597 struct policy_handle *handle)
4599 bool ret = true;
4601 if (torture_setting_bool(tctx, "samba3", false)) {
4602 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4605 if (!test_PrinterInfo(tctx, p, handle)) {
4606 ret = false;
4609 if (!test_SetPrinter_errors(tctx, p, handle)) {
4610 ret = false;
4613 return ret;
4616 static bool test_EnumPrinterKey(struct torture_context *tctx,
4617 struct dcerpc_pipe *p,
4618 struct policy_handle *handle,
4619 const char *key_name,
4620 const char ***array)
4622 struct spoolss_EnumPrinterKey r;
4623 uint32_t needed = 0;
4624 union spoolss_KeyNames key_buffer;
4625 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4626 uint32_t _ndr_size;
4627 int i;
4629 r.in.handle = handle;
4630 r.in.key_name = key_name;
4631 r.out.key_buffer = &key_buffer;
4632 r.out.needed = &needed;
4633 r.out._ndr_size = &_ndr_size;
4635 for (i=0; i < ARRAY_SIZE(offered); i++) {
4637 if (offered[i] < 0 && needed) {
4638 if (needed <= 4) {
4639 continue;
4641 r.in.offered = needed + offered[i];
4642 } else {
4643 r.in.offered = offered[i];
4646 ZERO_STRUCT(key_buffer);
4648 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4650 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4651 "failed to call EnumPrinterKey");
4652 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4654 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4655 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4656 _ndr_size, r.in.offered/2));
4658 r.in.offered = needed;
4659 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4660 "failed to call EnumPrinterKey");
4663 if (offered[i] > 0) {
4664 torture_assert_werr_ok(tctx, r.out.result,
4665 "failed to call EnumPrinterKey");
4668 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4669 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4670 _ndr_size, r.in.offered/2));
4672 torture_assert(tctx, (*r.out.needed <= r.in.offered),
4673 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
4675 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
4676 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
4678 if (key_buffer.string_array) {
4679 uint32_t calc_needed = 0;
4680 int s;
4681 for (s=0; key_buffer.string_array[s]; s++) {
4682 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
4684 if (!key_buffer.string_array[0]) {
4685 calc_needed += 2;
4687 calc_needed += 2;
4689 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
4690 "EnumPrinterKey unexpected size");
4694 if (array) {
4695 *array = key_buffer.string_array;
4698 return true;
4701 bool test_printer_keys(struct torture_context *tctx,
4702 struct dcerpc_pipe *p,
4703 struct policy_handle *handle)
4705 const char **key_array = NULL;
4706 int i;
4708 torture_comment(tctx, "\nTesting Printer Keys\n");
4710 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4711 "failed to call test_EnumPrinterKey");
4713 for (i=0; key_array && key_array[i]; i++) {
4714 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4715 "failed to call test_EnumPrinterKey");
4717 for (i=0; key_array && key_array[i]; i++) {
4718 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
4719 "failed to call test_EnumPrinterDataEx");
4722 return true;
4725 static bool test_one_printer(struct torture_context *tctx,
4726 struct dcerpc_pipe *p,
4727 struct policy_handle *handle,
4728 const char *name)
4730 bool ret = true;
4732 if (!test_printer_info(tctx, p, handle)) {
4733 ret = false;
4736 if (!test_PrinterInfo_SD(tctx, p, handle)) {
4737 ret = false;
4740 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
4741 ret = false;
4744 if (!test_ChangeID(tctx, p, handle)) {
4745 ret = false;
4748 if (!test_printer_keys(tctx, p, handle)) {
4749 ret = false;
4752 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
4753 ret = false;
4756 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
4757 ret = false;
4760 return ret;
4763 static bool test_printer(struct torture_context *tctx,
4764 struct dcerpc_pipe *p)
4766 bool ret = true;
4767 struct policy_handle handle[2];
4768 bool found = false;
4769 const char *drivername = "Microsoft XPS Document Writer";
4770 const char *portname = "LPT1:";
4772 /* test printer created via AddPrinter */
4774 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
4775 return false;
4778 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
4779 ret = false;
4782 if (!test_DeletePrinter(tctx, p, &handle[0])) {
4783 ret = false;
4786 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4787 TORTURE_PRINTER, &found)) {
4788 ret = false;
4791 torture_assert(tctx, !found, "deleted printer still there");
4793 /* test printer created via AddPrinterEx */
4795 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
4796 return false;
4799 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
4800 ret = false;
4803 if (!test_DeletePrinter(tctx, p, &handle[1])) {
4804 ret = false;
4807 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4808 TORTURE_PRINTER_EX, &found)) {
4809 ret = false;
4812 torture_assert(tctx, !found, "deleted printer still there");
4814 return ret;
4817 static bool test_architecture_buffer(struct torture_context *tctx,
4818 struct dcerpc_pipe *p)
4820 struct spoolss_OpenPrinterEx r;
4821 struct spoolss_UserLevel1 u1;
4822 struct policy_handle handle;
4823 uint32_t architectures[] = {
4824 PROCESSOR_ARCHITECTURE_INTEL,
4825 PROCESSOR_ARCHITECTURE_IA64,
4826 PROCESSOR_ARCHITECTURE_AMD64
4828 uint32_t needed[3];
4829 int i;
4831 for (i=0; i < ARRAY_SIZE(architectures); i++) {
4833 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
4835 u1.size = 0;
4836 u1.client = NULL;
4837 u1.user = NULL;
4838 u1.build = 0;
4839 u1.major = 3;
4840 u1.minor = 0;
4841 u1.processor = architectures[i];
4843 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4844 r.in.datatype = NULL;
4845 r.in.devmode_ctr.devmode= NULL;
4846 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4847 r.in.level = 1;
4848 r.in.userlevel.level1 = &u1;
4849 r.out.handle = &handle;
4851 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
4852 torture_assert_werr_ok(tctx, r.out.result, "");
4855 struct spoolss_EnumPrinters e;
4856 uint32_t count;
4857 union spoolss_PrinterInfo *info;
4859 e.in.flags = PRINTER_ENUM_LOCAL;
4860 e.in.server = NULL;
4861 e.in.level = 2;
4862 e.in.buffer = NULL;
4863 e.in.offered = 0;
4864 e.out.count = &count;
4865 e.out.info = &info;
4866 e.out.needed = &needed[i];
4868 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
4869 #if 0
4870 torture_comment(tctx, "needed was %d\n", needed[i]);
4871 #endif
4874 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
4877 for (i=1; i < ARRAY_SIZE(architectures); i++) {
4878 if (needed[i-1] != needed[i]) {
4879 torture_fail(tctx,
4880 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
4881 needed[i-1], architectures[i-1], needed[i], architectures[i]));
4885 return true;
4888 bool torture_rpc_spoolss(struct torture_context *torture)
4890 NTSTATUS status;
4891 struct dcerpc_pipe *p;
4892 bool ret = true;
4893 struct test_spoolss_context *ctx;
4894 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
4896 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
4897 if (!NT_STATUS_IS_OK(status)) {
4898 return false;
4901 ctx = talloc_zero(torture, struct test_spoolss_context);
4903 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
4904 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
4905 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
4906 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
4907 ret &= test_EnumPorts(torture, p, ctx);
4908 ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
4909 ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
4910 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
4911 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
4912 ret &= test_EnumMonitors(torture, p, ctx);
4913 ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
4914 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
4915 ret &= test_EnumPrinters(torture, p, ctx);
4916 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
4917 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
4918 ret &= test_OpenPrinter_badname(torture, p, "");
4919 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
4920 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
4921 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
4922 ret &= test_OpenPrinter_badname(torture, p,
4923 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
4926 ret &= test_AddPort(torture, p);
4927 ret &= test_EnumPorts_old(torture, p);
4928 ret &= test_EnumPrinters_old(torture, p, environment);
4929 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
4930 ret &= test_architecture_buffer(torture, p);
4932 return ret;
4935 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
4937 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
4939 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
4940 "printer", &ndr_table_spoolss);
4942 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
4944 return suite;