/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- test_OpenPrinter_server
- test_EnumPorts
- test_GetPrintProcessorDirectory
- test_GetPrinterDriverDirectory
- test_EnumPrinterDrivers
- test_EnumMonitors
- test_EnumPrintProcessors
- test_EnumPrintProcDataTypes
- test_EnumPrinters
- test_GetPrinter
- test_ClosePrinter
- test_GetForm
- test_EnumForms
- test_DeleteForm
- test_AddForm
- test_EnumPorts_old
- test_AddPort
- test_GetJob
- test_SetJob
- test_AddJob
- test_EnumJobs
- test_DoPrintTest
- test_PausePrinter
- test_ResumePrinter
- test_GetPrinterData
- test_GetPrinterDataEx
- test_EnumPrinterData
- test_EnumPrinterDataEx
- test_DeletePrinterData
- test_SetPrinterData
- test_SecondaryClosePrinter
- test_OpenPrinter_badname
- test_OpenPrinter
- call_OpenPrinterEx
- test_OpenPrinterEx
- test_EnumPrinters_old
- test_GetPrinterDriver2
- test_EnumPrinterDrivers_old
- torture_rpc_spoolss
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
4
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Stefan Metzmacher 2005
7 Copyright (C) Jelmer Vernooij 2007
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "torture/rpc/rpc.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
27
28 struct test_spoolss_context {
29 /* print server handle */
30 struct policy_handle server_handle;
31
32 /* for EnumPorts */
33 uint32_t port_count[3];
34 union spoolss_PortInfo *ports[3];
35
36 /* for EnumPrinterDrivers */
37 uint32_t driver_count[7];
38 union spoolss_DriverInfo *drivers[7];
39
40 /* for EnumMonitors */
41 uint32_t monitor_count[3];
42 union spoolss_MonitorInfo *monitors[3];
43
44 /* for EnumPrintProcessors */
45 uint32_t print_processor_count[2];
46 union spoolss_PrintProcessorInfo *print_processors[2];
47
48 /* for EnumPrinters */
49 uint32_t printer_count[6];
50 union spoolss_PrinterInfo *printers[6];
51 };
52
53 #define COMPARE_STRING(tctx, c,r,e) \
54 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
55
56 /* not every compiler supports __typeof__() */
57 #if (__GNUC__ >= 3)
58 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
59 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
60 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
61 }\
62 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
63 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
64 }\
65 } while(0)
66 #else
67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
68 #endif
69
70 #define COMPARE_UINT32(tctx, c, r, e) do {\
71 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
72 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
73 } while(0)
74
75 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
76
77 static bool test_OpenPrinter_server(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
/* [<][>][^][v][top][bottom][index][help] */
78 {
79 NTSTATUS status;
80 struct spoolss_OpenPrinter op;
81
82 op.in.printername = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
83 op.in.datatype = NULL;
84 op.in.devmode_ctr.devmode= NULL;
85 op.in.access_mask = 0;
86 op.out.handle = &ctx->server_handle;
87
88 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
89
90 status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
91 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
92 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
93
94 return true;
95 }
96
97 static bool test_EnumPorts(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
98 struct dcerpc_pipe *p,
99 struct test_spoolss_context *ctx)
100 {
101 NTSTATUS status;
102 struct spoolss_EnumPorts r;
103 uint16_t levels[] = { 1, 2 };
104 int i, j;
105
106 for (i=0;i<ARRAY_SIZE(levels);i++) {
107 int level = levels[i];
108 DATA_BLOB blob;
109 uint32_t needed;
110 uint32_t count;
111 union spoolss_PortInfo *info;
112
113 r.in.servername = "";
114 r.in.level = level;
115 r.in.buffer = NULL;
116 r.in.offered = 0;
117 r.out.needed = &needed;
118 r.out.count = &count;
119 r.out.info = &info;
120
121 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
122
123 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
124 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
125 if (W_ERROR_IS_OK(r.out.result)) {
126 /* TODO: do some more checks here */
127 continue;
128 }
129 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
130 "EnumPorts unexpected return code");
131
132 blob = data_blob_talloc(ctx, NULL, needed);
133 data_blob_clear(&blob);
134 r.in.buffer = &blob;
135 r.in.offered = needed;
136
137 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
138 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
139
140 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
141
142 torture_assert(tctx, info, "EnumPorts returned no info");
143
144 ctx->port_count[level] = count;
145 ctx->ports[level] = info;
146 }
147
148 for (i=1;i<ARRAY_SIZE(levels);i++) {
149 int level = levels[i];
150 int old_level = levels[i-1];
151 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
152 "EnumPorts invalid value");
153 }
154 /* if the array sizes are not the same we would maybe segfault in the following code */
155
156 for (i=0;i<ARRAY_SIZE(levels);i++) {
157 int level = levels[i];
158 for (j=0;j<ctx->port_count[level];j++) {
159 union spoolss_PortInfo *cur = &ctx->ports[level][j];
160 union spoolss_PortInfo *ref = &ctx->ports[2][j];
161 switch (level) {
162 case 1:
163 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
164 break;
165 case 2:
166 /* level 2 is our reference, and it makes no sense to compare it to itself */
167 break;
168 }
169 }
170 }
171
172 return true;
173 }
174
175 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
176 struct dcerpc_pipe *p,
177 struct test_spoolss_context *ctx)
178 {
179 NTSTATUS status;
180 struct spoolss_GetPrintProcessorDirectory r;
181 struct {
182 uint16_t level;
183 const char *server;
184 } levels[] = {{
185 .level = 1,
186 .server = NULL
187 },{
188 .level = 1,
189 .server = ""
190 },{
191 .level = 78,
192 .server = ""
193 },{
194 .level = 1,
195 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
196 },{
197 .level = 1024,
198 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
199 }
200 };
201 int i;
202 uint32_t needed;
203
204 for (i=0;i<ARRAY_SIZE(levels);i++) {
205 int level = levels[i].level;
206 DATA_BLOB blob;
207
208 r.in.server = levels[i].server;
209 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
210 r.in.level = level;
211 r.in.buffer = NULL;
212 r.in.offered = 0;
213 r.out.needed = &needed;
214
215 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
216
217 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
218 torture_assert_ntstatus_ok(tctx, status,
219 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
220 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
221 "GetPrintProcessorDirectory unexpected return code");
222
223 blob = data_blob_talloc(ctx, NULL, needed);
224 data_blob_clear(&blob);
225 r.in.buffer = &blob;
226 r.in.offered = needed;
227
228 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
229 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
230
231 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
232 }
233
234 return true;
235 }
236
237
238 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
239 struct dcerpc_pipe *p,
240 struct test_spoolss_context *ctx)
241 {
242 NTSTATUS status;
243 struct spoolss_GetPrinterDriverDirectory r;
244 struct {
245 uint16_t level;
246 const char *server;
247 } levels[] = {{
248 .level = 1,
249 .server = NULL
250 },{
251 .level = 1,
252 .server = ""
253 },{
254 .level = 78,
255 .server = ""
256 },{
257 .level = 1,
258 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
259 },{
260 .level = 1024,
261 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
262 }
263 };
264 int i;
265 uint32_t needed;
266
267 for (i=0;i<ARRAY_SIZE(levels);i++) {
268 int level = levels[i].level;
269 DATA_BLOB blob;
270
271 r.in.server = levels[i].server;
272 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
273 r.in.level = level;
274 r.in.buffer = NULL;
275 r.in.offered = 0;
276 r.out.needed = &needed;
277
278 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
279
280 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
281 torture_assert_ntstatus_ok(tctx, status,
282 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
283 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
284 "GetPrinterDriverDirectory unexpected return code");
285
286 blob = data_blob_talloc(ctx, NULL, needed);
287 data_blob_clear(&blob);
288 r.in.buffer = &blob;
289 r.in.offered = needed;
290
291 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
292 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
293
294 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
295 }
296
297 return true;
298 }
299
300 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
301 struct dcerpc_pipe *p,
302 struct test_spoolss_context *ctx)
303 {
304 NTSTATUS status;
305 struct spoolss_EnumPrinterDrivers r;
306 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
307 int i, j;
308
309 for (i=0;i<ARRAY_SIZE(levels);i++) {
310 int level = levels[i];
311 DATA_BLOB blob;
312 uint32_t needed;
313 uint32_t count;
314 union spoolss_DriverInfo *info;
315
316 /* FIXME: gd, come back and fix "" as server, and handle
317 * priority of returned error codes in torture test and samba 3
318 * server */
319
320 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
321 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
322 r.in.level = level;
323 r.in.buffer = NULL;
324 r.in.offered = 0;
325 r.out.needed = &needed;
326 r.out.count = &count;
327 r.out.info = &info;
328
329 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
330
331 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
332 torture_assert_ntstatus_ok(tctx, status,
333 "dcerpc_spoolss_EnumPrinterDrivers failed");
334 if (W_ERROR_IS_OK(r.out.result)) {
335 /* TODO: do some more checks here */
336 continue;
337 }
338 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
339 blob = data_blob_talloc(ctx, NULL, needed);
340 data_blob_clear(&blob);
341 r.in.buffer = &blob;
342 r.in.offered = needed;
343
344 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
345 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
346 }
347
348 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
349
350 ctx->driver_count[level] = count;
351 ctx->drivers[level] = info;
352 }
353
354 for (i=1;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 int old_level = levels[i-1];
357 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
358 "EnumPrinterDrivers invalid value");
359 }
360
361 for (i=0;i<ARRAY_SIZE(levels);i++) {
362 int level = levels[i];
363 for (j=0;j<ctx->driver_count[level];j++) {
364 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
365 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
366 switch (level) {
367 case 1:
368 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
369 break;
370 case 2:
371 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
372 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
373 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
374 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
375 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
376 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
377 break;
378 case 3:
379 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
380 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
381 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
382 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
383 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
384 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
385 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
386 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
387 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
388 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
389 break;
390 case 4:
391 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
392 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
393 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
394 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
395 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
396 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
397 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
398 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
399 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
400 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
401 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
402 break;
403 case 5:
404 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
405 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
406 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
407 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
408 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
409 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
410 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
411 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
412 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
413 break;
414 case 6:
415 /* level 6 is our reference, and it makes no sense to compare it to itself */
416 break;
417 }
418 }
419 }
420
421 return true;
422 }
423
424 static bool test_EnumMonitors(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
425 struct dcerpc_pipe *p,
426 struct test_spoolss_context *ctx)
427 {
428 NTSTATUS status;
429 struct spoolss_EnumMonitors r;
430 uint16_t levels[] = { 1, 2 };
431 int i, j;
432
433 for (i=0;i<ARRAY_SIZE(levels);i++) {
434 int level = levels[i];
435 DATA_BLOB blob;
436 uint32_t needed;
437 uint32_t count;
438 union spoolss_MonitorInfo *info;
439
440 r.in.servername = "";
441 r.in.level = level;
442 r.in.buffer = NULL;
443 r.in.offered = 0;
444 r.out.needed = &needed;
445 r.out.count = &count;
446 r.out.info = &info;
447
448 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
449
450 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
451 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
452 if (W_ERROR_IS_OK(r.out.result)) {
453 /* TODO: do some more checks here */
454 continue;
455 }
456 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
457 "EnumMonitors failed");
458
459 blob = data_blob_talloc(ctx, NULL, needed);
460 data_blob_clear(&blob);
461 r.in.buffer = &blob;
462 r.in.offered = needed;
463
464 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
465 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
466
467 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
468
469 ctx->monitor_count[level] = count;
470 ctx->monitors[level] = info;
471 }
472
473 for (i=1;i<ARRAY_SIZE(levels);i++) {
474 int level = levels[i];
475 int old_level = levels[i-1];
476 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
477 "EnumMonitors invalid value");
478 }
479
480 for (i=0;i<ARRAY_SIZE(levels);i++) {
481 int level = levels[i];
482 for (j=0;j<ctx->monitor_count[level];j++) {
483 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
484 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
485 switch (level) {
486 case 1:
487 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
488 break;
489 case 2:
490 /* level 2 is our reference, and it makes no sense to compare it to itself */
491 break;
492 }
493 }
494 }
495
496 return true;
497 }
498
499 static bool test_EnumPrintProcessors(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
500 struct dcerpc_pipe *p,
501 struct test_spoolss_context *ctx)
502 {
503 NTSTATUS status;
504 struct spoolss_EnumPrintProcessors r;
505 uint16_t levels[] = { 1 };
506 int i, j;
507
508 for (i=0;i<ARRAY_SIZE(levels);i++) {
509 int level = levels[i];
510 DATA_BLOB blob;
511 uint32_t needed;
512 uint32_t count;
513 union spoolss_PrintProcessorInfo *info;
514
515 r.in.servername = "";
516 r.in.environment = "Windows NT x86";
517 r.in.level = level;
518 r.in.buffer = NULL;
519 r.in.offered = 0;
520 r.out.needed = &needed;
521 r.out.count = &count;
522 r.out.info = &info;
523
524 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
525
526 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
527 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
528 if (W_ERROR_IS_OK(r.out.result)) {
529 /* TODO: do some more checks here */
530 continue;
531 }
532 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
533 "EnumPrintProcessors unexpected return code");
534
535 blob = data_blob_talloc(ctx, NULL, needed);
536 data_blob_clear(&blob);
537 r.in.buffer = &blob;
538 r.in.offered = needed;
539
540 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
541 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
542
543 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
544
545 ctx->print_processor_count[level] = count;
546 ctx->print_processors[level] = info;
547 }
548
549 for (i=1;i<ARRAY_SIZE(levels);i++) {
550 int level = levels[i];
551 int old_level = levels[i-1];
552 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
553 "EnumPrintProcessors failed");
554 }
555
556 for (i=0;i<ARRAY_SIZE(levels);i++) {
557 int level = levels[i];
558 for (j=0;j<ctx->print_processor_count[level];j++) {
559 #if 0
560 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
561 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
562 #endif
563 switch (level) {
564 case 1:
565 /* level 1 is our reference, and it makes no sense to compare it to itself */
566 break;
567 }
568 }
569 }
570
571 return true;
572 }
573
574 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
575 struct dcerpc_pipe *p,
576 struct test_spoolss_context *ctx)
577 {
578 NTSTATUS status;
579 struct spoolss_EnumPrintProcDataTypes r;
580 uint16_t levels[] = { 1 };
581 int i;
582
583 for (i=0;i<ARRAY_SIZE(levels);i++) {
584 int level = levels[i];
585 DATA_BLOB blob;
586 uint32_t needed;
587 uint32_t count;
588 union spoolss_PrintProcDataTypesInfo *info;
589
590 r.in.servername = "";
591 r.in.print_processor_name = "winprint";
592 r.in.level = level;
593 r.in.buffer = NULL;
594 r.in.offered = 0;
595 r.out.needed = &needed;
596 r.out.count = &count;
597 r.out.info = &info;
598
599 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
600
601 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
602 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
603 if (W_ERROR_IS_OK(r.out.result)) {
604 /* TODO: do some more checks here */
605 continue;
606 }
607 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
608 "EnumPrintProcDataTypes unexpected return code");
609
610 blob = data_blob_talloc(ctx, NULL, needed);
611 data_blob_clear(&blob);
612 r.in.buffer = &blob;
613 r.in.offered = needed;
614
615 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
616 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
617
618 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
619 }
620
621 return true;
622 }
623
624
625 static bool test_EnumPrinters(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
626 struct dcerpc_pipe *p,
627 struct test_spoolss_context *ctx)
628 {
629 struct spoolss_EnumPrinters r;
630 NTSTATUS status;
631 uint16_t levels[] = { 0, 1, 2, 4, 5 };
632 int i, j;
633
634 for (i=0;i<ARRAY_SIZE(levels);i++) {
635 int level = levels[i];
636 DATA_BLOB blob;
637 uint32_t needed;
638 uint32_t count;
639 union spoolss_PrinterInfo *info;
640
641 r.in.flags = PRINTER_ENUM_LOCAL;
642 r.in.server = "";
643 r.in.level = level;
644 r.in.buffer = NULL;
645 r.in.offered = 0;
646 r.out.needed = &needed;
647 r.out.count = &count;
648 r.out.info = &info;
649
650 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
651
652 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
653 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
654 if (W_ERROR_IS_OK(r.out.result)) {
655 /* TODO: do some more checks here */
656 continue;
657 }
658 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
659 "EnumPrinters unexpected return code");
660
661 blob = data_blob_talloc(ctx, NULL, needed);
662 data_blob_clear(&blob);
663 r.in.buffer = &blob;
664 r.in.offered = needed;
665
666 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
667 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
668
669 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
670
671 ctx->printer_count[level] = count;
672 ctx->printers[level] = info;
673 }
674
675 for (i=1;i<ARRAY_SIZE(levels);i++) {
676 int level = levels[i];
677 int old_level = levels[i-1];
678 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
679 "EnumPrinters invalid value");
680 }
681
682 for (i=0;i<ARRAY_SIZE(levels);i++) {
683 int level = levels[i];
684 for (j=0;j<ctx->printer_count[level];j++) {
685 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
686 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
687 switch (level) {
688 case 0:
689 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
690 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
691 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
692 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
693 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
694 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
695 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
696 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
697 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
698 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
699 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
700 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
701 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
702 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
703 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
704 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
705 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
706 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
707 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
708 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
709 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
710 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
711 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
712 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
713 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
714 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
715 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
716 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
718 break;
719 case 1:
720 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
721 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
722 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
723 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
724 break;
725 case 2:
726 /* level 2 is our reference, and it makes no sense to compare it to itself */
727 break;
728 case 4:
729 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
730 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
731 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
732 break;
733 case 5:
734 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
735 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
736 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
737 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
738 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
739 break;
740 }
741 }
742 }
743
744 /* TODO:
745 * - verify that the port of a printer was in the list returned by EnumPorts
746 */
747
748 return true;
749 }
750
751 static bool test_GetPrinter(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
752 struct dcerpc_pipe *p,
753 struct policy_handle *handle)
754 {
755 NTSTATUS status;
756 struct spoolss_GetPrinter r;
757 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
758 int i;
759 uint32_t needed;
760
761 for (i=0;i<ARRAY_SIZE(levels);i++) {
762 r.in.handle = handle;
763 r.in.level = levels[i];
764 r.in.buffer = NULL;
765 r.in.offered = 0;
766 r.out.needed = &needed;
767
768 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
769
770 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
771 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
772
773 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
774 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
775 data_blob_clear(&blob);
776 r.in.buffer = &blob;
777 r.in.offered = needed;
778 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
779 }
780
781 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
782
783 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
784 }
785
786 return true;
787 }
788
789
790 static bool test_ClosePrinter(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
791 struct dcerpc_pipe *p,
792 struct policy_handle *handle)
793 {
794 NTSTATUS status;
795 struct spoolss_ClosePrinter r;
796
797 r.in.handle = handle;
798 r.out.handle = handle;
799
800 torture_comment(tctx, "Testing ClosePrinter\n");
801
802 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
803 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
804
805 return true;
806 }
807
808 static bool test_GetForm(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
809 struct dcerpc_pipe *p,
810 struct policy_handle *handle,
811 const char *form_name,
812 uint32_t level)
813 {
814 NTSTATUS status;
815 struct spoolss_GetForm r;
816 uint32_t needed;
817
818 r.in.handle = handle;
819 r.in.form_name = form_name;
820 r.in.level = level;
821 r.in.buffer = NULL;
822 r.in.offered = 0;
823 r.out.needed = &needed;
824
825 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
826
827 status = dcerpc_spoolss_GetForm(p, tctx, &r);
828 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
829
830 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
831 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
832 data_blob_clear(&blob);
833 r.in.buffer = &blob;
834 r.in.offered = needed;
835 status = dcerpc_spoolss_GetForm(p, tctx, &r);
836 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
837
838 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
839
840 torture_assert(tctx, r.out.info, "No form info returned");
841 }
842
843 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
844
845 return true;
846 }
847
848 static bool test_EnumForms(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
849 struct dcerpc_pipe *p,
850 struct policy_handle *handle, bool print_server)
851 {
852 NTSTATUS status;
853 struct spoolss_EnumForms r;
854 bool ret = true;
855 uint32_t needed;
856 uint32_t count;
857 uint32_t levels[] = { 1, 2 };
858 int i;
859
860 for (i=0; i<ARRAY_SIZE(levels); i++) {
861
862 union spoolss_FormInfo *info;
863
864 r.in.handle = handle;
865 r.in.level = levels[i];
866 r.in.buffer = NULL;
867 r.in.offered = 0;
868 r.out.needed = &needed;
869 r.out.count = &count;
870 r.out.info = &info;
871
872 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
873
874 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
875 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
876
877 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
878 break;
879 }
880
881 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
882 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
883
884 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
885 int j;
886 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
887 data_blob_clear(&blob);
888 r.in.buffer = &blob;
889 r.in.offered = needed;
890
891 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
892
893 torture_assert(tctx, info, "No forms returned");
894
895 for (j = 0; j < count; j++) {
896 if (!print_server)
897 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
898 }
899 }
900
901 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
902
903 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
904 }
905
906 return true;
907 }
908
909 static bool test_DeleteForm(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
910 struct dcerpc_pipe *p,
911 struct policy_handle *handle,
912 const char *form_name)
913 {
914 NTSTATUS status;
915 struct spoolss_DeleteForm r;
916
917 r.in.handle = handle;
918 r.in.form_name = form_name;
919
920 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
921
922 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
923
924 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
925
926 return true;
927 }
928
929 static bool test_AddForm(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
930 struct dcerpc_pipe *p,
931 struct policy_handle *handle, bool print_server)
932 {
933 struct spoolss_AddForm r;
934 struct spoolss_AddFormInfo1 addform;
935 const char *form_name = "testform3";
936 NTSTATUS status;
937 bool ret = true;
938
939 r.in.handle = handle;
940 r.in.level = 1;
941 r.in.info.info1 = &addform;
942 addform.flags = SPOOLSS_FORM_USER;
943 addform.form_name = form_name;
944 addform.size.width = 50;
945 addform.size.height = 25;
946 addform.area.left = 5;
947 addform.area.top = 10;
948 addform.area.right = 45;
949 addform.area.bottom = 15;
950
951 status = dcerpc_spoolss_AddForm(p, tctx, &r);
952
953 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
954
955 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
956
957 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
958
959 {
960 struct spoolss_SetForm sf;
961 struct spoolss_AddFormInfo1 setform;
962
963 sf.in.handle = handle;
964 sf.in.form_name = form_name;
965 sf.in.level = 1;
966 sf.in.info.info1= &setform;
967 setform.flags = addform.flags;
968 setform.form_name = addform.form_name;
969 setform.size = addform.size;
970 setform.area = addform.area;
971
972 setform.size.width = 1234;
973
974 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
975
976 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
977
978 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
979 }
980
981 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
982
983 if (!test_DeleteForm(tctx, p, handle, form_name)) {
984 ret = false;
985 }
986
987 return ret;
988 }
989
990 static bool test_EnumPorts_old(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
991 struct dcerpc_pipe *p)
992 {
993 NTSTATUS status;
994 struct spoolss_EnumPorts r;
995 uint32_t needed;
996 uint32_t count;
997 union spoolss_PortInfo *info;
998
999 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1000 dcerpc_server_name(p));
1001 r.in.level = 2;
1002 r.in.buffer = NULL;
1003 r.in.offered = 0;
1004 r.out.needed = &needed;
1005 r.out.count = &count;
1006 r.out.info = &info;
1007
1008 torture_comment(tctx, "Testing EnumPorts\n");
1009
1010 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1011
1012 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1013
1014 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1015 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1016 data_blob_clear(&blob);
1017 r.in.buffer = &blob;
1018 r.in.offered = needed;
1019
1020 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1021 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1022
1023 torture_assert(tctx, info, "No ports returned");
1024 }
1025
1026 return true;
1027 }
1028
1029 static bool test_AddPort(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1030 struct dcerpc_pipe *p)
1031 {
1032 NTSTATUS status;
1033 struct spoolss_AddPort r;
1034
1035 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1036 dcerpc_server_name(p));
1037 r.in.unknown = 0;
1038 r.in.monitor_name = "foo";
1039
1040 torture_comment(tctx, "Testing AddPort\n");
1041
1042 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1043
1044 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1045
1046 /* win2k3 returns WERR_NOT_SUPPORTED */
1047
1048 #if 0
1049
1050 if (!W_ERROR_IS_OK(r.out.result)) {
1051 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1052 return false;
1053 }
1054
1055 #endif
1056
1057 return true;
1058 }
1059
1060 static bool test_GetJob(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1061 struct dcerpc_pipe *p,
1062 struct policy_handle *handle, uint32_t job_id)
1063 {
1064 NTSTATUS status;
1065 struct spoolss_GetJob r;
1066 uint32_t needed;
1067 uint32_t levels[] = {1, 2 /* 3, 4 */};
1068 uint32_t i;
1069
1070 r.in.handle = handle;
1071 r.in.job_id = job_id;
1072 r.in.level = 0;
1073 r.in.buffer = NULL;
1074 r.in.offered = 0;
1075 r.out.needed = &needed;
1076
1077 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1078
1079 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1080 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1081
1082 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1083
1084 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1085
1086 r.in.level = levels[i];
1087 r.in.offered = 0;
1088
1089 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1090 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1091
1092 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1093 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1094 data_blob_clear(&blob);
1095 r.in.buffer = &blob;
1096 r.in.offered = needed;
1097
1098 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1099 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1100
1101 }
1102 torture_assert(tctx, r.out.info, "No job info returned");
1103 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1104 }
1105
1106 return true;
1107 }
1108
1109 static bool test_SetJob(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1110 struct dcerpc_pipe *p,
1111 struct policy_handle *handle, uint32_t job_id,
1112 enum spoolss_JobControl command)
1113 {
1114 NTSTATUS status;
1115 struct spoolss_SetJob r;
1116
1117 r.in.handle = handle;
1118 r.in.job_id = job_id;
1119 r.in.ctr = NULL;
1120 r.in.command = command;
1121
1122 switch (command) {
1123 case SPOOLSS_JOB_CONTROL_PAUSE:
1124 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1125 break;
1126 case SPOOLSS_JOB_CONTROL_RESUME:
1127 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1128 break;
1129 case SPOOLSS_JOB_CONTROL_CANCEL:
1130 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1131 break;
1132 case SPOOLSS_JOB_CONTROL_RESTART:
1133 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1134 break;
1135 case SPOOLSS_JOB_CONTROL_DELETE:
1136 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1137 break;
1138 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1139 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1140 break;
1141 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1142 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1143 break;
1144 case SPOOLSS_JOB_CONTROL_RETAIN:
1145 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1146 break;
1147 case SPOOLSS_JOB_CONTROL_RELEASE:
1148 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1149 break;
1150 default:
1151 torture_comment(tctx, "Testing SetJob\n");
1152 break;
1153 }
1154
1155 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1156 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1157 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1158
1159 return true;
1160 }
1161
1162 static bool test_AddJob(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1163 struct dcerpc_pipe *p,
1164 struct policy_handle *handle)
1165 {
1166 NTSTATUS status;
1167 struct spoolss_AddJob r;
1168 uint32_t needed;
1169
1170 r.in.level = 0;
1171 r.in.handle = handle;
1172 r.in.offered = 0;
1173 r.out.needed = &needed;
1174 r.in.buffer = r.out.buffer = NULL;
1175
1176 torture_comment(tctx, "Testing AddJob\n");
1177
1178 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1179 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1180
1181 r.in.level = 1;
1182
1183 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1184 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1185
1186 return true;
1187 }
1188
1189
1190 static bool test_EnumJobs(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1191 struct dcerpc_pipe *p,
1192 struct policy_handle *handle)
1193 {
1194 NTSTATUS status;
1195 struct spoolss_EnumJobs r;
1196 uint32_t needed;
1197 uint32_t count;
1198 union spoolss_JobInfo *info;
1199
1200 r.in.handle = handle;
1201 r.in.firstjob = 0;
1202 r.in.numjobs = 0xffffffff;
1203 r.in.level = 1;
1204 r.in.buffer = NULL;
1205 r.in.offered = 0;
1206 r.out.needed = &needed;
1207 r.out.count = &count;
1208 r.out.info = &info;
1209
1210 torture_comment(tctx, "Testing EnumJobs\n");
1211
1212 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1213
1214 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1215
1216 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1217 int j;
1218 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1219 data_blob_clear(&blob);
1220 r.in.buffer = &blob;
1221 r.in.offered = needed;
1222
1223 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1224
1225 torture_assert(tctx, info, "No jobs returned");
1226
1227 for (j = 0; j < count; j++) {
1228
1229 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1230
1231 /* FIXME - gd */
1232 if (!torture_setting_bool(tctx, "samba3", false)) {
1233 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1234 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1235 }
1236 }
1237
1238 } else {
1239 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1240 }
1241
1242 return true;
1243 }
1244
1245 static bool test_DoPrintTest(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1246 struct dcerpc_pipe *p,
1247 struct policy_handle *handle)
1248 {
1249 bool ret = true;
1250 NTSTATUS status;
1251 struct spoolss_StartDocPrinter s;
1252 struct spoolss_DocumentInfo1 info1;
1253 struct spoolss_StartPagePrinter sp;
1254 struct spoolss_WritePrinter w;
1255 struct spoolss_EndPagePrinter ep;
1256 struct spoolss_EndDocPrinter e;
1257 int i;
1258 uint32_t job_id;
1259 uint32_t num_written;
1260
1261 torture_comment(tctx, "Testing StartDocPrinter\n");
1262
1263 s.in.handle = handle;
1264 s.in.level = 1;
1265 s.in.info.info1 = &info1;
1266 s.out.job_id = &job_id;
1267 info1.document_name = "TorturePrintJob";
1268 info1.output_file = NULL;
1269 info1.datatype = "RAW";
1270
1271 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1272 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1273 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1274
1275 for (i=1; i < 4; i++) {
1276 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1277
1278 sp.in.handle = handle;
1279
1280 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1281 torture_assert_ntstatus_ok(tctx, status,
1282 "dcerpc_spoolss_StartPagePrinter failed");
1283 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1284
1285 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1286
1287 w.in.handle = handle;
1288 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1289 w.out.num_written = &num_written;
1290
1291 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1292 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1293 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1294
1295 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1296
1297 ep.in.handle = handle;
1298
1299 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1300 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1301 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1302 }
1303
1304 torture_comment(tctx, "Testing EndDocPrinter\n");
1305
1306 e.in.handle = handle;
1307
1308 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1309 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1310 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1311
1312 ret &= test_AddJob(tctx, p, handle);
1313 ret &= test_EnumJobs(tctx, p, handle);
1314
1315 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1316
1317 return ret;
1318 }
1319
1320 static bool test_PausePrinter(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1321 struct dcerpc_pipe *p,
1322 struct policy_handle *handle)
1323 {
1324 NTSTATUS status;
1325 struct spoolss_SetPrinter r;
1326 struct spoolss_SetPrinterInfoCtr info_ctr;
1327 struct spoolss_DevmodeContainer devmode_ctr;
1328 struct sec_desc_buf secdesc_ctr;
1329
1330 info_ctr.level = 0;
1331 info_ctr.info.info0 = NULL;
1332
1333 ZERO_STRUCT(devmode_ctr);
1334 ZERO_STRUCT(secdesc_ctr);
1335
1336 r.in.handle = handle;
1337 r.in.info_ctr = &info_ctr;
1338 r.in.devmode_ctr = &devmode_ctr;
1339 r.in.secdesc_ctr = &secdesc_ctr;
1340 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1341
1342 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1343
1344 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1345
1346 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1347
1348 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1349
1350 return true;
1351 }
1352
1353 static bool test_ResumePrinter(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1354 struct dcerpc_pipe *p,
1355 struct policy_handle *handle)
1356 {
1357 NTSTATUS status;
1358 struct spoolss_SetPrinter r;
1359 struct spoolss_SetPrinterInfoCtr info_ctr;
1360 struct spoolss_DevmodeContainer devmode_ctr;
1361 struct sec_desc_buf secdesc_ctr;
1362
1363 info_ctr.level = 0;
1364 info_ctr.info.info0 = NULL;
1365
1366 ZERO_STRUCT(devmode_ctr);
1367 ZERO_STRUCT(secdesc_ctr);
1368
1369 r.in.handle = handle;
1370 r.in.info_ctr = &info_ctr;
1371 r.in.devmode_ctr = &devmode_ctr;
1372 r.in.secdesc_ctr = &secdesc_ctr;
1373 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
1374
1375 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1376
1377 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1378
1379 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1380
1381 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1382
1383 return true;
1384 }
1385
1386 static bool test_GetPrinterData(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1387 struct dcerpc_pipe *p,
1388 struct policy_handle *handle,
1389 const char *value_name)
1390 {
1391 NTSTATUS status;
1392 struct spoolss_GetPrinterData r;
1393 uint32_t needed;
1394 enum winreg_Type type;
1395 union spoolss_PrinterData data;
1396
1397 r.in.handle = handle;
1398 r.in.value_name = value_name;
1399 r.in.offered = 0;
1400 r.out.needed = &needed;
1401 r.out.type = &type;
1402 r.out.data = &data;
1403
1404 torture_comment(tctx, "Testing GetPrinterData\n");
1405
1406 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1407 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1408
1409 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1410 r.in.offered = needed;
1411
1412 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1413 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1414
1415 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1416 }
1417
1418 return true;
1419 }
1420
1421 static bool test_GetPrinterDataEx(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1422 struct dcerpc_pipe *p,
1423 struct policy_handle *handle,
1424 const char *key_name,
1425 const char *value_name)
1426 {
1427 NTSTATUS status;
1428 struct spoolss_GetPrinterDataEx r;
1429 enum winreg_Type type;
1430 uint32_t needed;
1431
1432 r.in.handle = handle;
1433 r.in.key_name = key_name;
1434 r.in.value_name = value_name;
1435 r.in.offered = 0;
1436 r.out.type = &type;
1437 r.out.needed = &needed;
1438 r.out.buffer = NULL;
1439
1440 torture_comment(tctx, "Testing GetPrinterDataEx\n");
1441
1442 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1445 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1446 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1447 }
1448 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1449 }
1450
1451 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1452 r.in.offered = needed;
1453 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1454
1455 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1456 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1457
1458 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
1459 }
1460
1461 return true;
1462 }
1463
1464 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
/* [<][>][^][v][top][bottom][index][help] */
1465 struct policy_handle *handle)
1466 {
1467 NTSTATUS status;
1468 struct spoolss_EnumPrinterData r;
1469
1470 ZERO_STRUCT(r);
1471 r.in.handle = handle;
1472 r.in.enum_index = 0;
1473
1474 do {
1475 uint32_t value_size = 0;
1476 uint32_t data_size = 0;
1477 enum winreg_Type type = 0;
1478
1479 r.in.value_offered = value_size;
1480 r.out.value_needed = &value_size;
1481 r.in.data_offered = data_size;
1482 r.out.data_needed = &data_size;
1483
1484 r.out.type = &type;
1485 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1486
1487 torture_comment(tctx, "Testing EnumPrinterData\n");
1488
1489 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1490
1491 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1492
1493 r.in.value_offered = value_size;
1494 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1495 r.in.data_offered = data_size;
1496 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1497
1498 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1499
1500 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1501
1502 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1503
1504 test_GetPrinterDataEx(tctx,
1505 p, handle, "PrinterDriverData",
1506 r.out.value_name);
1507
1508 r.in.enum_index++;
1509
1510 } while (W_ERROR_IS_OK(r.out.result));
1511
1512 return true;
1513 }
1514
1515 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1516 struct dcerpc_pipe *p,
1517 struct policy_handle *handle)
1518 {
1519 NTSTATUS status;
1520 struct spoolss_EnumPrinterDataEx r;
1521 struct spoolss_PrinterEnumValues *info;
1522 uint32_t needed;
1523 uint32_t count;
1524
1525 r.in.handle = handle;
1526 r.in.key_name = "PrinterDriverData";
1527 r.in.offered = 0;
1528 r.out.needed = &needed;
1529 r.out.count = &count;
1530 r.out.info = &info;
1531
1532 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1533
1534 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1535 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1536
1537 r.in.offered = needed;
1538
1539 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1540
1541 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1542
1543 return true;
1544 }
1545
1546
1547 static bool test_DeletePrinterData(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1548 struct dcerpc_pipe *p,
1549 struct policy_handle *handle,
1550 const char *value_name)
1551 {
1552 NTSTATUS status;
1553 struct spoolss_DeletePrinterData r;
1554
1555 r.in.handle = handle;
1556 r.in.value_name = value_name;
1557
1558 torture_comment(tctx, "Testing DeletePrinterData\n");
1559
1560 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1561
1562 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1563
1564 return true;
1565 }
1566
1567 static bool test_SetPrinterData(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1568 struct dcerpc_pipe *p,
1569 struct policy_handle *handle)
1570 {
1571 NTSTATUS status;
1572 struct spoolss_SetPrinterData r;
1573 const char *value_name = "spottyfoot";
1574
1575 r.in.handle = handle;
1576 r.in.value_name = value_name;
1577 r.in.type = REG_SZ;
1578 r.in.data.string = "dog";
1579
1580 torture_comment(tctx, "Testing SetPrinterData\n");
1581
1582 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1583
1584 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1585
1586 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1587 return false;
1588 }
1589
1590 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1591 return false;
1592 }
1593
1594 return true;
1595 }
1596
1597 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1598 struct dcerpc_pipe *p,
1599 struct policy_handle *handle)
1600 {
1601 NTSTATUS status;
1602 struct dcerpc_binding *b;
1603 struct dcerpc_pipe *p2;
1604 struct spoolss_ClosePrinter cp;
1605
1606 /* only makes sense on SMB */
1607 if (p->conn->transport.transport != NCACN_NP) {
1608 return true;
1609 }
1610
1611 torture_comment(tctx, "testing close on secondary pipe\n");
1612
1613 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1614 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1615
1616 status = dcerpc_secondary_connection(p, &p2, b);
1617 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1618
1619 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1620 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1621
1622 cp.in.handle = handle;
1623 cp.out.handle = handle;
1624
1625 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1626 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1627 "ERROR: Allowed close on secondary connection");
1628
1629 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1630 "Unexpected fault code");
1631
1632 talloc_free(p2);
1633
1634 return true;
1635 }
1636
1637 static bool test_OpenPrinter_badname(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1638 struct dcerpc_pipe *p, const char *name)
1639 {
1640 NTSTATUS status;
1641 struct spoolss_OpenPrinter op;
1642 struct spoolss_OpenPrinterEx opEx;
1643 struct policy_handle handle;
1644 bool ret = true;
1645
1646 op.in.printername = name;
1647 op.in.datatype = NULL;
1648 op.in.devmode_ctr.devmode= NULL;
1649 op.in.access_mask = 0;
1650 op.out.handle = &handle;
1651
1652 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1653
1654 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1655 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1656 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1657 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1658 name, win_errstr(op.out.result));
1659 }
1660
1661 if (W_ERROR_IS_OK(op.out.result)) {
1662 ret &=test_ClosePrinter(tctx, p, &handle);
1663 }
1664
1665 opEx.in.printername = name;
1666 opEx.in.datatype = NULL;
1667 opEx.in.devmode_ctr.devmode = NULL;
1668 opEx.in.access_mask = 0;
1669 opEx.in.level = 1;
1670 opEx.in.userlevel.level1 = NULL;
1671 opEx.out.handle = &handle;
1672
1673 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1674
1675 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1676 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1677 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1678 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1679 name, win_errstr(opEx.out.result));
1680 }
1681
1682 if (W_ERROR_IS_OK(opEx.out.result)) {
1683 ret &=test_ClosePrinter(tctx, p, &handle);
1684 }
1685
1686 return ret;
1687 }
1688
1689 static bool test_OpenPrinter(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1690 struct dcerpc_pipe *p,
1691 const char *name)
1692 {
1693 NTSTATUS status;
1694 struct spoolss_OpenPrinter r;
1695 struct policy_handle handle;
1696 bool ret = true;
1697
1698 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1699 r.in.datatype = NULL;
1700 r.in.devmode_ctr.devmode= NULL;
1701 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1702 r.out.handle = &handle;
1703
1704 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1705
1706 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1707
1708 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1709
1710 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1711
1712 if (!test_GetPrinter(tctx, p, &handle)) {
1713 ret = false;
1714 }
1715
1716 if (!torture_setting_bool(tctx, "samba3", false)) {
1717 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1718 ret = false;
1719 }
1720 }
1721
1722 if (!test_ClosePrinter(tctx, p, &handle)) {
1723 ret = false;
1724 }
1725
1726 return ret;
1727 }
1728
1729 static bool call_OpenPrinterEx(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1730 struct dcerpc_pipe *p,
1731 const char *name, struct policy_handle *handle)
1732 {
1733 struct spoolss_OpenPrinterEx r;
1734 struct spoolss_UserLevel1 userlevel1;
1735 NTSTATUS status;
1736
1737 if (name && name[0]) {
1738 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1739 dcerpc_server_name(p), name);
1740 } else {
1741 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1742 dcerpc_server_name(p));
1743 }
1744
1745 r.in.datatype = NULL;
1746 r.in.devmode_ctr.devmode= NULL;
1747 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1748 r.in.level = 1;
1749 r.in.userlevel.level1 = &userlevel1;
1750 r.out.handle = handle;
1751
1752 userlevel1.size = 1234;
1753 userlevel1.client = "hello";
1754 userlevel1.user = "spottyfoot!";
1755 userlevel1.build = 1;
1756 userlevel1.major = 2;
1757 userlevel1.minor = 3;
1758 userlevel1.processor = 4;
1759
1760 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1761
1762 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1763
1764 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1765
1766 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1767
1768 return true;
1769 }
1770
1771 static bool test_OpenPrinterEx(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1772 struct dcerpc_pipe *p,
1773 const char *name)
1774 {
1775 struct policy_handle handle;
1776 bool ret = true;
1777
1778 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1779 return false;
1780 }
1781
1782 if (!test_GetPrinter(tctx, p, &handle)) {
1783 ret = false;
1784 }
1785
1786 if (!test_EnumForms(tctx, p, &handle, false)) {
1787 ret = false;
1788 }
1789
1790 if (!test_AddForm(tctx, p, &handle, false)) {
1791 ret = false;
1792 }
1793
1794 if (!test_EnumPrinterData(tctx, p, &handle)) {
1795 ret = false;
1796 }
1797
1798 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1799 ret = false;
1800 }
1801
1802 if (!test_PausePrinter(tctx, p, &handle)) {
1803 ret = false;
1804 }
1805
1806 if (!test_DoPrintTest(tctx, p, &handle)) {
1807 ret = false;
1808 }
1809
1810 if (!test_ResumePrinter(tctx, p, &handle)) {
1811 ret = false;
1812 }
1813
1814 if (!test_SetPrinterData(tctx, p, &handle)) {
1815 ret = false;
1816 }
1817
1818 if (!torture_setting_bool(tctx, "samba3", false)) {
1819 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1820 ret = false;
1821 }
1822 }
1823
1824 if (!test_ClosePrinter(tctx, p, &handle)) {
1825 ret = false;
1826 }
1827
1828 return ret;
1829 }
1830
1831 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
/* [<][>][^][v][top][bottom][index][help] */
1832 {
1833 struct spoolss_EnumPrinters r;
1834 NTSTATUS status;
1835 uint16_t levels[] = {1, 2, 4, 5};
1836 int i;
1837 bool ret = true;
1838
1839 for (i=0;i<ARRAY_SIZE(levels);i++) {
1840 union spoolss_PrinterInfo *info;
1841 int j;
1842 uint32_t needed;
1843 uint32_t count;
1844
1845 r.in.flags = PRINTER_ENUM_LOCAL;
1846 r.in.server = "";
1847 r.in.level = levels[i];
1848 r.in.buffer = NULL;
1849 r.in.offered = 0;
1850 r.out.needed = &needed;
1851 r.out.count = &count;
1852 r.out.info = &info;
1853
1854 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1855
1856 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1857 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1858
1859 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1860 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1861 data_blob_clear(&blob);
1862 r.in.buffer = &blob;
1863 r.in.offered = needed;
1864 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1865 }
1866
1867 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1868
1869 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1870
1871 if (!info) {
1872 torture_comment(tctx, "No printers returned\n");
1873 return true;
1874 }
1875
1876 for (j=0;j<count;j++) {
1877 if (r.in.level == 1) {
1878 char *unc = talloc_strdup(tctx, info[j].info1.name);
1879 char *slash, *name;
1880 name = unc;
1881 if (unc[0] == '\\' && unc[1] == '\\') {
1882 unc +=2;
1883 }
1884 slash = strchr(unc, '\\');
1885 if (slash) {
1886 slash++;
1887 name = slash;
1888 }
1889 if (!test_OpenPrinter(tctx, p, name)) {
1890 ret = false;
1891 }
1892 if (!test_OpenPrinterEx(tctx, p, name)) {
1893 ret = false;
1894 }
1895 }
1896 }
1897 }
1898
1899 return ret;
1900 }
1901
1902 #if 0
1903 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
/* [<][>][^][v][top][bottom][index][help] */
1904 struct policy_handle *handle,
1905 const char *driver_name)
1906 {
1907 NTSTATUS status;
1908 struct spoolss_GetPrinterDriver2 r;
1909 uint32_t needed;
1910 uint32_t server_major_version;
1911 uint32_t server_minor_version;
1912
1913 r.in.handle = handle;
1914 r.in.architecture = "W32X86";
1915 r.in.level = 1;
1916 r.in.buffer = NULL;
1917 r.in.offered = 0;
1918 r.in.client_major_version = 0;
1919 r.in.client_minor_version = 0;
1920 r.out.needed = &needed;
1921 r.out.server_major_version = &server_major_version;
1922 r.out.server_minor_version = &server_minor_version;
1923
1924 printf("Testing GetPrinterDriver2\n");
1925
1926 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1927 if (!NT_STATUS_IS_OK(status)) {
1928 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1929 return false;
1930 }
1931
1932 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1933 r.in.offered = needed;
1934 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1935 }
1936
1937 if (!NT_STATUS_IS_OK(status)) {
1938 printf("GetPrinterDriver2 failed - %s\n",
1939 nt_errstr(status));
1940 return false;
1941 }
1942
1943 if (!W_ERROR_IS_OK(r.out.result)) {
1944 printf("GetPrinterDriver2 failed - %s\n",
1945 win_errstr(r.out.result));
1946 return false;
1947 }
1948
1949 return true;
1950 }
1951 #endif
1952
1953 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
/* [<][>][^][v][top][bottom][index][help] */
1954 struct dcerpc_pipe *p)
1955 {
1956 struct spoolss_EnumPrinterDrivers r;
1957 NTSTATUS status;
1958 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1959 int i;
1960
1961 for (i=0;i<ARRAY_SIZE(levels);i++) {
1962
1963 uint32_t needed;
1964 uint32_t count;
1965 union spoolss_DriverInfo *info;
1966
1967 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1968 r.in.environment = "Windows NT x86";
1969 r.in.level = levels[i];
1970 r.in.buffer = NULL;
1971 r.in.offered = 0;
1972 r.out.needed = &needed;
1973 r.out.count = &count;
1974 r.out.info = &info;
1975
1976 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1977
1978 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1979
1980 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1981
1982 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1983 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1984 data_blob_clear(&blob);
1985 r.in.buffer = &blob;
1986 r.in.offered = needed;
1987 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1988 }
1989
1990 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1991
1992 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1993
1994 if (!info) {
1995 torture_comment(tctx, "No printer drivers returned\n");
1996 break;
1997 }
1998 }
1999
2000 return true;
2001 }
2002
2003 bool torture_rpc_spoolss(struct torture_context *torture)
/* [<][>][^][v][top][bottom][index][help] */
2004 {
2005 NTSTATUS status;
2006 struct dcerpc_pipe *p;
2007 bool ret = true;
2008 struct test_spoolss_context *ctx;
2009
2010 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 return false;
2013 }
2014
2015 ctx = talloc_zero(torture, struct test_spoolss_context);
2016
2017 ret &= test_OpenPrinter_server(torture, p, ctx);
2018
2019 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2020 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2021 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2022 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2023 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2024 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2025 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2026 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2027 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2028 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2029 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2030 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2031 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2032 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2033 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2034 ret &= test_EnumPorts(torture, p, ctx);
2035 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2036 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2037 ret &= test_EnumPrinterDrivers(torture, p, ctx);
2038 ret &= test_EnumMonitors(torture, p, ctx);
2039 ret &= test_EnumPrintProcessors(torture, p, ctx);
2040 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2041 ret &= test_EnumPrinters(torture, p, ctx);
2042 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2043 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2044 ret &= test_OpenPrinter_badname(torture, p, "");
2045 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2046 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2047 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2048 ret &= test_OpenPrinter_badname(torture, p,
2049 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2050
2051
2052 ret &= test_AddPort(torture, p);
2053 ret &= test_EnumPorts_old(torture, p);
2054 ret &= test_EnumPrinters_old(torture, p);
2055 ret &= test_EnumPrinterDrivers_old(torture, p);
2056
2057 return ret;
2058 }