s4-smbtorture: merge badname spoolss openprinter tests.
[Samba/ita.git] / source4 / torture / rpc / spoolss.c
blob4cc0e847694143c9041608433640f7bd28ef9660
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_badname_list(struct torture_context *tctx,
4386 struct dcerpc_binding_handle *b,
4387 const char *server_name)
4389 const char *badnames[] = {
4390 "__INVALID_PRINTER__",
4391 "\\\\__INVALID_HOST__",
4393 "\\\\\\",
4394 "\\\\\\__INVALID_PRINTER__"
4396 const char *badname;
4397 int i;
4399 for (i=0; i < ARRAY_SIZE(badnames); i++) {
4400 torture_assert(tctx,
4401 test_OpenPrinter_badname(tctx, b, badnames[i]),
4402 "");
4405 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
4406 torture_assert(tctx,
4407 test_OpenPrinter_badname(tctx, b, badname),
4408 "");
4410 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
4411 torture_assert(tctx,
4412 test_OpenPrinter_badname(tctx, b, badname),
4413 "");
4415 return true;
4418 static bool test_OpenPrinter(struct torture_context *tctx,
4419 struct dcerpc_pipe *p,
4420 const char *name,
4421 const char *environment)
4423 NTSTATUS status;
4424 struct spoolss_OpenPrinter r;
4425 struct policy_handle handle;
4426 bool ret = true;
4427 struct dcerpc_binding_handle *b = p->binding_handle;
4429 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4430 r.in.datatype = NULL;
4431 r.in.devmode_ctr.devmode= NULL;
4432 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4433 r.out.handle = &handle;
4435 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4437 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
4439 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4441 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4443 if (!test_GetPrinter(tctx, b, &handle, environment)) {
4444 ret = false;
4447 if (!torture_setting_bool(tctx, "samba3", false)) {
4448 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4449 ret = false;
4453 if (!test_ClosePrinter(tctx, b, &handle)) {
4454 ret = false;
4457 return ret;
4460 static bool call_OpenPrinterEx(struct torture_context *tctx,
4461 struct dcerpc_pipe *p,
4462 const char *name,
4463 struct spoolss_DeviceMode *devmode,
4464 struct policy_handle *handle)
4466 struct spoolss_OpenPrinterEx r;
4467 struct spoolss_UserLevel1 userlevel1;
4468 NTSTATUS status;
4469 struct dcerpc_binding_handle *b = p->binding_handle;
4471 if (name && name[0]) {
4472 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4473 dcerpc_server_name(p), name);
4474 } else {
4475 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4476 dcerpc_server_name(p));
4479 r.in.datatype = NULL;
4480 r.in.devmode_ctr.devmode= devmode;
4481 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4482 r.in.level = 1;
4483 r.in.userlevel.level1 = &userlevel1;
4484 r.out.handle = handle;
4486 userlevel1.size = 1234;
4487 userlevel1.client = "hello";
4488 userlevel1.user = "spottyfoot!";
4489 userlevel1.build = 1;
4490 userlevel1.major = 2;
4491 userlevel1.minor = 3;
4492 userlevel1.processor = 4;
4494 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4496 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
4498 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4500 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4502 return true;
4505 static bool test_printer_rename(struct torture_context *tctx,
4506 struct dcerpc_pipe *p,
4507 struct policy_handle *handle,
4508 const char *name)
4510 bool ret = true;
4511 union spoolss_PrinterInfo info;
4512 union spoolss_SetPrinterInfo sinfo;
4513 struct spoolss_SetPrinterInfoCtr info_ctr;
4514 struct spoolss_DevmodeContainer devmode_ctr;
4515 struct sec_desc_buf secdesc_ctr;
4516 const char *printer_name;
4517 const char *printer_name_orig;
4518 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4519 struct policy_handle new_handle;
4520 const char *q;
4521 struct dcerpc_binding_handle *b = p->binding_handle;
4523 ZERO_STRUCT(devmode_ctr);
4524 ZERO_STRUCT(secdesc_ctr);
4526 torture_comment(tctx, "Testing Printer rename operations\n");
4528 torture_assert(tctx,
4529 test_GetPrinter_level(tctx, b, handle, 2, &info),
4530 "failed to call GetPrinter level 2");
4532 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4534 q = strrchr(info.info2.printername, '\\');
4535 if (q) {
4536 torture_warning(tctx,
4537 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4540 torture_assert(tctx,
4541 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4543 sinfo.info2->printername = printer_name_new;
4545 info_ctr.level = 2;
4546 info_ctr.info = sinfo;
4548 torture_assert(tctx,
4549 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4550 "failed to call SetPrinter level 2");
4552 torture_assert(tctx,
4553 test_GetPrinter_level(tctx, b, handle, 2, &info),
4554 "failed to call GetPrinter level 2");
4556 printer_name = talloc_strdup(tctx, info.info2.printername);
4558 q = strrchr(info.info2.printername, '\\');
4559 if (q) {
4560 torture_warning(tctx,
4561 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4562 q++;
4563 printer_name = q;
4566 torture_assert_str_equal(tctx, printer_name, printer_name_new,
4567 "new printer name was not set");
4569 /* samba currently cannot fully rename printers */
4570 if (!torture_setting_bool(tctx, "samba3", false)) {
4571 torture_assert(tctx,
4572 test_OpenPrinter_badname(tctx, b, printer_name_orig),
4573 "still can open printer with oldname after rename");
4574 } else {
4575 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
4578 torture_assert(tctx,
4579 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4580 "failed to open printer with new name");
4582 torture_assert(tctx,
4583 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
4584 "failed to call GetPrinter level 2");
4586 /* FIXME: we openend with servername! */
4587 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4588 dcerpc_server_name(p), printer_name_new);
4590 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4591 "new printer name was not set");
4593 torture_assert(tctx,
4594 test_ClosePrinter(tctx, b, &new_handle),
4595 "failed to close printer");
4597 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
4599 return ret;
4603 static bool test_OpenPrinterEx(struct torture_context *tctx,
4604 struct dcerpc_pipe *p,
4605 const char *name,
4606 const char *environment)
4608 struct policy_handle handle;
4609 bool ret = true;
4610 struct dcerpc_binding_handle *b = p->binding_handle;
4612 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4613 return false;
4616 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
4617 ret = false;
4620 if (!test_GetPrinter(tctx, b, &handle, environment)) {
4621 ret = false;
4624 if (!test_EnumForms_all(tctx, b, &handle, false)) {
4625 ret = false;
4628 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
4629 ret = false;
4632 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
4633 ret = false;
4636 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4637 ret = false;
4640 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
4641 ret = false;
4644 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4645 ret = false;
4648 if (!test_printer_keys(tctx, b, &handle)) {
4649 ret = false;
4652 if (!test_PausePrinter(tctx, b, &handle)) {
4653 ret = false;
4656 if (!test_DoPrintTest(tctx, b, &handle)) {
4657 ret = false;
4660 if (!test_ResumePrinter(tctx, b, &handle)) {
4661 ret = false;
4664 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
4665 ret = false;
4668 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4669 ret = false;
4672 if (!torture_setting_bool(tctx, "samba3", false)) {
4673 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4674 ret = false;
4678 if (!test_ClosePrinter(tctx, b, &handle)) {
4679 ret = false;
4682 return ret;
4685 static bool test_EnumPrinters_old(struct torture_context *tctx,
4686 struct dcerpc_pipe *p,
4687 const char *environment)
4689 struct spoolss_EnumPrinters r;
4690 NTSTATUS status;
4691 uint16_t levels[] = {1, 2, 4, 5};
4692 int i;
4693 bool ret = true;
4694 struct dcerpc_binding_handle *b = p->binding_handle;
4696 for (i=0;i<ARRAY_SIZE(levels);i++) {
4697 union spoolss_PrinterInfo *info;
4698 int j;
4699 uint32_t needed;
4700 uint32_t count;
4702 r.in.flags = PRINTER_ENUM_LOCAL;
4703 r.in.server = "";
4704 r.in.level = levels[i];
4705 r.in.buffer = NULL;
4706 r.in.offered = 0;
4707 r.out.needed = &needed;
4708 r.out.count = &count;
4709 r.out.info = &info;
4711 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4713 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
4714 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4716 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4717 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4718 data_blob_clear(&blob);
4719 r.in.buffer = &blob;
4720 r.in.offered = needed;
4721 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
4724 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4726 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4728 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4730 if (!info) {
4731 torture_comment(tctx, "No printers returned\n");
4732 return true;
4735 for (j=0;j<count;j++) {
4736 if (r.in.level == 1) {
4737 char *unc = talloc_strdup(tctx, info[j].info1.name);
4738 char *slash, *name;
4739 name = unc;
4740 if (unc[0] == '\\' && unc[1] == '\\') {
4741 unc +=2;
4743 slash = strchr(unc, '\\');
4744 if (slash) {
4745 slash++;
4746 name = slash;
4748 if (!test_OpenPrinter(tctx, p, name, environment)) {
4749 ret = false;
4751 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4752 ret = false;
4758 return ret;
4761 static bool test_GetPrinterDriver(struct torture_context *tctx,
4762 struct dcerpc_binding_handle *b,
4763 struct policy_handle *handle,
4764 const char *driver_name)
4766 struct spoolss_GetPrinterDriver r;
4767 uint32_t needed;
4769 r.in.handle = handle;
4770 r.in.architecture = "W32X86";
4771 r.in.level = 1;
4772 r.in.buffer = NULL;
4773 r.in.offered = 0;
4774 r.out.needed = &needed;
4776 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4778 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
4779 "failed to call GetPrinterDriver");
4780 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4781 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4782 data_blob_clear(&blob);
4783 r.in.buffer = &blob;
4784 r.in.offered = needed;
4785 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
4786 "failed to call GetPrinterDriver");
4789 torture_assert_werr_ok(tctx, r.out.result,
4790 "failed to call GetPrinterDriver");
4792 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4794 return true;
4797 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4798 struct dcerpc_binding_handle *b,
4799 struct policy_handle *handle,
4800 const char *driver_name,
4801 const char *architecture)
4803 struct spoolss_GetPrinterDriver2 r;
4804 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4805 uint32_t needed;
4806 uint32_t server_major_version;
4807 uint32_t server_minor_version;
4808 int i;
4810 r.in.handle = handle;
4811 r.in.architecture = architecture;
4812 r.in.client_major_version = 3;
4813 r.in.client_minor_version = 0;
4814 r.out.needed = &needed;
4815 r.out.server_major_version = &server_major_version;
4816 r.out.server_minor_version = &server_minor_version;
4818 for (i=0;i<ARRAY_SIZE(levels);i++) {
4820 r.in.buffer = NULL;
4821 r.in.offered = 0;
4822 r.in.level = levels[i];
4824 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4825 driver_name, r.in.level);
4827 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
4828 "failed to call GetPrinterDriver2");
4829 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4830 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4831 data_blob_clear(&blob);
4832 r.in.buffer = &blob;
4833 r.in.offered = needed;
4834 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
4835 "failed to call GetPrinterDriver2");
4838 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4839 switch (r.in.level) {
4840 case 101:
4841 case 8:
4842 continue;
4843 default:
4844 break;
4848 torture_assert_werr_ok(tctx, r.out.result,
4849 "failed to call GetPrinterDriver2");
4851 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4854 return true;
4857 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4858 struct dcerpc_pipe *p,
4859 const char *environment)
4861 struct spoolss_EnumPrinterDrivers r;
4862 NTSTATUS status;
4863 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4864 int i;
4865 struct dcerpc_binding_handle *b = p->binding_handle;
4867 for (i=0;i<ARRAY_SIZE(levels);i++) {
4869 uint32_t needed;
4870 uint32_t count;
4871 union spoolss_DriverInfo *info;
4873 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4874 r.in.environment = environment;
4875 r.in.level = levels[i];
4876 r.in.buffer = NULL;
4877 r.in.offered = 0;
4878 r.out.needed = &needed;
4879 r.out.count = &count;
4880 r.out.info = &info;
4882 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4884 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
4886 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4888 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4889 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4890 data_blob_clear(&blob);
4891 r.in.buffer = &blob;
4892 r.in.offered = needed;
4893 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
4896 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4898 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4900 if (!info) {
4901 torture_comment(tctx, "No printer drivers returned\n");
4902 break;
4905 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4908 return true;
4911 static bool test_DeletePrinter(struct torture_context *tctx,
4912 struct dcerpc_binding_handle *b,
4913 struct policy_handle *handle)
4915 struct spoolss_DeletePrinter r;
4917 torture_comment(tctx, "Testing DeletePrinter\n");
4919 r.in.handle = handle;
4921 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
4922 "failed to delete printer");
4923 torture_assert_werr_ok(tctx, r.out.result,
4924 "failed to delete printer");
4926 return true;
4929 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4930 struct dcerpc_binding_handle *b,
4931 uint32_t flags,
4932 uint32_t level,
4933 const char *name,
4934 bool *found)
4936 struct spoolss_EnumPrinters e;
4937 uint32_t count;
4938 union spoolss_PrinterInfo *info;
4939 uint32_t needed;
4940 int i;
4942 *found = false;
4944 e.in.flags = flags;
4945 e.in.server = NULL;
4946 e.in.level = level;
4947 e.in.buffer = NULL;
4948 e.in.offered = 0;
4949 e.out.count = &count;
4950 e.out.info = &info;
4951 e.out.needed = &needed;
4953 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
4954 "failed to enum printers");
4956 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4957 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4958 data_blob_clear(&blob);
4959 e.in.buffer = &blob;
4960 e.in.offered = needed;
4962 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
4963 "failed to enum printers");
4966 torture_assert_werr_ok(tctx, e.out.result,
4967 "failed to enum printers");
4969 for (i=0; i < count; i++) {
4971 const char *current = NULL;
4972 const char *q;
4974 switch (level) {
4975 case 1:
4976 current = info[i].info1.name;
4977 break;
4980 if (strequal(current, name)) {
4981 *found = true;
4982 break;
4985 q = strrchr(current, '\\');
4986 if (q) {
4987 if (!e.in.server) {
4988 torture_warning(tctx,
4989 "server returns printername %s incl. servername although we did not set servername", current);
4991 q++;
4992 if (strequal(q, name)) {
4993 *found = true;
4994 break;
4999 return true;
5002 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
5003 struct dcerpc_pipe *p,
5004 const char *printername,
5005 bool ex)
5007 WERROR result;
5008 struct spoolss_AddPrinter r;
5009 struct spoolss_AddPrinterEx rex;
5010 struct spoolss_SetPrinterInfoCtr info_ctr;
5011 struct spoolss_SetPrinterInfo1 info1;
5012 struct spoolss_DevmodeContainer devmode_ctr;
5013 struct sec_desc_buf secdesc_ctr;
5014 struct spoolss_UserLevelCtr userlevel_ctr;
5015 struct policy_handle handle;
5016 bool found = false;
5017 struct dcerpc_binding_handle *b = p->binding_handle;
5019 ZERO_STRUCT(devmode_ctr);
5020 ZERO_STRUCT(secdesc_ctr);
5021 ZERO_STRUCT(userlevel_ctr);
5022 ZERO_STRUCT(info1);
5024 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
5026 /* try to add printer to wellknown printer list (level 1) */
5028 userlevel_ctr.level = 1;
5030 info_ctr.info.info1 = &info1;
5031 info_ctr.level = 1;
5033 rex.in.server = NULL;
5034 rex.in.info_ctr = &info_ctr;
5035 rex.in.devmode_ctr = &devmode_ctr;
5036 rex.in.secdesc_ctr = &secdesc_ctr;
5037 rex.in.userlevel_ctr = &userlevel_ctr;
5038 rex.out.handle = &handle;
5040 r.in.server = NULL;
5041 r.in.info_ctr = &info_ctr;
5042 r.in.devmode_ctr = &devmode_ctr;
5043 r.in.secdesc_ctr = &secdesc_ctr;
5044 r.out.handle = &handle;
5046 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5047 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5048 "failed to add printer");
5049 result = ex ? rex.out.result : r.out.result;
5050 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5051 "unexpected result code");
5053 info1.name = printername;
5054 info1.flags = PRINTER_ATTRIBUTE_SHARED;
5056 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5057 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5058 "failed to add printer");
5059 result = ex ? rex.out.result : r.out.result;
5060 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5061 "unexpected result code");
5063 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5064 better do a real check to see the printer is really there */
5066 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5067 PRINTER_ENUM_NETWORK, 1,
5068 printername,
5069 &found),
5070 "failed to enum printers");
5072 torture_assert(tctx, found, "failed to find newly added printer");
5074 info1.flags = 0;
5076 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5077 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5078 "failed to add printer");
5079 result = ex ? rex.out.result : r.out.result;
5080 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5081 "unexpected result code");
5083 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5084 better do a real check to see the printer has really been removed
5085 from the well known printer list */
5087 found = false;
5089 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5090 PRINTER_ENUM_NETWORK, 1,
5091 printername,
5092 &found),
5093 "failed to enum printers");
5094 #if 0
5095 torture_assert(tctx, !found, "printer still in well known printer list");
5096 #endif
5097 return true;
5100 static bool test_AddPrinter_normal(struct torture_context *tctx,
5101 struct dcerpc_pipe *p,
5102 struct policy_handle *handle_p,
5103 const char *printername,
5104 const char *drivername,
5105 const char *portname,
5106 bool ex)
5108 WERROR result;
5109 struct spoolss_AddPrinter r;
5110 struct spoolss_AddPrinterEx rex;
5111 struct spoolss_SetPrinterInfoCtr info_ctr;
5112 struct spoolss_SetPrinterInfo2 info2;
5113 struct spoolss_DevmodeContainer devmode_ctr;
5114 struct sec_desc_buf secdesc_ctr;
5115 struct spoolss_UserLevelCtr userlevel_ctr;
5116 struct policy_handle handle;
5117 bool found = false;
5118 bool existing_printer_deleted = false;
5119 struct dcerpc_binding_handle *b = p->binding_handle;
5121 ZERO_STRUCT(devmode_ctr);
5122 ZERO_STRUCT(secdesc_ctr);
5123 ZERO_STRUCT(userlevel_ctr);
5125 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
5127 userlevel_ctr.level = 1;
5129 rex.in.server = NULL;
5130 rex.in.info_ctr = &info_ctr;
5131 rex.in.devmode_ctr = &devmode_ctr;
5132 rex.in.secdesc_ctr = &secdesc_ctr;
5133 rex.in.userlevel_ctr = &userlevel_ctr;
5134 rex.out.handle = &handle;
5136 r.in.server = NULL;
5137 r.in.info_ctr = &info_ctr;
5138 r.in.devmode_ctr = &devmode_ctr;
5139 r.in.secdesc_ctr = &secdesc_ctr;
5140 r.out.handle = &handle;
5142 again:
5144 /* try to add printer to printer list (level 2) */
5146 ZERO_STRUCT(info2);
5148 info_ctr.info.info2 = &info2;
5149 info_ctr.level = 2;
5151 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5152 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5153 "failed to add printer");
5154 result = ex ? rex.out.result : r.out.result;
5155 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5156 "unexpected result code");
5158 info2.printername = printername;
5160 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5161 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5162 "failed to add printer");
5163 result = ex ? rex.out.result : r.out.result;
5165 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
5166 struct policy_handle printer_handle;
5168 if (existing_printer_deleted) {
5169 torture_fail(tctx, "already deleted printer still existing?");
5172 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
5173 "failed to open printer handle");
5175 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
5176 "failed to delete printer");
5178 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
5179 "failed to close server handle");
5181 existing_printer_deleted = true;
5183 goto again;
5186 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
5187 "unexpected result code");
5189 info2.portname = portname;
5191 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5192 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5193 "failed to add printer");
5194 result = ex ? rex.out.result : r.out.result;
5195 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
5196 "unexpected result code");
5198 info2.drivername = drivername;
5200 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5201 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5202 "failed to add printer");
5203 result = ex ? rex.out.result : r.out.result;
5205 /* w2k8r2 allows to add printer w/o defining printprocessor */
5207 if (!W_ERROR_IS_OK(result)) {
5208 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
5209 "unexpected result code");
5211 info2.printprocessor = "winprint";
5213 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5214 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5215 "failed to add printer");
5216 result = ex ? rex.out.result : r.out.result;
5217 torture_assert_werr_ok(tctx, result,
5218 "failed to add printer");
5221 *handle_p = handle;
5223 /* we are paranoid, really check if the printer is there now */
5225 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5226 PRINTER_ENUM_LOCAL, 1,
5227 printername,
5228 &found),
5229 "failed to enum printers");
5230 torture_assert(tctx, found, "failed to find newly added printer");
5232 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5233 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5234 "failed to add printer");
5235 result = ex ? rex.out.result : r.out.result;
5236 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5237 "unexpected result code");
5239 return true;
5242 static bool test_AddPrinterEx(struct torture_context *tctx,
5243 struct dcerpc_pipe *p,
5244 struct policy_handle *handle_p,
5245 const char *printername,
5246 const char *drivername,
5247 const char *portname)
5249 bool ret = true;
5251 if (!torture_setting_bool(tctx, "samba3", false)) {
5252 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
5253 torture_comment(tctx, "failed to add printer to well known list\n");
5254 ret = false;
5258 if (!test_AddPrinter_normal(tctx, p, handle_p,
5259 printername, drivername, portname,
5260 true)) {
5261 torture_comment(tctx, "failed to add printer to printer list\n");
5262 ret = false;
5265 return ret;
5268 static bool test_AddPrinter(struct torture_context *tctx,
5269 struct dcerpc_pipe *p,
5270 struct policy_handle *handle_p,
5271 const char *printername,
5272 const char *drivername,
5273 const char *portname)
5275 bool ret = true;
5277 if (!torture_setting_bool(tctx, "samba3", false)) {
5278 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
5279 torture_comment(tctx, "failed to add printer to well known list\n");
5280 ret = false;
5284 if (!test_AddPrinter_normal(tctx, p, handle_p,
5285 printername, drivername, portname,
5286 false)) {
5287 torture_comment(tctx, "failed to add printer to printer list\n");
5288 ret = false;
5291 return ret;
5294 static bool test_printer_info(struct torture_context *tctx,
5295 struct dcerpc_binding_handle *b,
5296 struct policy_handle *handle)
5298 bool ret = true;
5300 if (torture_setting_bool(tctx, "samba3", false)) {
5301 torture_skip(tctx, "skipping printer info cross tests against samba 3");
5304 if (!test_PrinterInfo(tctx, b, handle)) {
5305 ret = false;
5308 if (!test_SetPrinter_errors(tctx, b, handle)) {
5309 ret = false;
5312 return ret;
5315 static bool test_EnumPrinterKey(struct torture_context *tctx,
5316 struct dcerpc_binding_handle *b,
5317 struct policy_handle *handle,
5318 const char *key_name,
5319 const char ***array)
5321 struct spoolss_EnumPrinterKey r;
5322 uint32_t needed = 0;
5323 union spoolss_KeyNames key_buffer;
5324 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
5325 uint32_t _ndr_size;
5326 int i;
5328 r.in.handle = handle;
5329 r.in.key_name = key_name;
5330 r.out.key_buffer = &key_buffer;
5331 r.out.needed = &needed;
5332 r.out._ndr_size = &_ndr_size;
5334 for (i=0; i < ARRAY_SIZE(offered); i++) {
5336 if (offered[i] < 0 && needed) {
5337 if (needed <= 4) {
5338 continue;
5340 r.in.offered = needed + offered[i];
5341 } else {
5342 r.in.offered = offered[i];
5345 ZERO_STRUCT(key_buffer);
5347 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
5349 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5350 "failed to call EnumPrinterKey");
5351 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
5353 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5354 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5355 _ndr_size, r.in.offered/2));
5357 r.in.offered = needed;
5358 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5359 "failed to call EnumPrinterKey");
5362 if (offered[i] > 0) {
5363 torture_assert_werr_ok(tctx, r.out.result,
5364 "failed to call EnumPrinterKey");
5367 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5368 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5369 _ndr_size, r.in.offered/2));
5371 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5372 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5374 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5375 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5377 if (key_buffer.string_array) {
5378 uint32_t calc_needed = 0;
5379 int s;
5380 for (s=0; key_buffer.string_array[s]; s++) {
5381 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5383 if (!key_buffer.string_array[0]) {
5384 calc_needed += 2;
5386 calc_needed += 2;
5388 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5389 "EnumPrinterKey unexpected size");
5393 if (array) {
5394 *array = key_buffer.string_array;
5397 return true;
5400 bool test_printer_keys(struct torture_context *tctx,
5401 struct dcerpc_binding_handle *b,
5402 struct policy_handle *handle)
5404 const char **key_array = NULL;
5405 int i;
5407 torture_comment(tctx, "Testing Printer Keys\n");
5409 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
5410 "failed to call test_EnumPrinterKey");
5412 for (i=0; key_array && key_array[i]; i++) {
5413 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
5414 "failed to call test_EnumPrinterKey");
5416 for (i=0; key_array && key_array[i]; i++) {
5417 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
5418 "failed to call test_EnumPrinterDataEx");
5421 torture_comment(tctx, "Printer Keys test succeeded\n\n");
5423 return true;
5426 static bool test_one_printer(struct torture_context *tctx,
5427 struct dcerpc_pipe *p,
5428 struct policy_handle *handle,
5429 const char *name)
5431 bool ret = true;
5432 struct dcerpc_binding_handle *b = p->binding_handle;
5434 if (!test_PausePrinter(tctx, b, handle)) {
5435 ret = false;
5438 if (!test_DoPrintTest(tctx, b, handle)) {
5439 ret = false;
5442 if (!test_ResumePrinter(tctx, b, handle)) {
5443 ret = false;
5446 if (!test_printer_info(tctx, b, handle)) {
5447 ret = false;
5450 if (!test_PrinterInfo_SD(tctx, b, handle)) {
5451 ret = false;
5454 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5455 ret = false;
5458 if (!test_ChangeID(tctx, p, handle)) {
5459 ret = false;
5462 if (!test_printer_keys(tctx, b, handle)) {
5463 ret = false;
5466 if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5467 ret = false;
5470 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5471 ret = false;
5474 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5475 ret = false;
5478 if (!test_printer_rename(tctx, p, handle, name)) {
5479 ret = false;
5482 return ret;
5485 static bool test_printer(struct torture_context *tctx,
5486 struct dcerpc_pipe *p)
5488 bool ret = true;
5489 struct policy_handle handle[2];
5490 bool found = false;
5491 const char *drivername = "Microsoft XPS Document Writer";
5492 const char *portname = "LPT1:";
5493 struct dcerpc_binding_handle *b = p->binding_handle;
5495 /* test printer created via AddPrinter */
5497 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5498 return false;
5501 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5502 ret = false;
5505 if (!test_DeletePrinter(tctx, b, &handle[0])) {
5506 ret = false;
5509 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5510 TORTURE_PRINTER, &found)) {
5511 ret = false;
5514 torture_assert(tctx, !found, "deleted printer still there");
5516 /* test printer created via AddPrinterEx */
5518 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5519 return false;
5522 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5523 ret = false;
5526 if (!test_DeletePrinter(tctx, b, &handle[1])) {
5527 ret = false;
5530 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5531 TORTURE_PRINTER_EX, &found)) {
5532 ret = false;
5535 torture_assert(tctx, !found, "deleted printer still there");
5537 return ret;
5540 static bool test_architecture_buffer(struct torture_context *tctx,
5541 struct dcerpc_pipe *p)
5543 struct spoolss_OpenPrinterEx r;
5544 struct spoolss_UserLevel1 u1;
5545 struct policy_handle handle;
5546 uint32_t architectures[] = {
5547 PROCESSOR_ARCHITECTURE_INTEL,
5548 PROCESSOR_ARCHITECTURE_IA64,
5549 PROCESSOR_ARCHITECTURE_AMD64
5551 uint32_t needed[3];
5552 int i;
5553 struct dcerpc_binding_handle *b = p->binding_handle;
5555 for (i=0; i < ARRAY_SIZE(architectures); i++) {
5557 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5559 u1.size = 0;
5560 u1.client = NULL;
5561 u1.user = NULL;
5562 u1.build = 0;
5563 u1.major = 3;
5564 u1.minor = 0;
5565 u1.processor = architectures[i];
5567 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5568 r.in.datatype = NULL;
5569 r.in.devmode_ctr.devmode= NULL;
5570 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5571 r.in.level = 1;
5572 r.in.userlevel.level1 = &u1;
5573 r.out.handle = &handle;
5575 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
5576 torture_assert_werr_ok(tctx, r.out.result, "");
5579 struct spoolss_EnumPrinters e;
5580 uint32_t count;
5581 union spoolss_PrinterInfo *info;
5583 e.in.flags = PRINTER_ENUM_LOCAL;
5584 e.in.server = NULL;
5585 e.in.level = 2;
5586 e.in.buffer = NULL;
5587 e.in.offered = 0;
5588 e.out.count = &count;
5589 e.out.info = &info;
5590 e.out.needed = &needed[i];
5592 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
5593 #if 0
5594 torture_comment(tctx, "needed was %d\n", needed[i]);
5595 #endif
5598 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
5601 for (i=1; i < ARRAY_SIZE(architectures); i++) {
5602 if (needed[i-1] != needed[i]) {
5603 torture_fail(tctx,
5604 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5605 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5609 return true;
5612 bool torture_rpc_spoolss(struct torture_context *torture)
5614 NTSTATUS status;
5615 struct dcerpc_pipe *p;
5616 struct dcerpc_binding_handle *b;
5617 bool ret = true;
5618 struct test_spoolss_context *ctx;
5619 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5621 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5622 if (!NT_STATUS_IS_OK(status)) {
5623 return false;
5625 b = p->binding_handle;
5627 ctx = talloc_zero(torture, struct test_spoolss_context);
5629 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5630 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5631 ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
5632 ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
5633 ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
5634 ret &= test_EnumPorts(torture, b, ctx);
5635 ret &= test_GetPrinterDriverDirectory(torture, p, environment);
5636 ret &= test_GetPrintProcessorDirectory(torture, p, environment);
5637 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5638 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5639 ret &= test_EnumMonitors(torture, b, ctx);
5640 ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
5641 ret &= test_EnumPrintProcDataTypes(torture, b);
5642 ret &= test_EnumPrinters(torture, b, ctx);
5643 ret &= test_OpenPrinter_badname_list(torture, b, dcerpc_server_name(p));
5645 ret &= test_AddPort(torture, p);
5646 ret &= test_EnumPorts_old(torture, p);
5647 ret &= test_EnumPrinters_old(torture, p, environment);
5648 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5649 ret &= test_architecture_buffer(torture, p);
5651 return ret;
5654 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5656 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5658 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5659 "printer", &ndr_table_spoolss);
5661 torture_rpc_tcase_add_test(tcase, "printer", test_printer);
5663 return suite;