s4-smbtorture: avoid passing down a full test_spoolss_context to directory
[Samba/ekacnet.git] / source4 / torture / rpc / spoolss.c
blob05ee57268c18d972b2f87530967e1c92d0fcb29c
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 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
42 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
43 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
44 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
46 struct test_spoolss_context {
47 /* print server handle */
48 struct policy_handle server_handle;
50 /* for EnumPorts */
51 uint32_t port_count[3];
52 union spoolss_PortInfo *ports[3];
54 /* for EnumPrinterDrivers */
55 uint32_t driver_count[8];
56 union spoolss_DriverInfo *drivers[8];
58 /* for EnumMonitors */
59 uint32_t monitor_count[3];
60 union spoolss_MonitorInfo *monitors[3];
62 /* for EnumPrintProcessors */
63 uint32_t print_processor_count[2];
64 union spoolss_PrintProcessorInfo *print_processors[2];
66 /* for EnumPrinters */
67 uint32_t printer_count[6];
68 union spoolss_PrinterInfo *printers[6];
71 #define COMPARE_STRING(tctx, c,r,e) \
72 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
74 /* not every compiler supports __typeof__() */
75 #if (__GNUC__ >= 3)
76 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
77 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
78 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
80 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
81 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
83 } while(0)
84 #else
85 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
86 #endif
88 #define COMPARE_UINT32(tctx, c, r, e) do {\
89 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
90 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
91 } while(0)
93 #define COMPARE_UINT64(tctx, c, r, e) do {\
94 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
95 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
96 } while(0)
99 #define COMPARE_NTTIME(tctx, c, r, e) do {\
100 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
101 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
102 } while(0)
104 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
105 int __i; \
106 if (!c.e && !r.e) { \
107 break; \
109 if (c.e && !r.e) { \
110 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
112 if (!c.e && r.e) { \
113 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
115 for (__i=0;c.e[__i] != NULL; __i++) { \
116 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
118 } while(0)
120 #define CHECK_ALIGN(size, n) do {\
121 if (size % n) {\
122 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
123 size, n, size + n - (size % n));\
125 } while(0)
127 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
129 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
130 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
131 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
132 uint32_t round_size = DO_ROUND(size, align);\
133 if (round_size != needed) {\
134 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
135 CHECK_ALIGN(size, align);\
138 } while(0)
140 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
141 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
142 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
143 uint32_t round_size = DO_ROUND(size, align);\
144 if (round_size != needed) {\
145 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
146 CHECK_ALIGN(size, align);\
149 } while(0)
151 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
152 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
153 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
154 uint32_t round_size = DO_ROUND(size, align);\
155 if (round_size != needed) {\
156 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
157 CHECK_ALIGN(size, align);\
160 } while(0)
162 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
163 const union spoolss_PrinterInfo *i,
164 uint32_t level,
165 union spoolss_SetPrinterInfo *s)
167 switch (level) {
168 case 0:
169 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
170 break;
171 case 2:
172 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
173 s->info2->servername = i->info2.servername;
174 s->info2->printername = i->info2.printername;
175 s->info2->sharename = i->info2.sharename;
176 s->info2->portname = i->info2.portname;
177 s->info2->drivername = i->info2.drivername;
178 s->info2->comment = i->info2.comment;
179 s->info2->location = i->info2.location;
180 s->info2->devmode_ptr = 0;
181 s->info2->sepfile = i->info2.sepfile;
182 s->info2->printprocessor = i->info2.printprocessor;
183 s->info2->datatype = i->info2.datatype;
184 s->info2->parameters = i->info2.parameters;
185 s->info2->secdesc_ptr = 0;
186 s->info2->attributes = i->info2.attributes;
187 s->info2->priority = i->info2.priority;
188 s->info2->defaultpriority = i->info2.defaultpriority;
189 s->info2->starttime = i->info2.starttime;
190 s->info2->untiltime = i->info2.untiltime;
191 s->info2->status = i->info2.status;
192 s->info2->cjobs = i->info2.cjobs;
193 s->info2->averageppm = i->info2.averageppm;
194 break;
195 case 3:
196 case 4:
197 case 5:
198 case 6:
199 case 7:
200 case 8:
201 case 9:
202 default:
203 return false;
206 return true;
209 static bool test_OpenPrinter_server(struct torture_context *tctx,
210 struct dcerpc_pipe *p,
211 struct policy_handle *server_handle)
213 NTSTATUS status;
214 struct spoolss_OpenPrinter op;
215 struct dcerpc_binding_handle *b = p->binding_handle;
217 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
218 op.in.datatype = NULL;
219 op.in.devmode_ctr.devmode= NULL;
220 op.in.access_mask = 0;
221 op.out.handle = server_handle;
223 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
225 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
226 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
227 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
229 return true;
232 static bool test_EnumPorts(struct torture_context *tctx,
233 struct dcerpc_binding_handle *b,
234 struct test_spoolss_context *ctx)
236 NTSTATUS status;
237 struct spoolss_EnumPorts r;
238 uint16_t levels[] = { 1, 2 };
239 int i, j;
241 for (i=0;i<ARRAY_SIZE(levels);i++) {
242 int level = levels[i];
243 DATA_BLOB blob;
244 uint32_t needed;
245 uint32_t count;
246 union spoolss_PortInfo *info;
248 r.in.servername = "";
249 r.in.level = level;
250 r.in.buffer = NULL;
251 r.in.offered = 0;
252 r.out.needed = &needed;
253 r.out.count = &count;
254 r.out.info = &info;
256 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
258 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
259 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
260 if (W_ERROR_IS_OK(r.out.result)) {
261 /* TODO: do some more checks here */
262 continue;
264 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
265 "EnumPorts unexpected return code");
267 blob = data_blob_talloc(ctx, NULL, needed);
268 data_blob_clear(&blob);
269 r.in.buffer = &blob;
270 r.in.offered = needed;
272 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
273 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
275 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
277 torture_assert(tctx, info, "EnumPorts returned no info");
279 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
281 ctx->port_count[level] = count;
282 ctx->ports[level] = info;
285 for (i=1;i<ARRAY_SIZE(levels);i++) {
286 int level = levels[i];
287 int old_level = levels[i-1];
288 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
289 "EnumPorts invalid value");
291 /* if the array sizes are not the same we would maybe segfault in the following code */
293 for (i=0;i<ARRAY_SIZE(levels);i++) {
294 int level = levels[i];
295 for (j=0;j<ctx->port_count[level];j++) {
296 union spoolss_PortInfo *cur = &ctx->ports[level][j];
297 union spoolss_PortInfo *ref = &ctx->ports[2][j];
298 switch (level) {
299 case 1:
300 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
301 break;
302 case 2:
303 /* level 2 is our reference, and it makes no sense to compare it to itself */
304 break;
309 return true;
312 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
313 struct dcerpc_pipe *p,
314 const char *environment)
316 NTSTATUS status;
317 struct dcerpc_binding_handle *b = p->binding_handle;
318 struct spoolss_GetPrintProcessorDirectory r;
319 struct {
320 uint16_t level;
321 const char *server;
322 } levels[] = {{
323 .level = 1,
324 .server = NULL
326 .level = 1,
327 .server = ""
329 .level = 78,
330 .server = ""
332 .level = 1,
333 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
335 .level = 1024,
336 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
339 int i;
340 uint32_t needed;
342 for (i=0;i<ARRAY_SIZE(levels);i++) {
343 int level = levels[i].level;
344 DATA_BLOB blob;
346 r.in.server = levels[i].server;
347 r.in.environment = environment;
348 r.in.level = level;
349 r.in.buffer = NULL;
350 r.in.offered = 0;
351 r.out.needed = &needed;
353 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
355 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
356 torture_assert_ntstatus_ok(tctx, status,
357 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
358 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
359 "GetPrintProcessorDirectory unexpected return code");
361 blob = data_blob_talloc(tctx, NULL, needed);
362 data_blob_clear(&blob);
363 r.in.buffer = &blob;
364 r.in.offered = needed;
366 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
367 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
369 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
371 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
374 return true;
378 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
379 struct dcerpc_pipe *p,
380 const char *environment)
382 NTSTATUS status;
383 struct dcerpc_binding_handle *b = p->binding_handle;
384 struct spoolss_GetPrinterDriverDirectory r;
385 struct {
386 uint16_t level;
387 const char *server;
388 } levels[] = {{
389 .level = 1,
390 .server = NULL
392 .level = 1,
393 .server = ""
395 .level = 78,
396 .server = ""
398 .level = 1,
399 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
401 .level = 1024,
402 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
405 int i;
406 uint32_t needed;
408 for (i=0;i<ARRAY_SIZE(levels);i++) {
409 int level = levels[i].level;
410 DATA_BLOB blob;
412 r.in.server = levels[i].server;
413 r.in.environment = environment;
414 r.in.level = level;
415 r.in.buffer = NULL;
416 r.in.offered = 0;
417 r.out.needed = &needed;
419 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
421 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
422 torture_assert_ntstatus_ok(tctx, status,
423 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
424 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
425 "GetPrinterDriverDirectory unexpected return code");
427 blob = data_blob_talloc(tctx, NULL, needed);
428 data_blob_clear(&blob);
429 r.in.buffer = &blob;
430 r.in.offered = needed;
432 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
433 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
435 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
437 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
440 return true;
443 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
444 struct dcerpc_pipe *p,
445 struct test_spoolss_context *ctx,
446 const char *architecture)
448 NTSTATUS status;
449 struct dcerpc_binding_handle *b = p->binding_handle;
450 struct spoolss_EnumPrinterDrivers r;
451 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
452 int i, j;
454 for (i=0;i<ARRAY_SIZE(levels);i++) {
455 int level = levels[i];
456 DATA_BLOB blob;
457 uint32_t needed;
458 uint32_t count;
459 union spoolss_DriverInfo *info;
461 /* FIXME: gd, come back and fix "" as server, and handle
462 * priority of returned error codes in torture test and samba 3
463 * server */
465 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
466 r.in.environment = architecture;
467 r.in.level = level;
468 r.in.buffer = NULL;
469 r.in.offered = 0;
470 r.out.needed = &needed;
471 r.out.count = &count;
472 r.out.info = &info;
474 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
476 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, ctx, &r);
477 torture_assert_ntstatus_ok(tctx, status,
478 "dcerpc_spoolss_EnumPrinterDrivers failed");
479 if (W_ERROR_IS_OK(r.out.result)) {
480 /* TODO: do some more checks here */
481 continue;
483 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
484 blob = data_blob_talloc(ctx, NULL, needed);
485 data_blob_clear(&blob);
486 r.in.buffer = &blob;
487 r.in.offered = needed;
489 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, ctx, &r);
490 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
493 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
495 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
497 ctx->driver_count[level] = count;
498 ctx->drivers[level] = info;
501 for (i=1;i<ARRAY_SIZE(levels);i++) {
502 int level = levels[i];
503 int old_level = levels[i-1];
505 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
506 "EnumPrinterDrivers invalid value");
509 for (i=0;i<ARRAY_SIZE(levels);i++) {
510 int level = levels[i];
512 for (j=0;j<ctx->driver_count[level];j++) {
513 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
514 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
516 switch (level) {
517 case 1:
518 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
519 break;
520 case 2:
521 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
522 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
523 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
524 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
525 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
526 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
527 break;
528 case 3:
529 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
530 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
531 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
532 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
533 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
534 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
535 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
536 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
537 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
538 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
539 break;
540 case 4:
541 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
542 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
543 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
544 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
545 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
546 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
547 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
548 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
549 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
550 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
551 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
552 break;
553 case 5:
554 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
555 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
556 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
557 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
558 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
559 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
560 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
561 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
562 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
563 break;
564 case 6:
565 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
566 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
567 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
568 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
569 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
570 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
571 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
572 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
573 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
574 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
575 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
576 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
577 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
578 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
579 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
580 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
581 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
582 break;
583 case 8:
584 /* level 8 is our reference, and it makes no sense to compare it to itself */
585 break;
590 return true;
593 static bool test_EnumMonitors(struct torture_context *tctx,
594 struct dcerpc_binding_handle *b,
595 struct test_spoolss_context *ctx)
597 NTSTATUS status;
598 struct spoolss_EnumMonitors r;
599 uint16_t levels[] = { 1, 2 };
600 int i, j;
602 for (i=0;i<ARRAY_SIZE(levels);i++) {
603 int level = levels[i];
604 DATA_BLOB blob;
605 uint32_t needed;
606 uint32_t count;
607 union spoolss_MonitorInfo *info;
609 r.in.servername = "";
610 r.in.level = level;
611 r.in.buffer = NULL;
612 r.in.offered = 0;
613 r.out.needed = &needed;
614 r.out.count = &count;
615 r.out.info = &info;
617 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
619 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
620 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
621 if (W_ERROR_IS_OK(r.out.result)) {
622 /* TODO: do some more checks here */
623 continue;
625 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
626 "EnumMonitors failed");
628 blob = data_blob_talloc(ctx, NULL, needed);
629 data_blob_clear(&blob);
630 r.in.buffer = &blob;
631 r.in.offered = needed;
633 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
634 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
636 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
638 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
640 ctx->monitor_count[level] = count;
641 ctx->monitors[level] = info;
644 for (i=1;i<ARRAY_SIZE(levels);i++) {
645 int level = levels[i];
646 int old_level = levels[i-1];
647 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
648 "EnumMonitors invalid value");
651 for (i=0;i<ARRAY_SIZE(levels);i++) {
652 int level = levels[i];
653 for (j=0;j<ctx->monitor_count[level];j++) {
654 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
655 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
656 switch (level) {
657 case 1:
658 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
659 break;
660 case 2:
661 /* level 2 is our reference, and it makes no sense to compare it to itself */
662 break;
667 return true;
670 static bool test_EnumPrintProcessors(struct torture_context *tctx,
671 struct dcerpc_binding_handle *b,
672 struct test_spoolss_context *ctx,
673 const char *environment)
675 NTSTATUS status;
676 struct spoolss_EnumPrintProcessors r;
677 uint16_t levels[] = { 1 };
678 int i, j;
680 for (i=0;i<ARRAY_SIZE(levels);i++) {
681 int level = levels[i];
682 DATA_BLOB blob;
683 uint32_t needed;
684 uint32_t count;
685 union spoolss_PrintProcessorInfo *info;
687 r.in.servername = "";
688 r.in.environment = environment;
689 r.in.level = level;
690 r.in.buffer = NULL;
691 r.in.offered = 0;
692 r.out.needed = &needed;
693 r.out.count = &count;
694 r.out.info = &info;
696 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
698 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
699 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
700 if (W_ERROR_IS_OK(r.out.result)) {
701 /* TODO: do some more checks here */
702 continue;
704 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
705 "EnumPrintProcessors unexpected return code");
707 blob = data_blob_talloc(ctx, NULL, needed);
708 data_blob_clear(&blob);
709 r.in.buffer = &blob;
710 r.in.offered = needed;
712 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
713 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
715 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
717 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
719 ctx->print_processor_count[level] = count;
720 ctx->print_processors[level] = info;
723 for (i=1;i<ARRAY_SIZE(levels);i++) {
724 int level = levels[i];
725 int old_level = levels[i-1];
726 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
727 "EnumPrintProcessors failed");
730 for (i=0;i<ARRAY_SIZE(levels);i++) {
731 int level = levels[i];
732 for (j=0;j<ctx->print_processor_count[level];j++) {
733 #if 0
734 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
735 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
736 #endif
737 switch (level) {
738 case 1:
739 /* level 1 is our reference, and it makes no sense to compare it to itself */
740 break;
745 return true;
748 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
749 struct dcerpc_binding_handle *b)
751 NTSTATUS status;
752 struct spoolss_EnumPrintProcDataTypes r;
753 uint16_t levels[] = { 1 };
754 int i;
756 for (i=0;i<ARRAY_SIZE(levels);i++) {
757 int level = levels[i];
758 DATA_BLOB blob;
759 uint32_t needed;
760 uint32_t count;
761 union spoolss_PrintProcDataTypesInfo *info;
763 r.in.servername = "";
764 r.in.print_processor_name = "winprint";
765 r.in.level = level;
766 r.in.buffer = NULL;
767 r.in.offered = 0;
768 r.out.needed = &needed;
769 r.out.count = &count;
770 r.out.info = &info;
772 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
774 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
775 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
776 if (W_ERROR_IS_OK(r.out.result)) {
777 /* TODO: do some more checks here */
778 continue;
780 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
781 "EnumPrintProcDataTypes unexpected return code");
783 blob = data_blob_talloc(tctx, NULL, needed);
784 data_blob_clear(&blob);
785 r.in.buffer = &blob;
786 r.in.offered = needed;
788 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
789 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
791 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
793 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
797 return true;
801 static bool test_EnumPrinters(struct torture_context *tctx,
802 struct dcerpc_binding_handle *b,
803 struct test_spoolss_context *ctx)
805 struct spoolss_EnumPrinters r;
806 NTSTATUS status;
807 uint16_t levels[] = { 0, 1, 2, 4, 5 };
808 int i, j;
810 for (i=0;i<ARRAY_SIZE(levels);i++) {
811 int level = levels[i];
812 DATA_BLOB blob;
813 uint32_t needed;
814 uint32_t count;
815 union spoolss_PrinterInfo *info;
817 r.in.flags = PRINTER_ENUM_LOCAL;
818 r.in.server = "";
819 r.in.level = level;
820 r.in.buffer = NULL;
821 r.in.offered = 0;
822 r.out.needed = &needed;
823 r.out.count = &count;
824 r.out.info = &info;
826 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
828 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
829 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
830 if (W_ERROR_IS_OK(r.out.result)) {
831 /* TODO: do some more checks here */
832 continue;
834 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
835 "EnumPrinters unexpected return code");
837 blob = data_blob_talloc(ctx, NULL, needed);
838 data_blob_clear(&blob);
839 r.in.buffer = &blob;
840 r.in.offered = needed;
842 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
843 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
845 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
847 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
849 ctx->printer_count[level] = count;
850 ctx->printers[level] = info;
853 for (i=1;i<ARRAY_SIZE(levels);i++) {
854 int level = levels[i];
855 int old_level = levels[i-1];
856 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
857 "EnumPrinters invalid value");
860 for (i=0;i<ARRAY_SIZE(levels);i++) {
861 int level = levels[i];
862 for (j=0;j<ctx->printer_count[level];j++) {
863 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
864 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
865 switch (level) {
866 case 0:
867 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
868 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
869 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
870 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
871 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
872 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
873 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
874 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
875 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
876 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
877 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
878 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
879 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
880 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
881 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
882 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
883 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
884 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
885 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
886 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
887 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
888 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
889 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
890 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
891 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
892 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
893 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
894 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
895 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
896 break;
897 case 1:
898 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
899 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
900 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
901 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
902 break;
903 case 2:
904 /* level 2 is our reference, and it makes no sense to compare it to itself */
905 break;
906 case 4:
907 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
908 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
909 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
910 break;
911 case 5:
912 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
913 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
914 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
915 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
916 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
917 break;
922 /* TODO:
923 * - verify that the port of a printer was in the list returned by EnumPorts
926 return true;
929 static bool test_GetPrinterDriver2(struct torture_context *tctx,
930 struct dcerpc_binding_handle *b,
931 struct policy_handle *handle,
932 const char *driver_name,
933 const char *environment);
935 bool test_GetPrinter_level(struct torture_context *tctx,
936 struct dcerpc_binding_handle *b,
937 struct policy_handle *handle,
938 uint32_t level,
939 union spoolss_PrinterInfo *info)
941 struct spoolss_GetPrinter r;
942 uint32_t needed;
944 r.in.handle = handle;
945 r.in.level = level;
946 r.in.buffer = NULL;
947 r.in.offered = 0;
948 r.out.needed = &needed;
950 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
952 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
953 "GetPrinter failed");
955 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
956 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
957 data_blob_clear(&blob);
958 r.in.buffer = &blob;
959 r.in.offered = needed;
961 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
962 "GetPrinter failed");
965 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
967 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
969 if (info && r.out.info) {
970 *info = *r.out.info;
973 return true;
977 static bool test_GetPrinter(struct torture_context *tctx,
978 struct dcerpc_binding_handle *b,
979 struct policy_handle *handle,
980 const char *environment)
982 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
983 int i;
985 for (i=0;i<ARRAY_SIZE(levels);i++) {
987 union spoolss_PrinterInfo info;
989 ZERO_STRUCT(info);
991 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
992 "failed to call GetPrinter");
994 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
995 torture_assert(tctx,
996 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
997 "failed to call test_GetPrinterDriver2");
1001 return true;
1004 static bool test_SetPrinter(struct torture_context *tctx,
1005 struct dcerpc_binding_handle *b,
1006 struct policy_handle *handle,
1007 struct spoolss_SetPrinterInfoCtr *info_ctr,
1008 struct spoolss_DevmodeContainer *devmode_ctr,
1009 struct sec_desc_buf *secdesc_ctr,
1010 enum spoolss_PrinterControl command)
1012 struct spoolss_SetPrinter r;
1014 r.in.handle = handle;
1015 r.in.info_ctr = info_ctr;
1016 r.in.devmode_ctr = devmode_ctr;
1017 r.in.secdesc_ctr = secdesc_ctr;
1018 r.in.command = command;
1020 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1022 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1023 "failed to call SetPrinter");
1024 torture_assert_werr_ok(tctx, r.out.result,
1025 "failed to call SetPrinter");
1027 return true;
1030 static bool test_SetPrinter_errors(struct torture_context *tctx,
1031 struct dcerpc_binding_handle *b,
1032 struct policy_handle *handle)
1034 struct spoolss_SetPrinter r;
1035 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1036 int i;
1038 struct spoolss_SetPrinterInfoCtr info_ctr;
1039 struct spoolss_DevmodeContainer devmode_ctr;
1040 struct sec_desc_buf secdesc_ctr;
1042 info_ctr.level = 0;
1043 info_ctr.info.info0 = NULL;
1045 ZERO_STRUCT(devmode_ctr);
1046 ZERO_STRUCT(secdesc_ctr);
1048 r.in.handle = handle;
1049 r.in.info_ctr = &info_ctr;
1050 r.in.devmode_ctr = &devmode_ctr;
1051 r.in.secdesc_ctr = &secdesc_ctr;
1052 r.in.command = 0;
1054 torture_comment(tctx, "Testing SetPrinter all zero\n");
1056 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1057 "failed to call SetPrinter");
1058 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1059 "failed to call SetPrinter");
1061 again:
1062 for (i=0; i < ARRAY_SIZE(levels); i++) {
1064 struct spoolss_SetPrinterInfo0 info0;
1065 struct spoolss_SetPrinterInfo1 info1;
1066 struct spoolss_SetPrinterInfo2 info2;
1067 struct spoolss_SetPrinterInfo3 info3;
1068 struct spoolss_SetPrinterInfo4 info4;
1069 struct spoolss_SetPrinterInfo5 info5;
1070 struct spoolss_SetPrinterInfo6 info6;
1071 struct spoolss_SetPrinterInfo7 info7;
1072 struct spoolss_SetPrinterInfo8 info8;
1073 struct spoolss_SetPrinterInfo9 info9;
1076 info_ctr.level = levels[i];
1077 switch (levels[i]) {
1078 case 0:
1079 ZERO_STRUCT(info0);
1080 info_ctr.info.info0 = &info0;
1081 break;
1082 case 1:
1083 ZERO_STRUCT(info1);
1084 info_ctr.info.info1 = &info1;
1085 break;
1086 case 2:
1087 ZERO_STRUCT(info2);
1088 info_ctr.info.info2 = &info2;
1089 break;
1090 case 3:
1091 ZERO_STRUCT(info3);
1092 info_ctr.info.info3 = &info3;
1093 break;
1094 case 4:
1095 ZERO_STRUCT(info4);
1096 info_ctr.info.info4 = &info4;
1097 break;
1098 case 5:
1099 ZERO_STRUCT(info5);
1100 info_ctr.info.info5 = &info5;
1101 break;
1102 case 6:
1103 ZERO_STRUCT(info6);
1104 info_ctr.info.info6 = &info6;
1105 break;
1106 case 7:
1107 ZERO_STRUCT(info7);
1108 info_ctr.info.info7 = &info7;
1109 break;
1110 case 8:
1111 ZERO_STRUCT(info8);
1112 info_ctr.info.info8 = &info8;
1113 break;
1114 case 9:
1115 ZERO_STRUCT(info9);
1116 info_ctr.info.info9 = &info9;
1117 break;
1120 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1121 info_ctr.level, r.in.command);
1123 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1124 "failed to call SetPrinter");
1126 switch (r.in.command) {
1127 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1128 /* is ignored for all levels other then 0 */
1129 if (info_ctr.level > 0) {
1130 /* ignored then */
1131 break;
1133 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1134 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1135 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1136 if (info_ctr.level > 0) {
1137 /* is invalid for all levels other then 0 */
1138 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1139 "unexpected error code returned");
1140 continue;
1141 } else {
1142 torture_assert_werr_ok(tctx, r.out.result,
1143 "failed to call SetPrinter with non 0 command");
1144 continue;
1146 break;
1148 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1149 /* FIXME: gd needs further investigation */
1150 default:
1151 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1152 "unexpected error code returned");
1153 continue;
1156 switch (info_ctr.level) {
1157 case 1:
1158 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1159 "unexpected error code returned");
1160 break;
1161 case 2:
1162 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1163 "unexpected error code returned");
1164 break;
1165 case 3:
1166 case 4:
1167 case 5:
1168 case 7:
1169 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1170 "unexpected error code returned");
1171 break;
1172 case 9:
1173 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1174 "unexpected error code returned");
1175 break;
1176 default:
1177 torture_assert_werr_ok(tctx, r.out.result,
1178 "failed to call SetPrinter");
1179 break;
1183 if (r.in.command < 5) {
1184 r.in.command++;
1185 goto again;
1188 return true;
1191 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1193 if ((r->level == 2) && (r->info.info2)) {
1194 r->info.info2->secdesc_ptr = 0;
1195 r->info.info2->devmode_ptr = 0;
1199 static bool test_PrinterInfo(struct torture_context *tctx,
1200 struct dcerpc_binding_handle *b,
1201 struct policy_handle *handle)
1203 NTSTATUS status;
1204 struct spoolss_SetPrinter s;
1205 struct spoolss_GetPrinter q;
1206 struct spoolss_GetPrinter q0;
1207 struct spoolss_SetPrinterInfoCtr info_ctr;
1208 union spoolss_PrinterInfo info;
1209 struct spoolss_DevmodeContainer devmode_ctr;
1210 struct sec_desc_buf secdesc_ctr;
1211 uint32_t needed;
1212 bool ret = true;
1213 int i;
1215 uint32_t status_list[] = {
1216 /* these do not stick
1217 PRINTER_STATUS_PAUSED,
1218 PRINTER_STATUS_ERROR,
1219 PRINTER_STATUS_PENDING_DELETION, */
1220 PRINTER_STATUS_PAPER_JAM,
1221 PRINTER_STATUS_PAPER_OUT,
1222 PRINTER_STATUS_MANUAL_FEED,
1223 PRINTER_STATUS_PAPER_PROBLEM,
1224 PRINTER_STATUS_OFFLINE,
1225 PRINTER_STATUS_IO_ACTIVE,
1226 PRINTER_STATUS_BUSY,
1227 PRINTER_STATUS_PRINTING,
1228 PRINTER_STATUS_OUTPUT_BIN_FULL,
1229 PRINTER_STATUS_NOT_AVAILABLE,
1230 PRINTER_STATUS_WAITING,
1231 PRINTER_STATUS_PROCESSING,
1232 PRINTER_STATUS_INITIALIZING,
1233 PRINTER_STATUS_WARMING_UP,
1234 PRINTER_STATUS_TONER_LOW,
1235 PRINTER_STATUS_NO_TONER,
1236 PRINTER_STATUS_PAGE_PUNT,
1237 PRINTER_STATUS_USER_INTERVENTION,
1238 PRINTER_STATUS_OUT_OF_MEMORY,
1239 PRINTER_STATUS_DOOR_OPEN,
1240 PRINTER_STATUS_SERVER_UNKNOWN,
1241 PRINTER_STATUS_POWER_SAVE,
1242 /* these do not stick
1243 0x02000000,
1244 0x04000000,
1245 0x08000000,
1246 0x10000000,
1247 0x20000000,
1248 0x40000000,
1249 0x80000000 */
1251 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1252 uint32_t attribute_list[] = {
1253 PRINTER_ATTRIBUTE_QUEUED,
1254 /* fails with WERR_INVALID_DATATYPE:
1255 PRINTER_ATTRIBUTE_DIRECT, */
1256 /* does not stick
1257 PRINTER_ATTRIBUTE_DEFAULT, */
1258 PRINTER_ATTRIBUTE_SHARED,
1259 /* does not stick
1260 PRINTER_ATTRIBUTE_NETWORK, */
1261 PRINTER_ATTRIBUTE_HIDDEN,
1262 PRINTER_ATTRIBUTE_LOCAL,
1263 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1264 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1265 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1266 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1267 /* does not stick
1268 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1269 /* fails with WERR_INVALID_DATATYPE:
1270 PRINTER_ATTRIBUTE_RAW_ONLY, */
1271 /* these do not stick
1272 PRINTER_ATTRIBUTE_PUBLISHED,
1273 PRINTER_ATTRIBUTE_FAX,
1274 PRINTER_ATTRIBUTE_TS,
1275 0x00010000,
1276 0x00020000,
1277 0x00040000,
1278 0x00080000,
1279 0x00100000,
1280 0x00200000,
1281 0x00400000,
1282 0x00800000,
1283 0x01000000,
1284 0x02000000,
1285 0x04000000,
1286 0x08000000,
1287 0x10000000,
1288 0x20000000,
1289 0x40000000,
1290 0x80000000 */
1293 ZERO_STRUCT(devmode_ctr);
1294 ZERO_STRUCT(secdesc_ctr);
1296 s.in.handle = handle;
1297 s.in.command = 0;
1298 s.in.info_ctr = &info_ctr;
1299 s.in.devmode_ctr = &devmode_ctr;
1300 s.in.secdesc_ctr = &secdesc_ctr;
1302 q.in.handle = handle;
1303 q.out.info = &info;
1304 q0 = q;
1306 #define TESTGETCALL(call, r) \
1307 r.in.buffer = NULL; \
1308 r.in.offered = 0;\
1309 r.out.needed = &needed; \
1310 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1311 if (!NT_STATUS_IS_OK(status)) { \
1312 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1313 r.in.level, nt_errstr(status), __location__); \
1314 ret = false; \
1315 break; \
1317 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1318 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1319 data_blob_clear(&blob); \
1320 r.in.buffer = &blob; \
1321 r.in.offered = needed; \
1323 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1324 if (!NT_STATUS_IS_OK(status)) { \
1325 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1326 r.in.level, nt_errstr(status), __location__); \
1327 ret = false; \
1328 break; \
1330 if (!W_ERROR_IS_OK(r.out.result)) { \
1331 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1332 r.in.level, win_errstr(r.out.result), __location__); \
1333 ret = false; \
1334 break; \
1338 #define TESTSETCALL_EXP(call, r, err) \
1339 clear_info2(&info_ctr);\
1340 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1341 if (!NT_STATUS_IS_OK(status)) { \
1342 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1343 r.in.info_ctr->level, nt_errstr(status), __location__); \
1344 ret = false; \
1345 break; \
1347 if (!W_ERROR_IS_OK(err)) { \
1348 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1349 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1350 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1351 ret = false; \
1353 break; \
1355 if (!W_ERROR_IS_OK(r.out.result)) { \
1356 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1357 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1358 ret = false; \
1359 break; \
1362 #define TESTSETCALL(call, r) \
1363 TESTSETCALL_EXP(call, r, WERR_OK)
1365 #define STRING_EQUAL(s1, s2, field) \
1366 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1367 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1368 #field, s2, __location__); \
1369 ret = false; \
1370 break; \
1373 #define MEM_EQUAL(s1, s2, length, field) \
1374 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1375 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1376 #field, (const char *)s2, __location__); \
1377 ret = false; \
1378 break; \
1381 #define INT_EQUAL(i1, i2, field) \
1382 if (i1 != i2) { \
1383 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1384 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1385 ret = false; \
1386 break; \
1389 #define SD_EQUAL(sd1, sd2, field) \
1390 if (!security_descriptor_equal(sd1, sd2)) { \
1391 torture_comment(tctx, "Failed to set %s (%s)\n", \
1392 #field, __location__); \
1393 ret = false; \
1394 break; \
1397 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1398 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1399 q.in.level = lvl1; \
1400 TESTGETCALL(GetPrinter, q) \
1401 info_ctr.level = lvl1; \
1402 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1403 info_ctr.info.info ## lvl1->field1 = value;\
1404 TESTSETCALL_EXP(SetPrinter, s, err) \
1405 info_ctr.info.info ## lvl1->field1 = ""; \
1406 TESTGETCALL(GetPrinter, q) \
1407 info_ctr.info.info ## lvl1->field1 = value; \
1408 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1409 q.in.level = lvl2; \
1410 TESTGETCALL(GetPrinter, q) \
1411 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1412 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1413 } while (0)
1415 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1416 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1417 } while (0);
1419 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1420 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1421 q.in.level = lvl1; \
1422 TESTGETCALL(GetPrinter, q) \
1423 info_ctr.level = lvl1; \
1424 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1425 info_ctr.info.info ## lvl1->field1 = value; \
1426 TESTSETCALL(SetPrinter, s) \
1427 info_ctr.info.info ## lvl1->field1 = 0; \
1428 TESTGETCALL(GetPrinter, q) \
1429 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1430 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1431 q.in.level = lvl2; \
1432 TESTGETCALL(GetPrinter, q) \
1433 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1434 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1435 } while (0)
1437 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1438 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1439 } while (0)
1441 q0.in.level = 0;
1442 do { TESTGETCALL(GetPrinter, q0) } while (0);
1444 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1445 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1447 /* level 0 printername does not stick */
1448 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1449 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1450 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1451 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1452 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1453 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1454 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1455 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1456 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1457 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1458 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1459 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1460 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1461 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1462 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1464 /* servername can be set but does not stick
1465 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1466 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1467 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1470 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1471 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1472 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1473 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1474 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1476 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1477 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1478 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1479 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1480 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1481 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1482 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1483 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1484 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1485 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1487 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1488 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1489 attribute_list[i],
1490 (attribute_list[i] | default_attribute)
1491 ); */
1492 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1493 attribute_list[i],
1494 (attribute_list[i] | default_attribute)
1496 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1497 attribute_list[i],
1498 (attribute_list[i] | default_attribute)
1500 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1501 attribute_list[i],
1502 (attribute_list[i] | default_attribute)
1504 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1505 attribute_list[i],
1506 (attribute_list[i] | default_attribute)
1507 ); */
1508 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1509 attribute_list[i],
1510 (attribute_list[i] | default_attribute)
1512 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1513 attribute_list[i],
1514 (attribute_list[i] | default_attribute)
1516 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1517 attribute_list[i],
1518 (attribute_list[i] | default_attribute)
1520 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1521 attribute_list[i],
1522 (attribute_list[i] | default_attribute)
1523 ); */
1524 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1525 attribute_list[i],
1526 (attribute_list[i] | default_attribute)
1528 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1529 attribute_list[i],
1530 (attribute_list[i] | default_attribute)
1532 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1533 attribute_list[i],
1534 (attribute_list[i] | default_attribute)
1538 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1539 /* level 2 sets do not stick
1540 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1541 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1542 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1543 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1544 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1545 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1548 /* priorities need to be between 0 and 99
1549 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1550 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1551 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1552 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1553 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1554 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1555 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1556 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1557 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1559 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1560 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1562 /* does not stick
1563 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1564 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1566 /* does not stick
1567 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1568 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1570 /* FIXME: gd also test devmode and secdesc behavior */
1573 /* verify composition of level 1 description field */
1574 const char *description;
1575 const char *tmp;
1577 q0.in.level = 1;
1578 do { TESTGETCALL(GetPrinter, q0) } while (0);
1580 description = talloc_strdup(tctx, q0.out.info->info1.description);
1582 q0.in.level = 2;
1583 do { TESTGETCALL(GetPrinter, q0) } while (0);
1585 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1586 q0.out.info->info2.printername,
1587 q0.out.info->info2.drivername,
1588 q0.out.info->info2.location);
1590 do { STRING_EQUAL(description, tmp, "description")} while (0);
1593 return ret;
1596 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1597 do { struct dom_sid *__got = (got), *__expected = (expected); \
1598 if (!dom_sid_equal(__got, __expected)) { \
1599 torture_result(torture_ctx, TORTURE_FAIL, \
1600 __location__": "#got" was %s, expected %s: %s", \
1601 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1602 return false; \
1604 } while(0)
1606 static bool test_security_descriptor_equal(struct torture_context *tctx,
1607 const struct security_descriptor *sd1,
1608 const struct security_descriptor *sd2)
1610 if (sd1 == sd2) {
1611 return true;
1614 if (!sd1 || !sd2) {
1615 torture_comment(tctx, "%s\n", __location__);
1616 return false;
1619 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1620 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1622 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1623 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1625 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1626 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1627 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1628 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1629 return false;
1631 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1632 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1633 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1634 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1635 return false;
1638 return true;
1641 static bool test_sd_set_level(struct torture_context *tctx,
1642 struct dcerpc_binding_handle *b,
1643 struct policy_handle *handle,
1644 uint32_t level,
1645 struct security_descriptor *sd)
1647 struct spoolss_SetPrinterInfoCtr info_ctr;
1648 struct spoolss_DevmodeContainer devmode_ctr;
1649 struct sec_desc_buf secdesc_ctr;
1650 union spoolss_SetPrinterInfo sinfo;
1652 ZERO_STRUCT(devmode_ctr);
1653 ZERO_STRUCT(secdesc_ctr);
1655 switch (level) {
1656 case 2: {
1657 union spoolss_PrinterInfo info;
1658 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1659 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1661 info_ctr.level = 2;
1662 info_ctr.info = sinfo;
1664 break;
1666 case 3: {
1667 struct spoolss_SetPrinterInfo3 info3;
1669 info3.sec_desc_ptr = 0;
1671 info_ctr.level = 3;
1672 info_ctr.info.info3 = &info3;
1674 break;
1676 default:
1677 return false;
1680 secdesc_ctr.sd = sd;
1682 torture_assert(tctx,
1683 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1685 return true;
1688 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1689 struct dcerpc_binding_handle *b,
1690 struct policy_handle *handle)
1692 union spoolss_PrinterInfo info;
1693 struct security_descriptor *sd1, *sd2;
1694 int i;
1696 /* just compare level 2 and level 3 */
1698 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1700 sd1 = info.info2.secdesc;
1702 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1704 sd2 = info.info3.secdesc;
1706 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1707 "SD level 2 != SD level 3");
1710 /* query level 2, set level 2, query level 2 */
1712 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1714 sd1 = info.info2.secdesc;
1716 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1718 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1720 sd2 = info.info2.secdesc;
1721 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1722 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1723 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1726 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1727 "SD level 2 != SD level 2 after SD has been set via level 2");
1730 /* query level 2, set level 3, query level 2 */
1732 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1734 sd1 = info.info2.secdesc;
1736 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1738 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1740 sd2 = info.info2.secdesc;
1742 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1743 "SD level 2 != SD level 2 after SD has been set via level 3");
1745 /* set modified sd level 3, query level 2 */
1747 for (i=0; i < 93; i++) {
1748 struct security_ace a;
1749 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1750 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1751 a.flags = 0;
1752 a.size = 0; /* autogenerated */
1753 a.access_mask = 0;
1754 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1755 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1758 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1760 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1761 sd2 = info.info2.secdesc;
1763 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1764 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1765 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1768 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1769 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1772 return true;
1776 * wrapper call that saves original sd, runs tests, and restores sd
1779 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1780 struct dcerpc_binding_handle *b,
1781 struct policy_handle *handle)
1783 union spoolss_PrinterInfo info;
1784 struct security_descriptor *sd;
1785 bool ret = true;
1787 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1789 /* save original sd */
1791 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1792 "failed to get initial security descriptor");
1794 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1796 /* run tests */
1798 ret = test_PrinterInfo_SDs(tctx, b, handle);
1800 /* restore original sd */
1802 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1803 "failed to restore initial security descriptor");
1805 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1806 ret ? "succeeded" : "failed");
1809 return ret;
1812 static bool test_devmode_set_level(struct torture_context *tctx,
1813 struct dcerpc_binding_handle *b,
1814 struct policy_handle *handle,
1815 uint32_t level,
1816 struct spoolss_DeviceMode *devmode)
1818 struct spoolss_SetPrinterInfoCtr info_ctr;
1819 struct spoolss_DevmodeContainer devmode_ctr;
1820 struct sec_desc_buf secdesc_ctr;
1821 union spoolss_SetPrinterInfo sinfo;
1823 ZERO_STRUCT(devmode_ctr);
1824 ZERO_STRUCT(secdesc_ctr);
1826 switch (level) {
1827 case 2: {
1828 union spoolss_PrinterInfo info;
1829 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1830 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1832 info_ctr.level = 2;
1833 info_ctr.info = sinfo;
1835 break;
1837 case 8: {
1838 struct spoolss_SetPrinterInfo8 info8;
1840 info8.devmode_ptr = 0;
1842 info_ctr.level = 8;
1843 info_ctr.info.info8 = &info8;
1845 break;
1847 default:
1848 return false;
1851 devmode_ctr.devmode = devmode;
1853 torture_assert(tctx,
1854 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1856 return true;
1860 static bool test_devicemode_equal(struct torture_context *tctx,
1861 const struct spoolss_DeviceMode *d1,
1862 const struct spoolss_DeviceMode *d2)
1864 if (d1 == d2) {
1865 return true;
1868 if (!d1 || !d2) {
1869 torture_comment(tctx, "%s\n", __location__);
1870 return false;
1872 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1873 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1874 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1875 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1876 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1877 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1878 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1879 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1880 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1881 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1882 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1883 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1884 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1885 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1886 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1887 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1888 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1889 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1890 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1891 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1892 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1893 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1894 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1895 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1896 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1897 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1898 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1899 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1900 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1901 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1902 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1903 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1904 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1905 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1906 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1908 return true;
1911 static bool test_devicemode_full(struct torture_context *tctx,
1912 struct dcerpc_binding_handle *b,
1913 struct policy_handle *handle)
1915 struct spoolss_SetPrinter s;
1916 struct spoolss_GetPrinter q;
1917 struct spoolss_GetPrinter q0;
1918 struct spoolss_SetPrinterInfoCtr info_ctr;
1919 struct spoolss_SetPrinterInfo8 info8;
1920 union spoolss_PrinterInfo info;
1921 struct spoolss_DevmodeContainer devmode_ctr;
1922 struct sec_desc_buf secdesc_ctr;
1923 uint32_t needed;
1924 bool ret = true;
1925 NTSTATUS status;
1927 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1928 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1929 q.in.level = lvl1; \
1930 TESTGETCALL(GetPrinter, q) \
1931 info_ctr.level = lvl1; \
1932 if (lvl1 == 2) {\
1933 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1934 } else if (lvl1 == 8) {\
1935 info_ctr.info.info ## lvl1 = &info8; \
1937 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1938 devmode_ctr.devmode->field1 = value; \
1939 TESTSETCALL(SetPrinter, s) \
1940 TESTGETCALL(GetPrinter, q) \
1941 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1942 q.in.level = lvl2; \
1943 TESTGETCALL(GetPrinter, q) \
1944 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1945 } while (0)
1947 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1948 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1949 } while (0)
1951 ZERO_STRUCT(devmode_ctr);
1952 ZERO_STRUCT(secdesc_ctr);
1953 ZERO_STRUCT(info8);
1955 s.in.handle = handle;
1956 s.in.command = 0;
1957 s.in.info_ctr = &info_ctr;
1958 s.in.devmode_ctr = &devmode_ctr;
1959 s.in.secdesc_ctr = &secdesc_ctr;
1961 q.in.handle = handle;
1962 q.out.info = &info;
1963 q0 = q;
1965 #if 0
1966 const char *devicename;/* [charset(UTF16)] */
1967 enum spoolss_DeviceModeSpecVersion specversion;
1968 uint16_t driverversion;
1969 uint16_t size;
1970 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1971 uint32_t fields;
1972 #endif
1974 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
1975 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
1976 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
1977 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
1978 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
1979 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
1980 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
1981 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
1982 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
1983 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
1984 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
1985 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
1986 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
1987 #if 0
1988 const char *formname;/* [charset(UTF16)] */
1989 #endif
1990 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
1991 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
1992 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
1993 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
1994 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
1995 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
1996 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
1997 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
1998 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
1999 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2000 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2001 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2002 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2003 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2005 return ret;
2008 static bool call_OpenPrinterEx(struct torture_context *tctx,
2009 struct dcerpc_pipe *p,
2010 const char *name,
2011 struct spoolss_DeviceMode *devmode,
2012 struct policy_handle *handle);
2014 static bool test_ClosePrinter(struct torture_context *tctx,
2015 struct dcerpc_binding_handle *b,
2016 struct policy_handle *handle);
2018 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2019 struct dcerpc_pipe *p,
2020 struct policy_handle *handle,
2021 const char *name)
2023 union spoolss_PrinterInfo info;
2024 struct spoolss_DeviceMode *devmode;
2025 struct spoolss_DeviceMode *devmode2;
2026 struct policy_handle handle_devmode;
2027 struct dcerpc_binding_handle *b = p->binding_handle;
2029 /* simply compare level8 and level2 devmode */
2031 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2033 devmode = info.info8.devmode;
2035 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2037 devmode2 = info.info2.devmode;
2039 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2040 "DM level 8 != DM level 2");
2043 /* set devicemode level 8 and see if it persists */
2045 devmode->copies = 93;
2046 devmode->formname = talloc_strdup(tctx, "Legal");
2048 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2050 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2052 devmode2 = info.info8.devmode;
2054 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2055 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2057 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2059 devmode2 = info.info2.devmode;
2061 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2062 "modified DM level 8 != DM level 2");
2065 /* set devicemode level 2 and see if it persists */
2067 devmode->copies = 39;
2068 devmode->formname = talloc_strdup(tctx, "Executive");
2070 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2072 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2074 devmode2 = info.info8.devmode;
2076 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2077 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2079 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2081 devmode2 = info.info2.devmode;
2083 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2084 "modified DM level 8 != DM level 2");
2087 /* check every single bit in public part of devicemode */
2089 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2090 "failed to set every single devicemode component");
2093 /* change formname upon open and see if it persists in getprinter calls */
2095 devmode->formname = talloc_strdup(tctx, "A4");
2096 devmode->copies = 42;
2098 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2099 "failed to open printer handle");
2101 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2103 devmode2 = info.info8.devmode;
2105 if (strequal(devmode->devicename, devmode2->devicename)) {
2106 torture_warning(tctx, "devicenames are the same\n");
2107 } else {
2108 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2109 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2112 if (strequal(devmode->formname, devmode2->formname)) {
2113 torture_warning(tctx, "formname are the same\n");
2114 } else {
2115 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2116 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2119 if (devmode->copies == devmode2->copies) {
2120 torture_warning(tctx, "copies are the same\n");
2121 } else {
2122 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2123 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2126 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2128 devmode2 = info.info2.devmode;
2130 if (strequal(devmode->devicename, devmode2->devicename)) {
2131 torture_warning(tctx, "devicenames are the same\n");
2132 } else {
2133 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2134 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2137 if (strequal(devmode->formname, devmode2->formname)) {
2138 torture_warning(tctx, "formname is the same\n");
2139 } else {
2140 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2141 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2144 if (devmode->copies == devmode2->copies) {
2145 torture_warning(tctx, "copies are the same\n");
2146 } else {
2147 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2148 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2151 test_ClosePrinter(tctx, b, &handle_devmode);
2153 return true;
2157 * wrapper call that saves original devmode, runs tests, and restores devmode
2160 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2161 struct dcerpc_pipe *p,
2162 struct policy_handle *handle,
2163 const char *name)
2165 union spoolss_PrinterInfo info;
2166 struct spoolss_DeviceMode *devmode;
2167 bool ret = true;
2168 struct dcerpc_binding_handle *b = p->binding_handle;
2170 torture_comment(tctx, "Testing Printer Devicemodes\n");
2172 /* save original devmode */
2174 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2175 "failed to get initial global devicemode");
2177 devmode = info.info8.devmode;
2179 /* run tests */
2181 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2183 /* restore original devmode */
2185 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2186 "failed to restore initial global device mode");
2188 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2189 ret ? "succeeded" : "failed");
2192 return ret;
2195 static bool test_ClosePrinter(struct torture_context *tctx,
2196 struct dcerpc_binding_handle *b,
2197 struct policy_handle *handle)
2199 NTSTATUS status;
2200 struct spoolss_ClosePrinter r;
2202 r.in.handle = handle;
2203 r.out.handle = handle;
2205 torture_comment(tctx, "Testing ClosePrinter\n");
2207 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2208 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2209 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2211 return true;
2214 static bool test_GetForm_args(struct torture_context *tctx,
2215 struct dcerpc_binding_handle *b,
2216 struct policy_handle *handle,
2217 const char *form_name,
2218 uint32_t level,
2219 union spoolss_FormInfo *info_p)
2221 NTSTATUS status;
2222 struct spoolss_GetForm r;
2223 uint32_t needed;
2225 r.in.handle = handle;
2226 r.in.form_name = form_name;
2227 r.in.level = level;
2228 r.in.buffer = NULL;
2229 r.in.offered = 0;
2230 r.out.needed = &needed;
2232 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2234 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2235 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2237 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2238 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2239 data_blob_clear(&blob);
2240 r.in.buffer = &blob;
2241 r.in.offered = needed;
2242 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2243 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2245 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2247 torture_assert(tctx, r.out.info, "No form info returned");
2250 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2252 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2254 if (info_p) {
2255 *info_p = *r.out.info;
2258 return true;
2261 static bool test_GetForm(struct torture_context *tctx,
2262 struct dcerpc_binding_handle *b,
2263 struct policy_handle *handle,
2264 const char *form_name,
2265 uint32_t level)
2267 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2270 static bool test_EnumForms(struct torture_context *tctx,
2271 struct dcerpc_binding_handle *b,
2272 struct policy_handle *handle,
2273 bool print_server,
2274 uint32_t level,
2275 uint32_t *count_p,
2276 union spoolss_FormInfo **info_p)
2278 struct spoolss_EnumForms r;
2279 uint32_t needed;
2280 uint32_t count;
2281 union spoolss_FormInfo *info;
2283 r.in.handle = handle;
2284 r.in.level = level;
2285 r.in.buffer = NULL;
2286 r.in.offered = 0;
2287 r.out.needed = &needed;
2288 r.out.count = &count;
2289 r.out.info = &info;
2291 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2293 torture_assert_ntstatus_ok(tctx,
2294 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2295 "EnumForms failed");
2297 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2298 torture_skip(tctx, "EnumForms level 2 not supported");
2301 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2302 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2305 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2306 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2307 data_blob_clear(&blob);
2308 r.in.buffer = &blob;
2309 r.in.offered = needed;
2311 torture_assert_ntstatus_ok(tctx,
2312 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2313 "EnumForms failed");
2315 torture_assert(tctx, info, "No forms returned");
2318 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2320 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2322 if (info_p) {
2323 *info_p = info;
2325 if (count_p) {
2326 *count_p = count;
2329 return true;
2332 static bool test_EnumForms_all(struct torture_context *tctx,
2333 struct dcerpc_binding_handle *b,
2334 struct policy_handle *handle,
2335 bool print_server)
2337 uint32_t levels[] = { 1, 2 };
2338 int i, j;
2340 for (i=0; i<ARRAY_SIZE(levels); i++) {
2342 uint32_t count = 0;
2343 union spoolss_FormInfo *info = NULL;
2345 torture_assert(tctx,
2346 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2347 "failed to enum forms");
2349 for (j = 0; j < count; j++) {
2350 if (!print_server) {
2351 torture_assert(tctx,
2352 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2353 "failed to get form");
2358 return true;
2361 static bool test_EnumForms_find_one(struct torture_context *tctx,
2362 struct dcerpc_binding_handle *b,
2363 struct policy_handle *handle,
2364 bool print_server,
2365 const char *form_name)
2367 union spoolss_FormInfo *info;
2368 uint32_t count;
2369 bool found = false;
2370 int i;
2372 torture_assert(tctx,
2373 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2374 "failed to enumerate forms");
2376 for (i=0; i<count; i++) {
2377 if (strequal(form_name, info[i].info1.form_name)) {
2378 found = true;
2379 break;
2383 return found;
2386 static bool test_DeleteForm(struct torture_context *tctx,
2387 struct dcerpc_binding_handle *b,
2388 struct policy_handle *handle,
2389 const char *form_name)
2391 struct spoolss_DeleteForm r;
2393 r.in.handle = handle;
2394 r.in.form_name = form_name;
2396 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2398 torture_assert_ntstatus_ok(tctx,
2399 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2400 "DeleteForm failed");
2401 torture_assert_werr_ok(tctx, r.out.result,
2402 "DeleteForm failed");
2403 torture_assert_ntstatus_ok(tctx,
2404 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2405 "2nd DeleteForm failed");
2406 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2407 "2nd DeleteForm failed");
2409 return true;
2412 static bool test_AddForm(struct torture_context *tctx,
2413 struct dcerpc_binding_handle *b,
2414 struct policy_handle *handle,
2415 uint32_t level,
2416 union spoolss_AddFormInfo *info)
2418 struct spoolss_AddForm r;
2420 if (level != 1) {
2421 torture_skip(tctx, "only level 1 supported");
2424 r.in.handle = handle;
2425 r.in.level = level;
2426 r.in.info = *info;
2428 torture_comment(tctx, "Testing AddForm(%s) level %d\n",
2429 r.in.info.info1->form_name, r.in.level);
2431 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2432 "AddForm failed");
2433 if (W_ERROR_EQUAL(r.out.result, WERR_FILE_EXISTS)) {
2434 test_DeleteForm(tctx, b, handle, r.in.info.info1->form_name);
2435 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2436 "AddForm failed");
2439 torture_assert_werr_ok(tctx, r.out.result,
2440 "AddForm failed");
2442 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2443 "2nd AddForm failed");
2444 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2445 "2nd AddForm gave unexpected result");
2447 return true;
2450 static bool test_SetForm(struct torture_context *tctx,
2451 struct dcerpc_binding_handle *b,
2452 struct policy_handle *handle,
2453 const char *form_name,
2454 uint32_t level,
2455 union spoolss_AddFormInfo *info)
2457 struct spoolss_SetForm r;
2459 r.in.handle = handle;
2460 r.in.form_name = form_name;
2461 r.in.level = level;
2462 r.in.info = *info;
2464 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2465 form_name, r.in.level);
2467 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2468 "SetForm failed");
2470 torture_assert_werr_ok(tctx, r.out.result,
2471 "SetForm failed");
2473 return true;
2476 static bool test_GetForm_winreg(struct torture_context *tctx,
2477 struct dcerpc_binding_handle *b,
2478 struct policy_handle *handle,
2479 const char *key_name,
2480 const char *form_name,
2481 enum winreg_Type *w_type,
2482 uint32_t *w_size,
2483 uint32_t *w_length,
2484 uint8_t **w_data);
2486 static bool test_Forms(struct torture_context *tctx,
2487 struct dcerpc_binding_handle *b,
2488 struct policy_handle *handle,
2489 bool print_server,
2490 const char *printer_name,
2491 struct dcerpc_binding_handle *winreg_handle,
2492 struct policy_handle *hive_handle)
2494 union spoolss_FormInfo info;
2495 const char *form_name = "testform3";
2497 union spoolss_AddFormInfo add_info;
2498 struct spoolss_AddFormInfo1 info1;
2500 enum winreg_Type w_type;
2501 uint32_t w_size;
2502 uint32_t w_length;
2503 uint8_t *w_data;
2505 info1.flags = SPOOLSS_FORM_USER;
2506 info1.form_name = form_name;
2507 info1.size.width = 50;
2508 info1.size.height = 25;
2509 info1.area.left = 5;
2510 info1.area.top = 10;
2511 info1.area.right = 45;
2512 info1.area.bottom = 15;
2514 add_info.info1 = &info1;
2516 torture_assert(tctx,
2517 test_AddForm(tctx, b, handle, 1, &add_info),
2518 "failed to add form");
2520 if (winreg_handle && hive_handle) {
2522 torture_assert(tctx,
2523 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2524 "failed to get form via winreg");
2526 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2527 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2528 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2529 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2530 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2531 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2532 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2533 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2534 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2535 /* skip index here */
2536 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2539 if (!print_server) {
2540 torture_assert(tctx,
2541 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2542 "failed to get added form");
2544 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2545 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2546 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2547 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2548 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2549 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2550 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2552 if (winreg_handle && hive_handle) {
2553 torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2554 torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2555 torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2556 torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2557 torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2558 torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2559 /* skip index here */
2560 torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2563 add_info.info1->size.width = 1234;
2565 torture_assert(tctx,
2566 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2567 "failed to set form");
2568 torture_assert(tctx,
2569 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2570 "failed to get setted form");
2572 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2575 torture_assert(tctx,
2576 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2577 "Newly added form not found in enum call");
2579 torture_assert(tctx,
2580 test_DeleteForm(tctx, b, handle, form_name),
2581 "failed to delete form");
2583 return true;
2586 static bool test_EnumPorts_old(struct torture_context *tctx,
2587 struct dcerpc_pipe *p)
2589 NTSTATUS status;
2590 struct spoolss_EnumPorts r;
2591 uint32_t needed;
2592 uint32_t count;
2593 union spoolss_PortInfo *info;
2594 struct dcerpc_binding_handle *b = p->binding_handle;
2596 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2597 dcerpc_server_name(p));
2598 r.in.level = 2;
2599 r.in.buffer = NULL;
2600 r.in.offered = 0;
2601 r.out.needed = &needed;
2602 r.out.count = &count;
2603 r.out.info = &info;
2605 torture_comment(tctx, "Testing EnumPorts\n");
2607 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2609 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2611 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2612 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2613 data_blob_clear(&blob);
2614 r.in.buffer = &blob;
2615 r.in.offered = needed;
2617 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2618 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2619 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2621 torture_assert(tctx, info, "No ports returned");
2624 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2626 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2628 return true;
2631 static bool test_AddPort(struct torture_context *tctx,
2632 struct dcerpc_pipe *p)
2634 NTSTATUS status;
2635 struct spoolss_AddPort r;
2636 struct dcerpc_binding_handle *b = p->binding_handle;
2638 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2639 dcerpc_server_name(p));
2640 r.in.unknown = 0;
2641 r.in.monitor_name = "foo";
2643 torture_comment(tctx, "Testing AddPort\n");
2645 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2647 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2649 /* win2k3 returns WERR_NOT_SUPPORTED */
2651 #if 0
2653 if (!W_ERROR_IS_OK(r.out.result)) {
2654 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2655 return false;
2658 #endif
2660 return true;
2663 static bool test_GetJob_args(struct torture_context *tctx,
2664 struct dcerpc_binding_handle *b,
2665 struct policy_handle *handle,
2666 uint32_t job_id,
2667 uint32_t level,
2668 union spoolss_JobInfo *info_p)
2670 NTSTATUS status;
2671 struct spoolss_GetJob r;
2672 union spoolss_JobInfo info;
2673 uint32_t needed;
2675 r.in.handle = handle;
2676 r.in.job_id = job_id;
2677 r.in.level = level;
2678 r.in.buffer = NULL;
2679 r.in.offered = 0;
2680 r.out.needed = &needed;
2681 r.out.info = &info;
2683 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2685 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2686 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2687 if (level == 0) {
2688 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2691 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2692 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2693 data_blob_clear(&blob);
2694 r.in.buffer = &blob;
2695 r.in.offered = needed;
2697 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2698 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2699 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2700 torture_assert(tctx, r.out.info, "No job info returned");
2702 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2705 if (info_p) {
2706 *info_p = *r.out.info;
2709 return true;
2712 static bool test_GetJob(struct torture_context *tctx,
2713 struct dcerpc_binding_handle *b,
2714 struct policy_handle *handle,
2715 uint32_t job_id)
2717 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
2718 uint32_t i;
2720 for (i=0; i < ARRAY_SIZE(levels); i++) {
2721 torture_assert(tctx,
2722 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
2723 "GetJob failed");
2726 return true;
2729 static bool test_SetJob(struct torture_context *tctx,
2730 struct dcerpc_binding_handle *b,
2731 struct policy_handle *handle, uint32_t job_id,
2732 enum spoolss_JobControl command)
2734 NTSTATUS status;
2735 struct spoolss_SetJob r;
2737 r.in.handle = handle;
2738 r.in.job_id = job_id;
2739 r.in.ctr = NULL;
2740 r.in.command = command;
2742 switch (command) {
2743 case SPOOLSS_JOB_CONTROL_PAUSE:
2744 torture_comment(tctx, "Testing SetJob(%d) SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
2745 break;
2746 case SPOOLSS_JOB_CONTROL_RESUME:
2747 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
2748 break;
2749 case SPOOLSS_JOB_CONTROL_CANCEL:
2750 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
2751 break;
2752 case SPOOLSS_JOB_CONTROL_RESTART:
2753 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
2754 break;
2755 case SPOOLSS_JOB_CONTROL_DELETE:
2756 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
2757 break;
2758 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2759 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
2760 break;
2761 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2762 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
2763 break;
2764 case SPOOLSS_JOB_CONTROL_RETAIN:
2765 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
2766 break;
2767 case SPOOLSS_JOB_CONTROL_RELEASE:
2768 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
2769 break;
2770 default:
2771 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
2772 break;
2775 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
2776 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2777 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2779 return true;
2782 static bool test_AddJob(struct torture_context *tctx,
2783 struct dcerpc_binding_handle *b,
2784 struct policy_handle *handle)
2786 NTSTATUS status;
2787 struct spoolss_AddJob r;
2788 uint32_t needed;
2790 r.in.level = 0;
2791 r.in.handle = handle;
2792 r.in.offered = 0;
2793 r.out.needed = &needed;
2794 r.in.buffer = r.out.buffer = NULL;
2796 torture_comment(tctx, "Testing AddJob\n");
2798 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
2799 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2801 r.in.level = 1;
2803 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
2804 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2806 return true;
2810 static bool test_EnumJobs_args(struct torture_context *tctx,
2811 struct dcerpc_binding_handle *b,
2812 struct policy_handle *handle,
2813 uint32_t level,
2814 uint32_t *count_p,
2815 union spoolss_JobInfo **info_p)
2817 NTSTATUS status;
2818 struct spoolss_EnumJobs r;
2819 uint32_t needed;
2820 uint32_t count;
2821 union spoolss_JobInfo *info;
2823 r.in.handle = handle;
2824 r.in.firstjob = 0;
2825 r.in.numjobs = 0xffffffff;
2826 r.in.level = level;
2827 r.in.buffer = NULL;
2828 r.in.offered = 0;
2829 r.out.needed = &needed;
2830 r.out.count = &count;
2831 r.out.info = &info;
2833 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
2835 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
2837 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2839 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2840 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2841 data_blob_clear(&blob);
2842 r.in.buffer = &blob;
2843 r.in.offered = needed;
2845 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
2847 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2848 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2849 torture_assert(tctx, info, "No jobs returned");
2851 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2853 } else {
2854 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2857 if (count_p) {
2858 *count_p = count;
2860 if (info_p) {
2861 *info_p = info;
2864 return true;
2867 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
2868 struct dcerpc_binding_handle *b,
2869 struct policy_handle *handle,
2870 uint32_t *job_id)
2872 NTSTATUS status;
2873 struct spoolss_StartDocPrinter s;
2874 struct spoolss_DocumentInfo1 info1;
2875 struct spoolss_StartPagePrinter sp;
2876 struct spoolss_WritePrinter w;
2877 struct spoolss_EndPagePrinter ep;
2878 struct spoolss_EndDocPrinter e;
2879 int i;
2880 uint32_t num_written;
2882 torture_comment(tctx, "Testing StartDocPrinter\n");
2884 s.in.handle = handle;
2885 s.in.level = 1;
2886 s.in.info.info1 = &info1;
2887 s.out.job_id = job_id;
2888 info1.document_name = "TorturePrintJob";
2889 info1.output_file = NULL;
2890 info1.datatype = "RAW";
2892 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
2893 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2894 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2896 for (i=1; i < 4; i++) {
2897 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2899 sp.in.handle = handle;
2901 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
2902 torture_assert_ntstatus_ok(tctx, status,
2903 "dcerpc_spoolss_StartPagePrinter failed");
2904 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2906 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2908 w.in.handle = handle;
2909 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2910 w.out.num_written = &num_written;
2912 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
2913 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2914 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2916 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2918 ep.in.handle = handle;
2920 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
2921 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2922 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2925 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
2927 e.in.handle = handle;
2929 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
2930 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2931 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2933 return true;
2936 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
2937 struct dcerpc_binding_handle *b,
2938 struct policy_handle *handle,
2939 uint32_t num_jobs,
2940 uint32_t *job_ids)
2942 uint32_t count;
2943 union spoolss_JobInfo *info = NULL;
2944 int i;
2946 torture_assert(tctx,
2947 test_AddJob(tctx, b, handle),
2948 "AddJob failed");
2950 torture_assert(tctx,
2951 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
2952 "EnumJobs level 1 failed");
2954 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
2956 for (i=0; i < num_jobs; i++) {
2957 union spoolss_JobInfo ginfo;
2959 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
2961 torture_assert(tctx,
2962 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
2963 "failed to call test_GetJob");
2965 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
2968 for (i=0; i < num_jobs; i++) {
2969 torture_assert(tctx,
2970 test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE),
2971 "failed to pause printjob");
2972 torture_assert(tctx,
2973 test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME),
2974 "failed to resume printjob");
2977 return true;
2980 static bool test_DoPrintTest(struct torture_context *tctx,
2981 struct dcerpc_binding_handle *b,
2982 struct policy_handle *handle)
2984 bool ret = true;
2985 uint32_t num_jobs = 8;
2986 uint32_t *job_ids;
2987 int i;
2989 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
2991 for (i=0; i < num_jobs; i++) {
2992 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
2995 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
2997 for (i=0; i < num_jobs; i++) {
2998 ret &= test_SetJob(tctx, b, handle, job_ids[i], SPOOLSS_JOB_CONTROL_DELETE);
3001 return ret;
3004 static bool test_PausePrinter(struct torture_context *tctx,
3005 struct dcerpc_binding_handle *b,
3006 struct policy_handle *handle)
3008 NTSTATUS status;
3009 struct spoolss_SetPrinter r;
3010 struct spoolss_SetPrinterInfoCtr info_ctr;
3011 struct spoolss_DevmodeContainer devmode_ctr;
3012 struct sec_desc_buf secdesc_ctr;
3014 info_ctr.level = 0;
3015 info_ctr.info.info0 = NULL;
3017 ZERO_STRUCT(devmode_ctr);
3018 ZERO_STRUCT(secdesc_ctr);
3020 r.in.handle = handle;
3021 r.in.info_ctr = &info_ctr;
3022 r.in.devmode_ctr = &devmode_ctr;
3023 r.in.secdesc_ctr = &secdesc_ctr;
3024 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3026 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3028 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3030 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3032 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3034 return true;
3037 static bool test_ResumePrinter(struct torture_context *tctx,
3038 struct dcerpc_binding_handle *b,
3039 struct policy_handle *handle)
3041 NTSTATUS status;
3042 struct spoolss_SetPrinter r;
3043 struct spoolss_SetPrinterInfoCtr info_ctr;
3044 struct spoolss_DevmodeContainer devmode_ctr;
3045 struct sec_desc_buf secdesc_ctr;
3047 info_ctr.level = 0;
3048 info_ctr.info.info0 = NULL;
3050 ZERO_STRUCT(devmode_ctr);
3051 ZERO_STRUCT(secdesc_ctr);
3053 r.in.handle = handle;
3054 r.in.info_ctr = &info_ctr;
3055 r.in.devmode_ctr = &devmode_ctr;
3056 r.in.secdesc_ctr = &secdesc_ctr;
3057 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3059 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3061 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3063 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3065 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3067 return true;
3070 static bool test_GetPrinterData(struct torture_context *tctx,
3071 struct dcerpc_binding_handle *b,
3072 struct policy_handle *handle,
3073 const char *value_name,
3074 enum winreg_Type *type_p,
3075 uint8_t **data_p,
3076 uint32_t *needed_p)
3078 NTSTATUS status;
3079 struct spoolss_GetPrinterData r;
3080 uint32_t needed;
3081 enum winreg_Type type;
3082 union spoolss_PrinterData data;
3084 r.in.handle = handle;
3085 r.in.value_name = value_name;
3086 r.in.offered = 0;
3087 r.out.needed = &needed;
3088 r.out.type = &type;
3089 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3091 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3093 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3094 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3096 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3097 r.in.offered = needed;
3098 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3099 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3100 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3103 torture_assert_werr_ok(tctx, r.out.result,
3104 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3106 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3108 if (type_p) {
3109 *type_p = type;
3112 if (data_p) {
3113 *data_p = r.out.data;
3116 if (needed_p) {
3117 *needed_p = needed;
3120 return true;
3123 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3124 struct dcerpc_pipe *p,
3125 struct policy_handle *handle,
3126 const char *key_name,
3127 const char *value_name,
3128 enum winreg_Type *type_p,
3129 uint8_t **data_p,
3130 uint32_t *needed_p)
3132 NTSTATUS status;
3133 struct spoolss_GetPrinterDataEx r;
3134 enum winreg_Type type;
3135 uint32_t needed;
3136 union spoolss_PrinterData data;
3137 struct dcerpc_binding_handle *b = p->binding_handle;
3139 r.in.handle = handle;
3140 r.in.key_name = key_name;
3141 r.in.value_name = value_name;
3142 r.in.offered = 0;
3143 r.out.type = &type;
3144 r.out.needed = &needed;
3145 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3147 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3148 r.in.key_name, r.in.value_name);
3150 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3151 if (!NT_STATUS_IS_OK(status)) {
3152 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
3153 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
3154 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3156 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3159 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3160 r.in.offered = needed;
3161 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3162 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3163 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3166 torture_assert_werr_ok(tctx, r.out.result,
3167 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3169 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3171 if (type_p) {
3172 *type_p = type;
3175 if (data_p) {
3176 *data_p = r.out.data;
3179 if (needed_p) {
3180 *needed_p = needed;
3183 return true;
3186 static bool test_GetPrinterData_list(struct torture_context *tctx,
3187 struct dcerpc_pipe *p,
3188 struct policy_handle *handle,
3189 const char **architecture)
3191 struct dcerpc_binding_handle *b = p->binding_handle;
3192 const char *list[] = {
3193 "W3SvcInstalled",
3194 "BeepEnabled",
3195 "EventLog",
3196 /* "NetPopup", not on w2k8 */
3197 /* "NetPopupToComputer", not on w2k8 */
3198 "MajorVersion",
3199 "MinorVersion",
3200 "DefaultSpoolDirectory",
3201 "Architecture",
3202 "DsPresent",
3203 "OSVersion",
3204 /* "OSVersionEx", not on s3 */
3205 "DNSMachineName"
3207 int i;
3209 for (i=0; i < ARRAY_SIZE(list); i++) {
3210 enum winreg_Type type, type_ex;
3211 uint8_t *data, *data_ex;
3212 uint32_t needed, needed_ex;
3214 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3215 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3216 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3217 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3218 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3219 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3220 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3222 if (strequal(list[i], "Architecture")) {
3223 if (architecture) {
3224 DATA_BLOB blob = data_blob_const(data, needed);
3225 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3230 return true;
3233 static bool test_EnumPrinterData(struct torture_context *tctx,
3234 struct dcerpc_pipe *p,
3235 struct policy_handle *handle,
3236 uint32_t enum_index,
3237 uint32_t value_offered,
3238 uint32_t data_offered,
3239 enum winreg_Type *type_p,
3240 uint32_t *value_needed_p,
3241 uint32_t *data_needed_p,
3242 const char **value_name_p,
3243 uint8_t **data_p,
3244 WERROR *result_p)
3246 struct spoolss_EnumPrinterData r;
3247 uint32_t data_needed;
3248 uint32_t value_needed;
3249 enum winreg_Type type;
3250 struct dcerpc_binding_handle *b = p->binding_handle;
3252 r.in.handle = handle;
3253 r.in.enum_index = enum_index;
3254 r.in.value_offered = value_offered;
3255 r.in.data_offered = data_offered;
3256 r.out.data_needed = &data_needed;
3257 r.out.value_needed = &value_needed;
3258 r.out.type = &type;
3259 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3260 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3262 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3264 torture_assert_ntstatus_ok(tctx,
3265 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3266 "EnumPrinterData failed");
3268 if (type_p) {
3269 *type_p = type;
3271 if (value_needed_p) {
3272 *value_needed_p = value_needed;
3274 if (data_needed_p) {
3275 *data_needed_p = data_needed;
3277 if (value_name_p) {
3278 *value_name_p = r.out.value_name;
3280 if (data_p) {
3281 *data_p = r.out.data;
3283 if (result_p) {
3284 *result_p = r.out.result;
3287 return true;
3291 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3292 struct dcerpc_pipe *p,
3293 struct policy_handle *handle)
3295 uint32_t enum_index = 0;
3296 enum winreg_Type type;
3297 uint32_t value_needed;
3298 uint32_t data_needed;
3299 uint8_t *data;
3300 const char *value_name;
3301 WERROR result;
3303 torture_comment(tctx, "Testing EnumPrinterData\n");
3305 do {
3306 torture_assert(tctx,
3307 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3308 &type, &value_needed, &data_needed,
3309 &value_name, &data, &result),
3310 "EnumPrinterData failed");
3312 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3313 break;
3316 torture_assert(tctx,
3317 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3318 &type, &value_needed, &data_needed,
3319 &value_name, &data, &result),
3320 "EnumPrinterData failed");
3322 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3323 break;
3326 enum_index++;
3328 } while (W_ERROR_IS_OK(result));
3330 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3332 return true;
3335 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3336 struct dcerpc_binding_handle *b,
3337 struct policy_handle *handle,
3338 const char *key_name,
3339 uint32_t *count_p,
3340 struct spoolss_PrinterEnumValues **info_p)
3342 struct spoolss_EnumPrinterDataEx r;
3343 struct spoolss_PrinterEnumValues *info;
3344 uint32_t needed;
3345 uint32_t count;
3347 r.in.handle = handle;
3348 r.in.key_name = key_name;
3349 r.in.offered = 0;
3350 r.out.needed = &needed;
3351 r.out.count = &count;
3352 r.out.info = &info;
3354 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3356 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3357 "EnumPrinterDataEx failed");
3358 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3359 r.in.offered = needed;
3360 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3361 "EnumPrinterDataEx failed");
3364 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3366 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3368 if (count_p) {
3369 *count_p = count;
3371 if (info_p) {
3372 *info_p = info;
3375 return true;
3378 static bool test_SetPrinterData(struct torture_context *tctx,
3379 struct dcerpc_binding_handle *b,
3380 struct policy_handle *handle,
3381 const char *value_name,
3382 enum winreg_Type type,
3383 uint8_t *data,
3384 uint32_t offered);
3385 static bool test_DeletePrinterData(struct torture_context *tctx,
3386 struct dcerpc_binding_handle *b,
3387 struct policy_handle *handle,
3388 const char *value_name);
3390 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3391 struct dcerpc_pipe *p,
3392 struct policy_handle *handle)
3394 uint32_t count;
3395 struct spoolss_PrinterEnumValues *info;
3396 int i;
3397 uint32_t value_needed, data_needed;
3398 uint32_t value_offered, data_offered;
3399 WERROR result;
3400 struct dcerpc_binding_handle *b = p->binding_handle;
3402 enum winreg_Type type;
3403 DATA_BLOB blob;
3405 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3407 torture_assert(tctx,
3408 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3409 "REG_SZ", "torture_data1", &type, &blob), "");
3411 torture_assert(tctx,
3412 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3413 "SetPrinterData failed");
3415 blob = data_blob_string_const("torture_data2");
3417 torture_assert(tctx,
3418 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3419 "SetPrinterData failed");
3421 blob = data_blob_talloc(tctx, NULL, 4);
3422 SIVAL(blob.data, 0, 0x11223344);
3424 torture_assert(tctx,
3425 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3426 "SetPrinterData failed");
3428 torture_assert(tctx,
3429 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3430 "failed to call EnumPrinterDataEx");
3432 /* get the max sizes for value and data */
3434 torture_assert(tctx,
3435 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3436 NULL, &value_needed, &data_needed,
3437 NULL, NULL, &result),
3438 "EnumPrinterData failed");
3439 torture_assert_werr_ok(tctx, result, "unexpected result");
3441 /* check if the reply from the EnumPrinterData really matches max values */
3443 for (i=0; i < count; i++) {
3444 if (info[i].value_name_len > value_needed) {
3445 torture_fail(tctx,
3446 talloc_asprintf(tctx,
3447 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3448 info[i].value_name_len, value_needed));
3450 if (info[i].data_length > data_needed) {
3451 torture_fail(tctx,
3452 talloc_asprintf(tctx,
3453 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3454 info[i].data_length, data_needed));
3458 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3459 * sort or not sort the replies by value name, we should be able to do
3460 * the following entry comparison */
3462 data_offered = data_needed;
3463 value_offered = value_needed;
3465 for (i=0; i < count; i++) {
3467 const char *value_name;
3468 uint8_t *data;
3470 torture_assert(tctx,
3471 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3472 &type, &value_needed, &data_needed,
3473 &value_name, &data, &result),
3474 "EnumPrinterData failed");
3476 if (i -1 == count) {
3477 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3478 "unexpected result");
3479 break;
3480 } else {
3481 torture_assert_werr_ok(tctx, result, "unexpected result");
3484 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3485 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3486 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3487 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3488 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3491 torture_assert(tctx,
3492 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3493 "DeletePrinterData failed");
3494 torture_assert(tctx,
3495 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3496 "DeletePrinterData failed");
3497 torture_assert(tctx,
3498 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3499 "DeletePrinterData failed");
3501 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3503 return true;
3506 static bool test_DeletePrinterData(struct torture_context *tctx,
3507 struct dcerpc_binding_handle *b,
3508 struct policy_handle *handle,
3509 const char *value_name)
3511 NTSTATUS status;
3512 struct spoolss_DeletePrinterData r;
3514 r.in.handle = handle;
3515 r.in.value_name = value_name;
3517 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3518 r.in.value_name);
3520 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3522 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3523 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3525 return true;
3528 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3529 struct dcerpc_binding_handle *b,
3530 struct policy_handle *handle,
3531 const char *key_name,
3532 const char *value_name)
3534 struct spoolss_DeletePrinterDataEx r;
3536 r.in.handle = handle;
3537 r.in.key_name = key_name;
3538 r.in.value_name = value_name;
3540 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3541 r.in.key_name, r.in.value_name);
3543 torture_assert_ntstatus_ok(tctx,
3544 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3545 "DeletePrinterDataEx failed");
3546 torture_assert_werr_ok(tctx, r.out.result,
3547 "DeletePrinterDataEx failed");
3549 return true;
3552 static bool test_DeletePrinterKey(struct torture_context *tctx,
3553 struct dcerpc_binding_handle *b,
3554 struct policy_handle *handle,
3555 const char *key_name)
3557 struct spoolss_DeletePrinterKey r;
3559 r.in.handle = handle;
3560 r.in.key_name = key_name;
3562 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3564 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3565 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3566 return true;
3569 torture_assert_ntstatus_ok(tctx,
3570 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3571 "DeletePrinterKey failed");
3572 torture_assert_werr_ok(tctx, r.out.result,
3573 "DeletePrinterKey failed");
3575 return true;
3578 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3579 struct dcerpc_binding_handle *b,
3580 struct policy_handle *handle)
3582 struct winreg_OpenHKLM r;
3584 r.in.system_name = NULL;
3585 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3586 r.out.handle = handle;
3588 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3590 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3591 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3593 return true;
3596 static void init_winreg_String(struct winreg_String *name, const char *s)
3598 name->name = s;
3599 if (s) {
3600 name->name_len = 2 * (strlen_m(s) + 1);
3601 name->name_size = name->name_len;
3602 } else {
3603 name->name_len = 0;
3604 name->name_size = 0;
3608 static bool test_winreg_OpenKey(struct torture_context *tctx,
3609 struct dcerpc_binding_handle *b,
3610 struct policy_handle *hive_handle,
3611 const char *keyname,
3612 struct policy_handle *key_handle)
3614 struct winreg_OpenKey r;
3616 r.in.parent_handle = hive_handle;
3617 init_winreg_String(&r.in.keyname, keyname);
3618 r.in.options = REG_KEYTYPE_NON_VOLATILE;
3619 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3620 r.out.handle = key_handle;
3622 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3624 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3625 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3627 return true;
3630 static bool test_winreg_CloseKey(struct torture_context *tctx,
3631 struct dcerpc_binding_handle *b,
3632 struct policy_handle *handle)
3634 struct winreg_CloseKey r;
3636 r.in.handle = handle;
3637 r.out.handle = handle;
3639 torture_comment(tctx, "Testing winreg_CloseKey\n");
3641 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3642 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3644 return true;
3647 bool test_winreg_QueryValue(struct torture_context *tctx,
3648 struct dcerpc_binding_handle *b,
3649 struct policy_handle *handle,
3650 const char *value_name,
3651 enum winreg_Type *type_p,
3652 uint32_t *data_size_p,
3653 uint32_t *data_length_p,
3654 uint8_t **data_p)
3656 struct winreg_QueryValue r;
3657 enum winreg_Type type = REG_NONE;
3658 uint32_t data_size = 0;
3659 uint32_t data_length = 0;
3660 struct winreg_String valuename;
3661 uint8_t *data = NULL;
3663 init_winreg_String(&valuename, value_name);
3665 data = talloc_zero_array(tctx, uint8_t, 0);
3667 r.in.handle = handle;
3668 r.in.value_name = &valuename;
3669 r.in.type = &type;
3670 r.in.data_size = &data_size;
3671 r.in.data_length = &data_length;
3672 r.in.data = data;
3673 r.out.type = &type;
3674 r.out.data = data;
3675 r.out.data_size = &data_size;
3676 r.out.data_length = &data_length;
3678 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3680 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3681 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3682 *r.in.data_size = *r.out.data_size;
3683 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3684 r.in.data = data;
3685 r.out.data = data;
3686 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3688 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3690 if (type_p) {
3691 *type_p = *r.out.type;
3693 if (data_size_p) {
3694 *data_size_p = *r.out.data_size;
3696 if (data_length_p) {
3697 *data_length_p = *r.out.data_length;
3699 if (data_p) {
3700 *data_p = r.out.data;
3703 return true;
3706 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3707 struct dcerpc_binding_handle *b,
3708 struct policy_handle *handle,
3709 const char *printer_name,
3710 const char *key_name,
3711 const char *value_name,
3712 enum winreg_Type *w_type,
3713 uint32_t *w_size,
3714 uint32_t *w_length,
3715 uint8_t **w_data)
3717 const char *printer_key;
3718 struct policy_handle key_handle;
3720 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3721 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
3723 torture_assert(tctx,
3724 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
3726 torture_assert(tctx,
3727 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3729 torture_assert(tctx,
3730 test_winreg_CloseKey(tctx, b, &key_handle), "");
3732 return true;
3735 static bool test_GetForm_winreg(struct torture_context *tctx,
3736 struct dcerpc_binding_handle *b,
3737 struct policy_handle *handle,
3738 const char *key_name,
3739 const char *form_name,
3740 enum winreg_Type *w_type,
3741 uint32_t *w_size,
3742 uint32_t *w_length,
3743 uint8_t **w_data)
3745 struct policy_handle key_handle;
3747 torture_assert(tctx,
3748 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
3750 torture_assert(tctx,
3751 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
3753 torture_assert(tctx,
3754 test_winreg_CloseKey(tctx, b, &key_handle), "");
3756 return true;
3759 static bool test_SetPrinterData(struct torture_context *tctx,
3760 struct dcerpc_binding_handle *b,
3761 struct policy_handle *handle,
3762 const char *value_name,
3763 enum winreg_Type type,
3764 uint8_t *data,
3765 uint32_t offered)
3767 struct spoolss_SetPrinterData r;
3769 r.in.handle = handle;
3770 r.in.value_name = value_name;
3771 r.in.type = type;
3772 r.in.data = data;
3773 r.in.offered = offered;
3775 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3776 r.in.value_name);
3778 torture_assert_ntstatus_ok(tctx,
3779 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
3780 "SetPrinterData failed");
3781 torture_assert_werr_ok(tctx, r.out.result,
3782 "SetPrinterData failed");
3784 return true;
3787 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
3788 struct dcerpc_binding_handle *b,
3789 struct policy_handle *handle,
3790 const char *printer_name,
3791 struct dcerpc_binding_handle *winreg_handle,
3792 struct policy_handle *hive_handle)
3794 const char *values[] = {
3795 "spootyfoot",
3796 "spooty\\foot",
3797 #if 0
3798 /* FIXME: not working with s3 atm. */
3799 "spooty,foot",
3800 "spooty,fo,ot",
3801 #endif
3802 "spooty foot",
3803 #if 0
3804 /* FIXME: not working with s3 atm. */
3805 "spooty\\fo,ot",
3806 "spooty,fo\\ot"
3807 #endif
3809 int i;
3811 for (i=0; i < ARRAY_SIZE(values); i++) {
3813 enum winreg_Type type;
3814 DATA_BLOB blob;
3815 uint8_t *data;
3816 uint32_t needed;
3818 torture_assert(tctx,
3819 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3820 "REG_SZ", "dog", &type, &blob), "");
3822 torture_assert(tctx,
3823 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
3824 "SetPrinterData failed");
3826 torture_assert(tctx,
3827 test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
3828 "GetPrinterData failed");
3830 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
3831 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
3832 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
3834 if (winreg_handle && hive_handle) {
3836 enum winreg_Type w_type;
3837 uint32_t w_size;
3838 uint32_t w_length;
3839 uint8_t *w_data;
3841 torture_assert(tctx,
3842 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
3843 printer_name, "PrinterDriverData", values[i],
3844 &w_type, &w_size, &w_length, &w_data), "");
3846 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
3847 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
3848 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
3849 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
3852 torture_assert(tctx,
3853 test_DeletePrinterData(tctx, b, handle, values[i]),
3854 "DeletePrinterData failed");
3857 return true;
3861 static bool test_EnumPrinterKey(struct torture_context *tctx,
3862 struct dcerpc_binding_handle *b,
3863 struct policy_handle *handle,
3864 const char *key_name,
3865 const char ***array);
3867 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3868 struct dcerpc_binding_handle *b,
3869 struct policy_handle *handle,
3870 const char *key_name,
3871 const char *value_name,
3872 enum winreg_Type type,
3873 uint8_t *data,
3874 uint32_t offered)
3876 NTSTATUS status;
3877 struct spoolss_SetPrinterDataEx r;
3879 r.in.handle = handle;
3880 r.in.key_name = key_name;
3881 r.in.value_name = value_name;
3882 r.in.type = type;
3883 r.in.data = data;
3884 r.in.offered = offered;
3886 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3887 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3889 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
3891 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3892 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3894 return true;
3897 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3898 struct dcerpc_pipe *p,
3899 struct policy_handle *handle,
3900 const char *printername,
3901 struct dcerpc_binding_handle *winreg_handle,
3902 struct policy_handle *hive_handle)
3904 struct dcerpc_binding_handle *b = p->binding_handle;
3905 const char *value_name = "dog";
3906 const char *keys[] = {
3907 "torturedataex",
3908 "torture data ex",
3909 #if 0
3910 /* FIXME: not working with s3 atm. */
3911 "torturedataex_with_subkey\\subkey",
3912 "torturedataex_with_subkey\\subkey:0",
3913 "torturedataex_with_subkey\\subkey:1",
3914 "torturedataex_with_subkey\\subkey\\subsubkey",
3915 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3916 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3917 #endif
3918 "torture,data",
3919 #if 0
3920 /* FIXME: not working with s3 atm. */
3922 "torture,data,ex",
3923 "torture,data\\ex",
3924 "torture\\data,ex"
3925 #endif
3927 enum winreg_Type types[] = {
3928 REG_SZ,
3929 REG_MULTI_SZ,
3930 REG_DWORD,
3931 REG_BINARY
3933 const char *str = "abcdefghijklmnopqrstuvwxzy";
3934 int i, t, s;
3937 for (i=0; i < ARRAY_SIZE(keys); i++) {
3938 for (t=0; t < ARRAY_SIZE(types); t++) {
3939 for (s=0; s < strlen(str); s++) {
3941 char *c;
3942 const char *key;
3943 enum winreg_Type type;
3944 const char *string = talloc_strndup(tctx, str, s);
3945 DATA_BLOB blob = data_blob_string_const(string);
3946 const char **subkeys;
3947 DATA_BLOB data;
3948 uint8_t *data_out;
3949 uint32_t needed, offered = 0;
3950 uint32_t ecount;
3951 struct spoolss_PrinterEnumValues *einfo;
3953 if (types[t] == REG_DWORD) {
3954 s = 0xffff;
3957 if (torture_setting_bool(tctx, "samba3", false)) {
3958 if ((types[t] == REG_MULTI_SZ) && s == 0) {
3959 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
3960 continue;
3964 switch (types[t]) {
3965 case REG_BINARY:
3966 data = blob;
3967 offered = blob.length;
3968 break;
3969 case REG_DWORD:
3970 data = data_blob_talloc(tctx, NULL, 4);
3971 SIVAL(data.data, 0, 0x12345678);
3972 offered = 4;
3973 break;
3974 case REG_SZ:
3975 torture_assert(tctx,
3976 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3977 "REG_SZ", string, &type, &data), "");
3978 offered = data.length;
3979 /*strlen_m_term(data.string)*2;*/
3980 break;
3981 case REG_MULTI_SZ:
3982 torture_assert(tctx,
3983 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3984 "REG_SZ", string, &type, &data), "");
3985 torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
3986 memset(&data.data[data.length - 2], '\0', 2);
3987 offered = data.length;
3988 break;
3989 default:
3990 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3993 torture_assert(tctx,
3994 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
3995 "failed to call SetPrinterDataEx");
3997 torture_assert(tctx,
3998 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
3999 "failed to call GetPrinterDataEx");
4001 torture_assert(tctx,
4002 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4003 "failed to call EnumPrinterDataEx");
4005 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4006 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4007 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4009 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4010 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4011 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4012 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4013 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4014 if (einfo[0].data_length > 0) {
4015 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4018 if (winreg_handle && hive_handle) {
4019 enum winreg_Type w_type;
4020 uint32_t w_size;
4021 uint32_t w_length;
4022 uint8_t *w_data;
4024 torture_assert(tctx,
4025 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4026 printername, keys[i], value_name,
4027 &w_type, &w_size, &w_length, &w_data), "");
4029 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4030 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4031 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4032 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4035 key = talloc_strdup(tctx, keys[i]);
4037 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4038 return false;
4041 c = strchr(key, '\\');
4042 if (c) {
4043 int k;
4045 /* we have subkeys */
4047 *c = 0;
4049 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4050 return false;
4053 for (k=0; subkeys && subkeys[k]; k++) {
4055 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4057 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4058 return false;
4062 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4063 return false;
4066 } else {
4067 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4068 return false;
4075 return true;
4078 static bool test_PrinterData_winreg(struct torture_context *tctx,
4079 struct dcerpc_pipe *p,
4080 struct policy_handle *handle,
4081 const char *printer_name)
4083 struct dcerpc_binding_handle *b = p->binding_handle;
4084 struct dcerpc_pipe *p2;
4085 bool ret = true;
4086 struct policy_handle hive_handle;
4087 struct dcerpc_binding_handle *b2;
4089 torture_assert_ntstatus_ok(tctx,
4090 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4091 "could not open winreg pipe");
4092 b2 = p2->binding_handle;
4094 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4096 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4097 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4099 test_winreg_CloseKey(tctx, b2, &hive_handle);
4101 talloc_free(p2);
4103 return ret;
4106 static bool test_Forms_winreg(struct torture_context *tctx,
4107 struct dcerpc_binding_handle *b,
4108 struct policy_handle *handle,
4109 bool print_server,
4110 const char *printer_name)
4112 struct dcerpc_pipe *p2;
4113 bool ret = true;
4114 struct policy_handle hive_handle;
4115 struct dcerpc_binding_handle *b2;
4117 torture_assert_ntstatus_ok(tctx,
4118 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4119 "could not open winreg pipe");
4120 b2 = p2->binding_handle;
4122 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4124 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4126 test_winreg_CloseKey(tctx, b2, &hive_handle);
4128 talloc_free(p2);
4130 return ret;
4133 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
4134 struct dcerpc_binding_handle *b,
4135 struct policy_handle *handle,
4136 uint32_t *change_id)
4138 enum winreg_Type type;
4139 uint8_t *data;
4140 uint32_t needed;
4142 torture_assert(tctx,
4143 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
4144 "failed to call GetPrinterData");
4146 torture_assert(tctx, type == REG_DWORD, "unexpected type");
4147 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4149 *change_id = IVAL(data, 0);
4151 return true;
4154 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
4155 struct dcerpc_pipe *p,
4156 struct policy_handle *handle,
4157 uint32_t *change_id)
4159 enum winreg_Type type;
4160 uint8_t *data;
4161 uint32_t needed;
4163 torture_assert(tctx,
4164 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
4165 "failed to call GetPrinterData");
4167 torture_assert(tctx, type == REG_DWORD, "unexpected type");
4168 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4170 *change_id = IVAL(data, 0);
4172 return true;
4175 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
4176 struct dcerpc_binding_handle *b,
4177 struct policy_handle *handle,
4178 uint32_t *change_id)
4180 union spoolss_PrinterInfo info;
4182 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
4183 "failed to query Printer level 0");
4185 *change_id = info.info0.change_id;
4187 return true;
4190 static bool test_ChangeID(struct torture_context *tctx,
4191 struct dcerpc_pipe *p,
4192 struct policy_handle *handle)
4194 uint32_t change_id, change_id_ex, change_id_info;
4195 uint32_t change_id2, change_id_ex2, change_id_info2;
4196 union spoolss_PrinterInfo info;
4197 const char *comment;
4198 struct dcerpc_binding_handle *b = p->binding_handle;
4200 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
4202 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4203 "failed to query for ChangeID");
4204 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4205 "failed to query for ChangeID");
4206 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4207 "failed to query for ChangeID");
4209 torture_assert_int_equal(tctx, change_id, change_id_ex,
4210 "change_ids should all be equal");
4211 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4212 "change_ids should all be equal");
4215 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
4217 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4218 "failed to query for ChangeID");
4219 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4220 "failed to query Printer level 2");
4221 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4222 "failed to query for ChangeID");
4223 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4224 "failed to query for ChangeID");
4225 torture_assert_int_equal(tctx, change_id, change_id_ex,
4226 "change_id should not have changed");
4227 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4228 "change_id should not have changed");
4231 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
4233 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4234 "failed to query for ChangeID");
4235 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4236 "failed to query for ChangeID");
4237 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4238 "failed to query for ChangeID");
4239 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4240 "failed to query Printer level 2");
4241 comment = talloc_strdup(tctx, info.info2.comment);
4244 struct spoolss_SetPrinterInfoCtr info_ctr;
4245 struct spoolss_DevmodeContainer devmode_ctr;
4246 struct sec_desc_buf secdesc_ctr;
4247 union spoolss_SetPrinterInfo sinfo;
4249 ZERO_STRUCT(info_ctr);
4250 ZERO_STRUCT(devmode_ctr);
4251 ZERO_STRUCT(secdesc_ctr);
4254 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4255 sinfo.info2->comment = "torture_comment";
4257 info_ctr.level = 2;
4258 info_ctr.info = sinfo;
4260 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4261 "failed to call SetPrinter");
4263 sinfo.info2->comment = comment;
4265 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4266 "failed to call SetPrinter");
4270 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
4271 "failed to query for ChangeID");
4272 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
4273 "failed to query for ChangeID");
4274 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
4275 "failed to query for ChangeID");
4277 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
4278 "change_ids should all be equal");
4279 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
4280 "change_ids should all be equal");
4282 torture_assert(tctx, (change_id < change_id2),
4283 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4284 change_id2, change_id));
4285 torture_assert(tctx, (change_id_ex < change_id_ex2),
4286 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4287 change_id_ex2, change_id_ex));
4288 torture_assert(tctx, (change_id_info < change_id_info2),
4289 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4290 change_id_info2, change_id_info));
4292 torture_comment(tctx, "ChangeID tests succeeded\n\n");
4294 return true;
4297 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
4298 struct dcerpc_pipe *p,
4299 struct policy_handle *handle)
4301 NTSTATUS status;
4302 struct dcerpc_binding *b;
4303 struct dcerpc_pipe *p2;
4304 struct spoolss_ClosePrinter cp;
4306 /* only makes sense on SMB */
4307 if (p->conn->transport.transport != NCACN_NP) {
4308 return true;
4311 torture_comment(tctx, "testing close on secondary pipe\n");
4313 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
4314 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
4316 status = dcerpc_secondary_connection(p, &p2, b);
4317 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
4319 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
4320 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
4322 cp.in.handle = handle;
4323 cp.out.handle = handle;
4325 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
4326 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
4327 "ERROR: Allowed close on secondary connection");
4329 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
4330 "Unexpected fault code");
4332 talloc_free(p2);
4334 return true;
4337 static bool test_OpenPrinter_badname(struct torture_context *tctx,
4338 struct dcerpc_binding_handle *b, const char *name)
4340 NTSTATUS status;
4341 struct spoolss_OpenPrinter op;
4342 struct spoolss_OpenPrinterEx opEx;
4343 struct policy_handle handle;
4344 bool ret = true;
4346 op.in.printername = name;
4347 op.in.datatype = NULL;
4348 op.in.devmode_ctr.devmode= NULL;
4349 op.in.access_mask = 0;
4350 op.out.handle = &handle;
4352 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
4354 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
4355 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4356 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
4357 "unexpected result");
4359 if (W_ERROR_IS_OK(op.out.result)) {
4360 ret &=test_ClosePrinter(tctx, b, &handle);
4363 opEx.in.printername = name;
4364 opEx.in.datatype = NULL;
4365 opEx.in.devmode_ctr.devmode = NULL;
4366 opEx.in.access_mask = 0;
4367 opEx.in.level = 1;
4368 opEx.in.userlevel.level1 = NULL;
4369 opEx.out.handle = &handle;
4371 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4373 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
4374 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4375 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
4376 "unexpected result");
4378 if (W_ERROR_IS_OK(opEx.out.result)) {
4379 ret &=test_ClosePrinter(tctx, b, &handle);
4382 return ret;
4385 static bool test_OpenPrinter(struct torture_context *tctx,
4386 struct dcerpc_pipe *p,
4387 const char *name,
4388 const char *environment)
4390 NTSTATUS status;
4391 struct spoolss_OpenPrinter r;
4392 struct policy_handle handle;
4393 bool ret = true;
4394 struct dcerpc_binding_handle *b = p->binding_handle;
4396 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4397 r.in.datatype = NULL;
4398 r.in.devmode_ctr.devmode= NULL;
4399 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4400 r.out.handle = &handle;
4402 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4404 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
4406 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4408 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4410 if (!test_GetPrinter(tctx, b, &handle, environment)) {
4411 ret = false;
4414 if (!torture_setting_bool(tctx, "samba3", false)) {
4415 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4416 ret = false;
4420 if (!test_ClosePrinter(tctx, b, &handle)) {
4421 ret = false;
4424 return ret;
4427 static bool call_OpenPrinterEx(struct torture_context *tctx,
4428 struct dcerpc_pipe *p,
4429 const char *name,
4430 struct spoolss_DeviceMode *devmode,
4431 struct policy_handle *handle)
4433 struct spoolss_OpenPrinterEx r;
4434 struct spoolss_UserLevel1 userlevel1;
4435 NTSTATUS status;
4436 struct dcerpc_binding_handle *b = p->binding_handle;
4438 if (name && name[0]) {
4439 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4440 dcerpc_server_name(p), name);
4441 } else {
4442 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4443 dcerpc_server_name(p));
4446 r.in.datatype = NULL;
4447 r.in.devmode_ctr.devmode= devmode;
4448 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4449 r.in.level = 1;
4450 r.in.userlevel.level1 = &userlevel1;
4451 r.out.handle = handle;
4453 userlevel1.size = 1234;
4454 userlevel1.client = "hello";
4455 userlevel1.user = "spottyfoot!";
4456 userlevel1.build = 1;
4457 userlevel1.major = 2;
4458 userlevel1.minor = 3;
4459 userlevel1.processor = 4;
4461 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4463 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
4465 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4467 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4469 return true;
4472 static bool test_printer_rename(struct torture_context *tctx,
4473 struct dcerpc_pipe *p,
4474 struct policy_handle *handle,
4475 const char *name)
4477 bool ret = true;
4478 union spoolss_PrinterInfo info;
4479 union spoolss_SetPrinterInfo sinfo;
4480 struct spoolss_SetPrinterInfoCtr info_ctr;
4481 struct spoolss_DevmodeContainer devmode_ctr;
4482 struct sec_desc_buf secdesc_ctr;
4483 const char *printer_name;
4484 const char *printer_name_orig;
4485 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4486 struct policy_handle new_handle;
4487 const char *q;
4488 struct dcerpc_binding_handle *b = p->binding_handle;
4490 ZERO_STRUCT(devmode_ctr);
4491 ZERO_STRUCT(secdesc_ctr);
4493 torture_comment(tctx, "Testing Printer rename operations\n");
4495 torture_assert(tctx,
4496 test_GetPrinter_level(tctx, b, handle, 2, &info),
4497 "failed to call GetPrinter level 2");
4499 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4501 q = strrchr(info.info2.printername, '\\');
4502 if (q) {
4503 torture_warning(tctx,
4504 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4507 torture_assert(tctx,
4508 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4510 sinfo.info2->printername = printer_name_new;
4512 info_ctr.level = 2;
4513 info_ctr.info = sinfo;
4515 torture_assert(tctx,
4516 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4517 "failed to call SetPrinter level 2");
4519 torture_assert(tctx,
4520 test_GetPrinter_level(tctx, b, handle, 2, &info),
4521 "failed to call GetPrinter level 2");
4523 printer_name = talloc_strdup(tctx, info.info2.printername);
4525 q = strrchr(info.info2.printername, '\\');
4526 if (q) {
4527 torture_warning(tctx,
4528 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4529 q++;
4530 printer_name = q;
4533 torture_assert_str_equal(tctx, printer_name, printer_name_new,
4534 "new printer name was not set");
4536 /* samba currently cannot fully rename printers */
4537 if (!torture_setting_bool(tctx, "samba3", false)) {
4538 torture_assert(tctx,
4539 test_OpenPrinter_badname(tctx, b, printer_name_orig),
4540 "still can open printer with oldname after rename");
4541 } else {
4542 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
4545 torture_assert(tctx,
4546 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4547 "failed to open printer with new name");
4549 torture_assert(tctx,
4550 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
4551 "failed to call GetPrinter level 2");
4553 /* FIXME: we openend with servername! */
4554 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4555 dcerpc_server_name(p), printer_name_new);
4557 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4558 "new printer name was not set");
4560 torture_assert(tctx,
4561 test_ClosePrinter(tctx, b, &new_handle),
4562 "failed to close printer");
4564 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
4566 return ret;
4570 static bool test_OpenPrinterEx(struct torture_context *tctx,
4571 struct dcerpc_pipe *p,
4572 const char *name,
4573 const char *environment)
4575 struct policy_handle handle;
4576 bool ret = true;
4577 struct dcerpc_binding_handle *b = p->binding_handle;
4579 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4580 return false;
4583 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
4584 ret = false;
4587 if (!test_GetPrinter(tctx, b, &handle, environment)) {
4588 ret = false;
4591 if (!test_EnumForms_all(tctx, b, &handle, false)) {
4592 ret = false;
4595 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
4596 ret = false;
4599 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
4600 ret = false;
4603 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4604 ret = false;
4607 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
4608 ret = false;
4611 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4612 ret = false;
4615 if (!test_printer_keys(tctx, b, &handle)) {
4616 ret = false;
4619 if (!test_PausePrinter(tctx, b, &handle)) {
4620 ret = false;
4623 if (!test_DoPrintTest(tctx, b, &handle)) {
4624 ret = false;
4627 if (!test_ResumePrinter(tctx, b, &handle)) {
4628 ret = false;
4631 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
4632 ret = false;
4635 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4636 ret = false;
4639 if (!torture_setting_bool(tctx, "samba3", false)) {
4640 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4641 ret = false;
4645 if (!test_ClosePrinter(tctx, b, &handle)) {
4646 ret = false;
4649 return ret;
4652 static bool test_EnumPrinters_old(struct torture_context *tctx,
4653 struct dcerpc_pipe *p,
4654 const char *environment)
4656 struct spoolss_EnumPrinters r;
4657 NTSTATUS status;
4658 uint16_t levels[] = {1, 2, 4, 5};
4659 int i;
4660 bool ret = true;
4661 struct dcerpc_binding_handle *b = p->binding_handle;
4663 for (i=0;i<ARRAY_SIZE(levels);i++) {
4664 union spoolss_PrinterInfo *info;
4665 int j;
4666 uint32_t needed;
4667 uint32_t count;
4669 r.in.flags = PRINTER_ENUM_LOCAL;
4670 r.in.server = "";
4671 r.in.level = levels[i];
4672 r.in.buffer = NULL;
4673 r.in.offered = 0;
4674 r.out.needed = &needed;
4675 r.out.count = &count;
4676 r.out.info = &info;
4678 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4680 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
4681 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4683 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4684 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4685 data_blob_clear(&blob);
4686 r.in.buffer = &blob;
4687 r.in.offered = needed;
4688 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
4691 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4693 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4695 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4697 if (!info) {
4698 torture_comment(tctx, "No printers returned\n");
4699 return true;
4702 for (j=0;j<count;j++) {
4703 if (r.in.level == 1) {
4704 char *unc = talloc_strdup(tctx, info[j].info1.name);
4705 char *slash, *name;
4706 name = unc;
4707 if (unc[0] == '\\' && unc[1] == '\\') {
4708 unc +=2;
4710 slash = strchr(unc, '\\');
4711 if (slash) {
4712 slash++;
4713 name = slash;
4715 if (!test_OpenPrinter(tctx, p, name, environment)) {
4716 ret = false;
4718 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4719 ret = false;
4725 return ret;
4728 static bool test_GetPrinterDriver(struct torture_context *tctx,
4729 struct dcerpc_binding_handle *b,
4730 struct policy_handle *handle,
4731 const char *driver_name)
4733 struct spoolss_GetPrinterDriver r;
4734 uint32_t needed;
4736 r.in.handle = handle;
4737 r.in.architecture = "W32X86";
4738 r.in.level = 1;
4739 r.in.buffer = NULL;
4740 r.in.offered = 0;
4741 r.out.needed = &needed;
4743 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4745 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
4746 "failed to call GetPrinterDriver");
4747 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4748 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4749 data_blob_clear(&blob);
4750 r.in.buffer = &blob;
4751 r.in.offered = needed;
4752 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
4753 "failed to call GetPrinterDriver");
4756 torture_assert_werr_ok(tctx, r.out.result,
4757 "failed to call GetPrinterDriver");
4759 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4761 return true;
4764 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4765 struct dcerpc_binding_handle *b,
4766 struct policy_handle *handle,
4767 const char *driver_name,
4768 const char *architecture)
4770 struct spoolss_GetPrinterDriver2 r;
4771 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4772 uint32_t needed;
4773 uint32_t server_major_version;
4774 uint32_t server_minor_version;
4775 int i;
4777 r.in.handle = handle;
4778 r.in.architecture = architecture;
4779 r.in.client_major_version = 3;
4780 r.in.client_minor_version = 0;
4781 r.out.needed = &needed;
4782 r.out.server_major_version = &server_major_version;
4783 r.out.server_minor_version = &server_minor_version;
4785 for (i=0;i<ARRAY_SIZE(levels);i++) {
4787 r.in.buffer = NULL;
4788 r.in.offered = 0;
4789 r.in.level = levels[i];
4791 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4792 driver_name, r.in.level);
4794 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
4795 "failed to call GetPrinterDriver2");
4796 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4797 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4798 data_blob_clear(&blob);
4799 r.in.buffer = &blob;
4800 r.in.offered = needed;
4801 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
4802 "failed to call GetPrinterDriver2");
4805 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4806 switch (r.in.level) {
4807 case 101:
4808 case 8:
4809 continue;
4810 default:
4811 break;
4815 torture_assert_werr_ok(tctx, r.out.result,
4816 "failed to call GetPrinterDriver2");
4818 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4821 return true;
4824 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4825 struct dcerpc_pipe *p,
4826 const char *environment)
4828 struct spoolss_EnumPrinterDrivers r;
4829 NTSTATUS status;
4830 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4831 int i;
4832 struct dcerpc_binding_handle *b = p->binding_handle;
4834 for (i=0;i<ARRAY_SIZE(levels);i++) {
4836 uint32_t needed;
4837 uint32_t count;
4838 union spoolss_DriverInfo *info;
4840 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4841 r.in.environment = environment;
4842 r.in.level = levels[i];
4843 r.in.buffer = NULL;
4844 r.in.offered = 0;
4845 r.out.needed = &needed;
4846 r.out.count = &count;
4847 r.out.info = &info;
4849 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4851 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
4853 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4855 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4856 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4857 data_blob_clear(&blob);
4858 r.in.buffer = &blob;
4859 r.in.offered = needed;
4860 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
4863 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4865 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4867 if (!info) {
4868 torture_comment(tctx, "No printer drivers returned\n");
4869 break;
4872 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4875 return true;
4878 static bool test_DeletePrinter(struct torture_context *tctx,
4879 struct dcerpc_binding_handle *b,
4880 struct policy_handle *handle)
4882 struct spoolss_DeletePrinter r;
4884 torture_comment(tctx, "Testing DeletePrinter\n");
4886 r.in.handle = handle;
4888 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
4889 "failed to delete printer");
4890 torture_assert_werr_ok(tctx, r.out.result,
4891 "failed to delete printer");
4893 return true;
4896 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4897 struct dcerpc_binding_handle *b,
4898 uint32_t flags,
4899 uint32_t level,
4900 const char *name,
4901 bool *found)
4903 struct spoolss_EnumPrinters e;
4904 uint32_t count;
4905 union spoolss_PrinterInfo *info;
4906 uint32_t needed;
4907 int i;
4909 *found = false;
4911 e.in.flags = flags;
4912 e.in.server = NULL;
4913 e.in.level = level;
4914 e.in.buffer = NULL;
4915 e.in.offered = 0;
4916 e.out.count = &count;
4917 e.out.info = &info;
4918 e.out.needed = &needed;
4920 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
4921 "failed to enum printers");
4923 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4924 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4925 data_blob_clear(&blob);
4926 e.in.buffer = &blob;
4927 e.in.offered = needed;
4929 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
4930 "failed to enum printers");
4933 torture_assert_werr_ok(tctx, e.out.result,
4934 "failed to enum printers");
4936 for (i=0; i < count; i++) {
4938 const char *current = NULL;
4939 const char *q;
4941 switch (level) {
4942 case 1:
4943 current = info[i].info1.name;
4944 break;
4947 if (strequal(current, name)) {
4948 *found = true;
4949 break;
4952 q = strrchr(current, '\\');
4953 if (q) {
4954 if (!e.in.server) {
4955 torture_warning(tctx,
4956 "server returns printername %s incl. servername although we did not set servername", current);
4958 q++;
4959 if (strequal(q, name)) {
4960 *found = true;
4961 break;
4966 return true;
4969 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4970 struct dcerpc_pipe *p,
4971 const char *printername,
4972 bool ex)
4974 WERROR result;
4975 struct spoolss_AddPrinter r;
4976 struct spoolss_AddPrinterEx rex;
4977 struct spoolss_SetPrinterInfoCtr info_ctr;
4978 struct spoolss_SetPrinterInfo1 info1;
4979 struct spoolss_DevmodeContainer devmode_ctr;
4980 struct sec_desc_buf secdesc_ctr;
4981 struct spoolss_UserLevelCtr userlevel_ctr;
4982 struct policy_handle handle;
4983 bool found = false;
4984 struct dcerpc_binding_handle *b = p->binding_handle;
4986 ZERO_STRUCT(devmode_ctr);
4987 ZERO_STRUCT(secdesc_ctr);
4988 ZERO_STRUCT(userlevel_ctr);
4989 ZERO_STRUCT(info1);
4991 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4993 /* try to add printer to wellknown printer list (level 1) */
4995 userlevel_ctr.level = 1;
4997 info_ctr.info.info1 = &info1;
4998 info_ctr.level = 1;
5000 rex.in.server = NULL;
5001 rex.in.info_ctr = &info_ctr;
5002 rex.in.devmode_ctr = &devmode_ctr;
5003 rex.in.secdesc_ctr = &secdesc_ctr;
5004 rex.in.userlevel_ctr = &userlevel_ctr;
5005 rex.out.handle = &handle;
5007 r.in.server = NULL;
5008 r.in.info_ctr = &info_ctr;
5009 r.in.devmode_ctr = &devmode_ctr;
5010 r.in.secdesc_ctr = &secdesc_ctr;
5011 r.out.handle = &handle;
5013 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5014 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5015 "failed to add printer");
5016 result = ex ? rex.out.result : r.out.result;
5017 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5018 "unexpected result code");
5020 info1.name = printername;
5021 info1.flags = PRINTER_ATTRIBUTE_SHARED;
5023 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5024 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5025 "failed to add printer");
5026 result = ex ? rex.out.result : r.out.result;
5027 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5028 "unexpected result code");
5030 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5031 better do a real check to see the printer is really there */
5033 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5034 PRINTER_ENUM_NETWORK, 1,
5035 printername,
5036 &found),
5037 "failed to enum printers");
5039 torture_assert(tctx, found, "failed to find newly added printer");
5041 info1.flags = 0;
5043 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5044 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5045 "failed to add printer");
5046 result = ex ? rex.out.result : r.out.result;
5047 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5048 "unexpected result code");
5050 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5051 better do a real check to see the printer has really been removed
5052 from the well known printer list */
5054 found = false;
5056 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5057 PRINTER_ENUM_NETWORK, 1,
5058 printername,
5059 &found),
5060 "failed to enum printers");
5061 #if 0
5062 torture_assert(tctx, !found, "printer still in well known printer list");
5063 #endif
5064 return true;
5067 static bool test_AddPrinter_normal(struct torture_context *tctx,
5068 struct dcerpc_pipe *p,
5069 struct policy_handle *handle_p,
5070 const char *printername,
5071 const char *drivername,
5072 const char *portname,
5073 bool ex)
5075 WERROR result;
5076 struct spoolss_AddPrinter r;
5077 struct spoolss_AddPrinterEx rex;
5078 struct spoolss_SetPrinterInfoCtr info_ctr;
5079 struct spoolss_SetPrinterInfo2 info2;
5080 struct spoolss_DevmodeContainer devmode_ctr;
5081 struct sec_desc_buf secdesc_ctr;
5082 struct spoolss_UserLevelCtr userlevel_ctr;
5083 struct policy_handle handle;
5084 bool found = false;
5085 bool existing_printer_deleted = false;
5086 struct dcerpc_binding_handle *b = p->binding_handle;
5088 ZERO_STRUCT(devmode_ctr);
5089 ZERO_STRUCT(secdesc_ctr);
5090 ZERO_STRUCT(userlevel_ctr);
5092 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
5094 userlevel_ctr.level = 1;
5096 rex.in.server = NULL;
5097 rex.in.info_ctr = &info_ctr;
5098 rex.in.devmode_ctr = &devmode_ctr;
5099 rex.in.secdesc_ctr = &secdesc_ctr;
5100 rex.in.userlevel_ctr = &userlevel_ctr;
5101 rex.out.handle = &handle;
5103 r.in.server = NULL;
5104 r.in.info_ctr = &info_ctr;
5105 r.in.devmode_ctr = &devmode_ctr;
5106 r.in.secdesc_ctr = &secdesc_ctr;
5107 r.out.handle = &handle;
5109 again:
5111 /* try to add printer to printer list (level 2) */
5113 ZERO_STRUCT(info2);
5115 info_ctr.info.info2 = &info2;
5116 info_ctr.level = 2;
5118 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5119 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5120 "failed to add printer");
5121 result = ex ? rex.out.result : r.out.result;
5122 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5123 "unexpected result code");
5125 info2.printername = printername;
5127 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5128 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5129 "failed to add printer");
5130 result = ex ? rex.out.result : r.out.result;
5132 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
5133 struct policy_handle printer_handle;
5135 if (existing_printer_deleted) {
5136 torture_fail(tctx, "already deleted printer still existing?");
5139 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
5140 "failed to open printer handle");
5142 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
5143 "failed to delete printer");
5145 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
5146 "failed to close server handle");
5148 existing_printer_deleted = true;
5150 goto again;
5153 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
5154 "unexpected result code");
5156 info2.portname = portname;
5158 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5159 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5160 "failed to add printer");
5161 result = ex ? rex.out.result : r.out.result;
5162 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
5163 "unexpected result code");
5165 info2.drivername = drivername;
5167 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5168 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5169 "failed to add printer");
5170 result = ex ? rex.out.result : r.out.result;
5172 /* w2k8r2 allows to add printer w/o defining printprocessor */
5174 if (!W_ERROR_IS_OK(result)) {
5175 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
5176 "unexpected result code");
5178 info2.printprocessor = "winprint";
5180 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5181 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5182 "failed to add printer");
5183 result = ex ? rex.out.result : r.out.result;
5184 torture_assert_werr_ok(tctx, result,
5185 "failed to add printer");
5188 *handle_p = handle;
5190 /* we are paranoid, really check if the printer is there now */
5192 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5193 PRINTER_ENUM_LOCAL, 1,
5194 printername,
5195 &found),
5196 "failed to enum printers");
5197 torture_assert(tctx, found, "failed to find newly added printer");
5199 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5200 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5201 "failed to add printer");
5202 result = ex ? rex.out.result : r.out.result;
5203 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5204 "unexpected result code");
5206 return true;
5209 static bool test_AddPrinterEx(struct torture_context *tctx,
5210 struct dcerpc_pipe *p,
5211 struct policy_handle *handle_p,
5212 const char *printername,
5213 const char *drivername,
5214 const char *portname)
5216 bool ret = true;
5218 if (!torture_setting_bool(tctx, "samba3", false)) {
5219 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
5220 torture_comment(tctx, "failed to add printer to well known list\n");
5221 ret = false;
5225 if (!test_AddPrinter_normal(tctx, p, handle_p,
5226 printername, drivername, portname,
5227 true)) {
5228 torture_comment(tctx, "failed to add printer to printer list\n");
5229 ret = false;
5232 return ret;
5235 static bool test_AddPrinter(struct torture_context *tctx,
5236 struct dcerpc_pipe *p,
5237 struct policy_handle *handle_p,
5238 const char *printername,
5239 const char *drivername,
5240 const char *portname)
5242 bool ret = true;
5244 if (!torture_setting_bool(tctx, "samba3", false)) {
5245 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
5246 torture_comment(tctx, "failed to add printer to well known list\n");
5247 ret = false;
5251 if (!test_AddPrinter_normal(tctx, p, handle_p,
5252 printername, drivername, portname,
5253 false)) {
5254 torture_comment(tctx, "failed to add printer to printer list\n");
5255 ret = false;
5258 return ret;
5261 static bool test_printer_info(struct torture_context *tctx,
5262 struct dcerpc_binding_handle *b,
5263 struct policy_handle *handle)
5265 bool ret = true;
5267 if (torture_setting_bool(tctx, "samba3", false)) {
5268 torture_skip(tctx, "skipping printer info cross tests against samba 3");
5271 if (!test_PrinterInfo(tctx, b, handle)) {
5272 ret = false;
5275 if (!test_SetPrinter_errors(tctx, b, handle)) {
5276 ret = false;
5279 return ret;
5282 static bool test_EnumPrinterKey(struct torture_context *tctx,
5283 struct dcerpc_binding_handle *b,
5284 struct policy_handle *handle,
5285 const char *key_name,
5286 const char ***array)
5288 struct spoolss_EnumPrinterKey r;
5289 uint32_t needed = 0;
5290 union spoolss_KeyNames key_buffer;
5291 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
5292 uint32_t _ndr_size;
5293 int i;
5295 r.in.handle = handle;
5296 r.in.key_name = key_name;
5297 r.out.key_buffer = &key_buffer;
5298 r.out.needed = &needed;
5299 r.out._ndr_size = &_ndr_size;
5301 for (i=0; i < ARRAY_SIZE(offered); i++) {
5303 if (offered[i] < 0 && needed) {
5304 if (needed <= 4) {
5305 continue;
5307 r.in.offered = needed + offered[i];
5308 } else {
5309 r.in.offered = offered[i];
5312 ZERO_STRUCT(key_buffer);
5314 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
5316 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5317 "failed to call EnumPrinterKey");
5318 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
5320 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5321 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5322 _ndr_size, r.in.offered/2));
5324 r.in.offered = needed;
5325 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5326 "failed to call EnumPrinterKey");
5329 if (offered[i] > 0) {
5330 torture_assert_werr_ok(tctx, r.out.result,
5331 "failed to call EnumPrinterKey");
5334 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5335 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5336 _ndr_size, r.in.offered/2));
5338 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5339 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5341 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5342 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5344 if (key_buffer.string_array) {
5345 uint32_t calc_needed = 0;
5346 int s;
5347 for (s=0; key_buffer.string_array[s]; s++) {
5348 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5350 if (!key_buffer.string_array[0]) {
5351 calc_needed += 2;
5353 calc_needed += 2;
5355 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5356 "EnumPrinterKey unexpected size");
5360 if (array) {
5361 *array = key_buffer.string_array;
5364 return true;
5367 bool test_printer_keys(struct torture_context *tctx,
5368 struct dcerpc_binding_handle *b,
5369 struct policy_handle *handle)
5371 const char **key_array = NULL;
5372 int i;
5374 torture_comment(tctx, "Testing Printer Keys\n");
5376 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
5377 "failed to call test_EnumPrinterKey");
5379 for (i=0; key_array && key_array[i]; i++) {
5380 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
5381 "failed to call test_EnumPrinterKey");
5383 for (i=0; key_array && key_array[i]; i++) {
5384 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
5385 "failed to call test_EnumPrinterDataEx");
5388 torture_comment(tctx, "Printer Keys test succeeded\n\n");
5390 return true;
5393 static bool test_one_printer(struct torture_context *tctx,
5394 struct dcerpc_pipe *p,
5395 struct policy_handle *handle,
5396 const char *name)
5398 bool ret = true;
5399 struct dcerpc_binding_handle *b = p->binding_handle;
5401 if (!test_PausePrinter(tctx, b, handle)) {
5402 ret = false;
5405 if (!test_DoPrintTest(tctx, b, handle)) {
5406 ret = false;
5409 if (!test_ResumePrinter(tctx, b, handle)) {
5410 ret = false;
5413 if (!test_printer_info(tctx, b, handle)) {
5414 ret = false;
5417 if (!test_PrinterInfo_SD(tctx, b, handle)) {
5418 ret = false;
5421 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5422 ret = false;
5425 if (!test_ChangeID(tctx, p, handle)) {
5426 ret = false;
5429 if (!test_printer_keys(tctx, b, handle)) {
5430 ret = false;
5433 if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5434 ret = false;
5437 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5438 ret = false;
5441 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5442 ret = false;
5445 if (!test_printer_rename(tctx, p, handle, name)) {
5446 ret = false;
5449 return ret;
5452 static bool test_printer(struct torture_context *tctx,
5453 struct dcerpc_pipe *p)
5455 bool ret = true;
5456 struct policy_handle handle[2];
5457 bool found = false;
5458 const char *drivername = "Microsoft XPS Document Writer";
5459 const char *portname = "LPT1:";
5460 struct dcerpc_binding_handle *b = p->binding_handle;
5462 /* test printer created via AddPrinter */
5464 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5465 return false;
5468 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5469 ret = false;
5472 if (!test_DeletePrinter(tctx, b, &handle[0])) {
5473 ret = false;
5476 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5477 TORTURE_PRINTER, &found)) {
5478 ret = false;
5481 torture_assert(tctx, !found, "deleted printer still there");
5483 /* test printer created via AddPrinterEx */
5485 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5486 return false;
5489 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5490 ret = false;
5493 if (!test_DeletePrinter(tctx, b, &handle[1])) {
5494 ret = false;
5497 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5498 TORTURE_PRINTER_EX, &found)) {
5499 ret = false;
5502 torture_assert(tctx, !found, "deleted printer still there");
5504 return ret;
5507 static bool test_architecture_buffer(struct torture_context *tctx,
5508 struct dcerpc_pipe *p)
5510 struct spoolss_OpenPrinterEx r;
5511 struct spoolss_UserLevel1 u1;
5512 struct policy_handle handle;
5513 uint32_t architectures[] = {
5514 PROCESSOR_ARCHITECTURE_INTEL,
5515 PROCESSOR_ARCHITECTURE_IA64,
5516 PROCESSOR_ARCHITECTURE_AMD64
5518 uint32_t needed[3];
5519 int i;
5520 struct dcerpc_binding_handle *b = p->binding_handle;
5522 for (i=0; i < ARRAY_SIZE(architectures); i++) {
5524 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5526 u1.size = 0;
5527 u1.client = NULL;
5528 u1.user = NULL;
5529 u1.build = 0;
5530 u1.major = 3;
5531 u1.minor = 0;
5532 u1.processor = architectures[i];
5534 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5535 r.in.datatype = NULL;
5536 r.in.devmode_ctr.devmode= NULL;
5537 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5538 r.in.level = 1;
5539 r.in.userlevel.level1 = &u1;
5540 r.out.handle = &handle;
5542 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
5543 torture_assert_werr_ok(tctx, r.out.result, "");
5546 struct spoolss_EnumPrinters e;
5547 uint32_t count;
5548 union spoolss_PrinterInfo *info;
5550 e.in.flags = PRINTER_ENUM_LOCAL;
5551 e.in.server = NULL;
5552 e.in.level = 2;
5553 e.in.buffer = NULL;
5554 e.in.offered = 0;
5555 e.out.count = &count;
5556 e.out.info = &info;
5557 e.out.needed = &needed[i];
5559 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
5560 #if 0
5561 torture_comment(tctx, "needed was %d\n", needed[i]);
5562 #endif
5565 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
5568 for (i=1; i < ARRAY_SIZE(architectures); i++) {
5569 if (needed[i-1] != needed[i]) {
5570 torture_fail(tctx,
5571 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5572 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5576 return true;
5579 bool torture_rpc_spoolss(struct torture_context *torture)
5581 NTSTATUS status;
5582 struct dcerpc_pipe *p;
5583 struct dcerpc_binding_handle *b;
5584 bool ret = true;
5585 struct test_spoolss_context *ctx;
5586 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5588 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5589 if (!NT_STATUS_IS_OK(status)) {
5590 return false;
5592 b = p->binding_handle;
5594 ctx = talloc_zero(torture, struct test_spoolss_context);
5596 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5597 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5598 ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
5599 ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
5600 ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
5601 ret &= test_EnumPorts(torture, b, ctx);
5602 ret &= test_GetPrinterDriverDirectory(torture, p, environment);
5603 ret &= test_GetPrintProcessorDirectory(torture, p, environment);
5604 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5605 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5606 ret &= test_EnumMonitors(torture, b, ctx);
5607 ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
5608 ret &= test_EnumPrintProcDataTypes(torture, b);
5609 ret &= test_EnumPrinters(torture, b, ctx);
5610 ret &= test_OpenPrinter_badname(torture, b, "__INVALID_PRINTER__");
5611 ret &= test_OpenPrinter_badname(torture, b, "\\\\__INVALID_HOST__");
5612 ret &= test_OpenPrinter_badname(torture, b, "");
5613 ret &= test_OpenPrinter_badname(torture, b, "\\\\\\");
5614 ret &= test_OpenPrinter_badname(torture, b, "\\\\\\__INVALID_PRINTER__");
5615 ret &= test_OpenPrinter_badname(torture, b, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
5616 ret &= test_OpenPrinter_badname(torture, b,
5617 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
5620 ret &= test_AddPort(torture, p);
5621 ret &= test_EnumPorts_old(torture, p);
5622 ret &= test_EnumPrinters_old(torture, p, environment);
5623 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5624 ret &= test_architecture_buffer(torture, p);
5626 return ret;
5629 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5631 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5633 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5634 "printer", &ndr_table_spoolss);
5636 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
5638 return suite;