r6195: I think Metze meant SPOOLSS_ARCHITECTURE_NT_X86, but I could be wrong.
[Samba.git] / source4 / torture / rpc / spoolss.c
blobcc22db42bd369361d493a9d832becb1d4b80882e
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
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_spoolss.h"
26 struct test_spoolss_context {
27 struct dcerpc_pipe *p;
29 /* print server handle */
30 struct policy_handle server_handle;
32 /* for EnumPorts */
33 uint32_t port_count[3];
34 union spoolss_PortInfo **ports[3];
36 /* for EnumPrinterDrivers */
37 uint32_t driver_count[7];
38 union spoolss_DriverInfo **drivers[7];
40 /* for EnumMonitors */
41 uint32_t monitor_count[3];
42 union spoolss_MonitorInfo **monitors[3];
44 /* for EnumPrintProcessors */
45 uint32_t print_processor_count[2];
46 union spoolss_PrintProcessorInfo **print_processors[2];
48 /* for EnumPrinters */
49 uint32_t printer_count[6];
50 union spoolss_PrinterInfo **printers[6];
53 #define COMPARE_STRING(c,r,e) do {\
54 BOOL _ok = True;\
55 if (c.e && !r.e) _ok = False;\
56 if (!c.e && r.e) _ok = False;\
57 if (c.e && r.e && strcmp_safe(c.e, r.e) != 0) _ok = False;\
58 if (!_ok){\
59 printf("%s: " #c "." #e " [%s] doesn't match " #r "." #e " [%s]\n",\
60 __location__, c.e, r.e);\
61 ret = False;\
63 } while(0)
65 #define COMPARE_UINT16(c,r,e) do {\
66 if (c.e != r.e){\
67 printf("%s: " #c "." #e " 0x%08X (%u) doesn't match " #r "." #e " 0x%08X (%u)\n",\
68 __location__, c.e, c.e, r.e, r.e);\
69 ret = False;\
71 } while(0)
73 #define COMPARE_UINT32(c,r,e) do {\
74 if (c.e != r.e){\
75 printf("%s: " #c "." #e " 0x%04X (%u) doesn't match " #r "." #e " 0x%04X (%u)\n",\
76 __location__, c.e, c.e, r.e, r.e);\
77 ret = False;\
79 } while(0)
81 #define COMPARE_UINT64(c,r,e) do {\
82 if (c.e != r.e){\
83 printf("%s: " #c "." #e " 0x%08X%08X (%llu) doesn't match " #r "." #e " 0x%08X%08X (%llu)\n",\
84 __location__, (uint32_t)(c.e >> 32), (uint32_t)(c.e & 0xFFFFFFFF), c.e,\
85 (uint32_t)(r.e >> 32), (uint32_t)(r.e & 0xFFFFFFFF), r.e);\
86 ret = False;\
88 } while(0)
90 /* TODO: ! */
91 #define COMPARE_SEC_DESC(c,r,e)
92 #define COMPARE_SPOOLSS_TIME(c,r,e)
93 #define COMPARE_STRING_ARRAY(c,r,e)
95 static BOOL test_OpenPrinter_server(struct test_spoolss_context *ctx)
97 NTSTATUS status;
98 struct spoolss_OpenPrinter op;
99 BOOL ret = True;
101 op.in.printername = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p));
102 op.in.datatype = NULL;
103 op.in.devmode_ctr.size = 0;
104 op.in.devmode_ctr.devmode= NULL;
105 op.in.access_mask = 0;
106 op.out.handle = &ctx->server_handle;
108 printf("\nTesting OpenPrinter(%s)\n", op.in.printername);
110 status = dcerpc_spoolss_OpenPrinter(ctx->p, ctx, &op);
111 if (!NT_STATUS_IS_OK(status)) {
112 printf("dcerpc_spoolss_OpenPrinter failed - %s\n", nt_errstr(status));
113 ret = False;
115 if (!W_ERROR_IS_OK(op.out.result)) {
116 printf("OpenPrinter(%s) failed - %s\n",
117 op.in.printername, win_errstr(op.out.result));
118 ret = False;
121 return ret;
124 static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
126 NTSTATUS status;
127 struct spoolss_EnumPorts r;
128 uint16_t levels[] = { 1, 2 };
129 int i, j;
130 BOOL ret = True;
132 for (i=0;i<ARRAY_SIZE(levels);i++) {
133 int level = levels[i];
134 DATA_BLOB blob;
135 uint32_t buf_size = 0;
137 r.in.servername = "";
138 r.in.level = level;
139 r.in.buffer = NULL;
140 buf_size = 0;
141 r.in.buf_size = &buf_size;
142 r.out.buf_size = &buf_size;
144 printf("Testing EnumPorts level %u\n", r.in.level);
146 status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r);
147 if (!NT_STATUS_IS_OK(status)) {
148 printf("dcerpc_spoolss_EnumPorts failed - %s\n", nt_errstr(status));
149 ret = False;
150 continue;
153 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
154 printf("EnumPorts unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
155 win_errstr(r.out.result));
156 ret = False;
157 continue;
160 blob = data_blob_talloc(ctx, NULL, buf_size);
161 data_blob_clear(&blob);
162 r.in.buffer = &blob;
164 status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r);
165 if (!NT_STATUS_IS_OK(status)) {
166 printf("dcerpc_spoolss_EnumPorts failed - %s\n", nt_errstr(status));
167 ret = False;
168 continue;
171 if (!W_ERROR_IS_OK(r.out.result)) {
172 printf("EnumPorts failed - %s\n",
173 win_errstr(r.out.result));
174 ret = False;
175 continue;
178 ctx->port_count[level] = r.out.count;
179 ctx->ports[level] = r.out.info;
182 for (i=1;i<ARRAY_SIZE(levels);i++) {
183 int level = levels[i];
184 int old_level = levels[i-1];
185 if (ctx->port_count[level] != ctx->port_count[old_level]) {
186 printf("EnumPorts level[%d] returns [%u] ports, but level[%d] returns [%u]\n",
187 level, ctx->port_count[level], old_level, ctx->port_count[old_level]);
188 ret = False;
191 /* if the array sizes are not the same we would maybe segfault in the following code */
192 if (!ret) return ret;
194 for (i=0;i<ARRAY_SIZE(levels);i++) {
195 int level = levels[i];
196 for (j=0;j<ctx->port_count[level];j++) {
197 union spoolss_PortInfo *cur = &ctx->ports[level][0][j];
198 union spoolss_PortInfo *ref = &ctx->ports[2][0][j];
199 switch (level) {
200 case 1:
201 COMPARE_STRING(cur->info1, ref->info2, port_name);
202 break;
203 case 2:
204 /* level 2 is our reference, and it makes no sense to compare it to itself */
205 break;
210 return True;
213 static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
215 NTSTATUS status;
216 struct spoolss_EnumPrinterDrivers r;
217 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
218 int i, j;
219 BOOL ret = True;
221 for (i=0;i<ARRAY_SIZE(levels);i++) {
222 int level = levels[i];
223 DATA_BLOB blob;
224 uint32_t buf_size = 0;
226 r.in.server = "";
227 r.in.environment = "Windows NT x86";
228 r.in.level = level;
229 r.in.buffer = NULL;
230 buf_size = 0;
231 r.in.buf_size = &buf_size;
232 r.out.buf_size = &buf_size;
234 printf("Testing EnumPrinterDrivers level %u\n", r.in.level);
236 status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r);
237 if (!NT_STATUS_IS_OK(status)) {
238 printf("dcerpc_spoolss_EnumPrinterDrivers failed - %s\n", nt_errstr(status));
239 ret = False;
240 continue;
243 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
244 printf("EnumPrinterDrivers unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
245 win_errstr(r.out.result));
246 ret = False;
247 continue;
250 blob = data_blob_talloc(ctx, NULL, buf_size);
251 data_blob_clear(&blob);
252 r.in.buffer = &blob;
254 status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r);
255 if (!NT_STATUS_IS_OK(status)) {
256 printf("dcerpc_spoolss_EnumPrinterDrivers failed - %s\n", nt_errstr(status));
257 ret = False;
258 continue;
261 if (!W_ERROR_IS_OK(r.out.result)) {
262 printf("EnumPrinterDrivers failed - %s\n",
263 win_errstr(r.out.result));
264 ret = False;
265 continue;
268 ctx->driver_count[level] = r.out.count;
269 ctx->drivers[level] = r.out.info;
272 for (i=1;i<ARRAY_SIZE(levels);i++) {
273 int level = levels[i];
274 int old_level = levels[i-1];
275 if (ctx->driver_count[level] != ctx->driver_count[old_level]) {
276 printf("EnumPrinterDrivers level[%d] returns [%u] drivers, but level[%d] returns [%u]\n",
277 level, ctx->driver_count[level], old_level, ctx->driver_count[old_level]);
278 ret = False;
281 /* if the array sizes are not the same we would maybe segfault in the following code */
282 if (!ret) return ret;
284 for (i=0;i<ARRAY_SIZE(levels);i++) {
285 int level = levels[i];
286 for (j=0;j<ctx->driver_count[level];j++) {
287 union spoolss_DriverInfo *cur = &ctx->drivers[level][0][j];
288 union spoolss_DriverInfo *ref = &ctx->drivers[6][0][j];
289 switch (level) {
290 case 1:
291 COMPARE_STRING(cur->info1, ref->info6, driver_name);
292 break;
293 case 2:
294 COMPARE_UINT32(cur->info2, ref->info6, version);
295 COMPARE_STRING(cur->info2, ref->info6, driver_name);
296 COMPARE_STRING(cur->info2, ref->info6, architecture);
297 COMPARE_STRING(cur->info2, ref->info6, driver_path);
298 COMPARE_STRING(cur->info2, ref->info6, data_file);
299 COMPARE_STRING(cur->info2, ref->info6, config_file);
300 break;
301 case 3:
302 COMPARE_UINT32(cur->info3, ref->info6, version);
303 COMPARE_STRING(cur->info3, ref->info6, driver_name);
304 COMPARE_STRING(cur->info3, ref->info6, architecture);
305 COMPARE_STRING(cur->info3, ref->info6, driver_path);
306 COMPARE_STRING(cur->info3, ref->info6, data_file);
307 COMPARE_STRING(cur->info3, ref->info6, config_file);
308 COMPARE_STRING(cur->info3, ref->info6, help_file);
309 COMPARE_STRING_ARRAY(cur->info3, ref->info6, dependent_files);
310 COMPARE_STRING(cur->info3, ref->info6, monitor_name);
311 COMPARE_STRING(cur->info3, ref->info6, default_datatype);
312 break;
313 case 4:
314 COMPARE_UINT32(cur->info4, ref->info6, version);
315 COMPARE_STRING(cur->info4, ref->info6, driver_name);
316 COMPARE_STRING(cur->info4, ref->info6, architecture);
317 COMPARE_STRING(cur->info4, ref->info6, driver_path);
318 COMPARE_STRING(cur->info4, ref->info6, data_file);
319 COMPARE_STRING(cur->info4, ref->info6, config_file);
320 COMPARE_STRING(cur->info4, ref->info6, help_file);
321 COMPARE_STRING_ARRAY(cur->info4, ref->info6, dependent_files);
322 COMPARE_STRING(cur->info4, ref->info6, monitor_name);
323 COMPARE_STRING(cur->info4, ref->info6, default_datatype);
324 COMPARE_STRING_ARRAY(cur->info4, ref->info6, previous_names);
325 break;
326 case 5:
327 COMPARE_UINT32(cur->info5, ref->info6, version);
328 COMPARE_STRING(cur->info5, ref->info6, driver_name);
329 COMPARE_STRING(cur->info5, ref->info6, architecture);
330 COMPARE_STRING(cur->info5, ref->info6, driver_path);
331 COMPARE_STRING(cur->info5, ref->info6, data_file);
332 COMPARE_STRING(cur->info5, ref->info6, config_file);
333 /*COMPARE_UINT32(cur->info5, ref->info6, driver_attributes);*/
334 /*COMPARE_UINT32(cur->info5, ref->info6, config_version);*/
335 /*TODO: ! COMPARE_UINT32(cur->info5, ref->info6, driver_version); */
336 break;
337 case 6:
338 /* level 6 is our reference, and it makes no sense to compare it to itself */
339 break;
344 return ret;
347 static BOOL test_EnumMonitors(struct test_spoolss_context *ctx)
349 NTSTATUS status;
350 struct spoolss_EnumMonitors r;
351 uint16_t levels[] = { 1, 2 };
352 int i, j;
353 BOOL ret = True;
355 for (i=0;i<ARRAY_SIZE(levels);i++) {
356 int level = levels[i];
357 DATA_BLOB blob;
358 uint32_t buf_size = 0;
360 r.in.servername = "";
361 r.in.level = level;
362 r.in.buffer = NULL;
363 buf_size = 0;
364 r.in.buf_size = &buf_size;
365 r.out.buf_size = &buf_size;
367 printf("Testing EnumMonitors level %u\n", r.in.level);
369 status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r);
370 if (!NT_STATUS_IS_OK(status)) {
371 printf("dcerpc_spoolss_EnumMonitors failed - %s\n", nt_errstr(status));
372 ret = False;
373 continue;
376 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
377 printf("EnumMonitors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
378 win_errstr(r.out.result));
379 ret = False;
380 continue;
383 blob = data_blob_talloc(ctx, NULL, buf_size);
384 data_blob_clear(&blob);
385 r.in.buffer = &blob;
387 status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r);
388 if (!NT_STATUS_IS_OK(status)) {
389 printf("dcerpc_spoolss_EnumMonitors failed - %s\n", nt_errstr(status));
390 ret = False;
391 continue;
394 if (!W_ERROR_IS_OK(r.out.result)) {
395 printf("EnumMonitors failed - %s\n",
396 win_errstr(r.out.result));
397 ret = False;
398 continue;
401 ctx->monitor_count[level] = r.out.count;
402 ctx->monitors[level] = r.out.info;
405 for (i=1;i<ARRAY_SIZE(levels);i++) {
406 int level = levels[i];
407 int old_level = levels[i-1];
408 if (ctx->monitor_count[level] != ctx->monitor_count[old_level]) {
409 printf("EnumMonitors level[%d] returns [%u] monitors, but level[%d] returns [%u]\n",
410 level, ctx->monitor_count[level], old_level, ctx->monitor_count[old_level]);
411 ret = False;
414 /* if the array sizes are not the same we would maybe segfault in the following code */
415 if (!ret) return ret;
417 for (i=0;i<ARRAY_SIZE(levels);i++) {
418 int level = levels[i];
419 for (j=0;j<ctx->monitor_count[level];j++) {
420 union spoolss_MonitorInfo *cur = &ctx->monitors[level][0][j];
421 union spoolss_MonitorInfo *ref = &ctx->monitors[2][0][j];
422 switch (level) {
423 case 1:
424 COMPARE_STRING(cur->info1, ref->info2, monitor_name);
425 break;
426 case 2:
427 /* level 2 is our reference, and it makes no sense to compare it to itself */
428 break;
433 return ret;
436 static BOOL test_EnumPrintProcessors(struct test_spoolss_context *ctx)
438 NTSTATUS status;
439 struct spoolss_EnumPrintProcessors r;
440 uint16_t levels[] = { 1 };
441 int i, j;
442 BOOL ret = True;
444 for (i=0;i<ARRAY_SIZE(levels);i++) {
445 int level = levels[i];
446 DATA_BLOB blob;
447 uint32_t buf_size = 0;
449 r.in.servername = "";
450 r.in.environment = "Windows NT x86";
451 r.in.level = level;
452 r.in.buffer = NULL;
453 buf_size = 0;
454 r.in.buf_size = &buf_size;
455 r.out.buf_size = &buf_size;
457 printf("Testing EnumPrintProcessors level %u\n", r.in.level);
459 status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r);
460 if (!NT_STATUS_IS_OK(status)) {
461 printf("dcerpc_spoolss_EnumPrintProcessors failed - %s\n", nt_errstr(status));
462 ret = False;
463 continue;
466 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
467 printf("EnumPrintProcessors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
468 win_errstr(r.out.result));
469 ret = False;
470 continue;
473 blob = data_blob_talloc(ctx, NULL, buf_size);
474 data_blob_clear(&blob);
475 r.in.buffer = &blob;
477 status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r);
478 if (!NT_STATUS_IS_OK(status)) {
479 printf("dcerpc_spoolss_EnumPrintProcessors failed - %s\n", nt_errstr(status));
480 ret = False;
481 continue;
484 if (!W_ERROR_IS_OK(r.out.result)) {
485 printf("EnumPrintProcessors failed - %s\n",
486 win_errstr(r.out.result));
487 ret = False;
488 continue;
491 ctx->print_processor_count[level] = r.out.count;
492 ctx->print_processors[level] = r.out.info;
495 for (i=1;i<ARRAY_SIZE(levels);i++) {
496 int level = levels[i];
497 int old_level = levels[i-1];
498 if (ctx->print_processor_count[level] != ctx->print_processor_count[old_level]) {
499 printf("EnumPrintProcessors level[%d] returns [%u] print_processors, but level[%d] returns [%u]\n",
500 level, ctx->print_processor_count[level], old_level, ctx->print_processor_count[old_level]);
501 ret = False;
504 /* if the array sizes are not the same we would maybe segfault in the following code */
505 if (!ret) return ret;
507 for (i=0;i<ARRAY_SIZE(levels);i++) {
508 int level = levels[i];
509 for (j=0;j<ctx->print_processor_count[level];j++) {
510 #if 0
511 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][0][j];
512 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][0][j];
513 #endif
514 switch (level) {
515 case 1:
516 /* level 1 is our reference, and it makes no sense to compare it to itself */
517 break;
522 return ret;
525 static BOOL test_EnumPrinters(struct test_spoolss_context *ctx)
527 struct spoolss_EnumPrinters r;
528 NTSTATUS status;
529 uint16_t levels[] = { 0, 1, 2, 4, 5 };
530 int i, j;
531 BOOL ret = True;
533 for (i=0;i<ARRAY_SIZE(levels);i++) {
534 int level = levels[i];
535 DATA_BLOB blob;
536 uint32_t buf_size = 0;
538 r.in.flags = PRINTER_ENUM_LOCAL;
539 r.in.server = "";
540 r.in.level = level;
541 r.in.buffer = NULL;
542 r.in.buf_size = &buf_size;
543 r.out.buf_size = &buf_size;
545 printf("\nTesting EnumPrinters level %u\n", r.in.level);
547 status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r);
548 if (!NT_STATUS_IS_OK(status)) {
549 printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status));
550 ret = False;
551 continue;
554 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
555 printf("EnumPrinters unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
556 win_errstr(r.out.result));
557 ret = False;
558 continue;
561 blob = data_blob_talloc(ctx, NULL, buf_size);
562 data_blob_clear(&blob);
563 r.in.buffer = &blob;
564 status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r);
565 if (!NT_STATUS_IS_OK(status)) {
566 printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status));
567 ret = False;
568 continue;
571 if (!W_ERROR_IS_OK(r.out.result)) {
572 printf("EnumPrinters failed - %s\n",
573 win_errstr(r.out.result));
574 continue;
577 ctx->printer_count[level] = r.out.count;
578 ctx->printers[level] = r.out.info;
581 for (i=1;i<ARRAY_SIZE(levels);i++) {
582 int level = levels[i];
583 int old_level = levels[i-1];
584 if (ctx->printer_count[level] != ctx->printer_count[old_level]) {
585 printf("EnumPrinters level[%d] returns [%u] printers, but level[%d] returns [%u]\n",
586 level, ctx->printer_count[level], old_level, ctx->printer_count[old_level]);
587 ret = False;
590 /* if the array sizes are not the same we would maybe segfault in the following code */
591 if (!ret) return ret;
593 for (i=0;i<ARRAY_SIZE(levels);i++) {
594 int level = levels[i];
595 for (j=0;j<ctx->printer_count[level];j++) {
596 union spoolss_PrinterInfo *cur = &ctx->printers[level][0][j];
597 union spoolss_PrinterInfo *ref = &ctx->printers[2][0][j];
598 switch (level) {
599 case 0:
600 COMPARE_STRING(cur->info0, ref->info2, printername);
601 COMPARE_STRING(cur->info0, ref->info2, servername);
602 COMPARE_UINT32(cur->info0, ref->info2, cjobs);
603 /*COMPARE_UINT32(cur->info0, ref->info2, total_jobs);
604 COMPARE_UINT32(cur->info0, ref->info2, total_bytes);
605 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
606 COMPARE_UINT32(cur->info0, ref->info2, global_counter);
607 COMPARE_UINT32(cur->info0, ref->info2, total_pages);
608 COMPARE_UINT32(cur->info0, ref->info2, version);
609 COMPARE_UINT32(cur->info0, ref->info2, unknown10);
610 COMPARE_UINT32(cur->info0, ref->info2, unknown11);
611 COMPARE_UINT32(cur->info0, ref->info2, unknown12);
612 COMPARE_UINT32(cur->info0, ref->info2, session_counter);
613 COMPARE_UINT32(cur->info0, ref->info2, unknown14);
614 COMPARE_UINT32(cur->info0, ref->info2, printer_errors);
615 COMPARE_UINT32(cur->info0, ref->info2, unknown16);
616 COMPARE_UINT32(cur->info0, ref->info2, unknown17);
617 COMPARE_UINT32(cur->info0, ref->info2, unknown18);
618 COMPARE_UINT32(cur->info0, ref->info2, unknown19);
619 COMPARE_UINT32(cur->info0, ref->info2, change_id);
620 COMPARE_UINT32(cur->info0, ref->info2, unknown21);*/
621 COMPARE_UINT32(cur->info0, ref->info2, status);
622 /*COMPARE_UINT32(cur->info0, ref->info2, unknown23);
623 COMPARE_UINT32(cur->info0, ref->info2, c_setprinter);
624 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
625 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
626 COMPARE_UINT32(cur->info0, ref->info2, unknown27);
627 COMPARE_UINT32(cur->info0, ref->info2, unknown28);
628 COMPARE_UINT32(cur->info0, ref->info2, unknown29);*/
629 break;
630 case 1:
631 /*COMPARE_UINT32(cur->info1, ref->info2, flags);*/
632 /*COMPARE_STRING(cur->info1, ref->info2, name);*/
633 /*COMPARE_STRING(cur->info1, ref->info2, description);*/
634 COMPARE_STRING(cur->info1, ref->info2, comment);
635 break;
636 case 2:
637 /* level 2 is our reference, and it makes no sense to compare it to itself */
638 break;
639 case 4:
640 COMPARE_STRING(cur->info4, ref->info2, printername);
641 COMPARE_STRING(cur->info4, ref->info2, servername);
642 COMPARE_UINT32(cur->info4, ref->info2, attributes);
643 break;
644 case 5:
645 COMPARE_STRING(cur->info5, ref->info2, printername);
646 COMPARE_STRING(cur->info5, ref->info2, portname);
647 COMPARE_UINT32(cur->info5, ref->info2, attributes);
648 /*COMPARE_UINT32(cur->info5, ref->info2, device_not_selected_timeout);
649 COMPARE_UINT32(cur->info5, ref->info2, transmission_retry_timeout);*/
650 break;
655 /* TODO:
656 * - verify that the port of a printer was in the list returned by EnumPorts
659 return ret;
662 static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
663 struct policy_handle *handle)
665 NTSTATUS status;
666 struct spoolss_GetPrinter r;
667 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
668 int i;
669 BOOL ret = True;
671 for (i=0;i<ARRAY_SIZE(levels);i++) {
672 uint32_t buf_size = 0;
673 r.in.handle = handle;
674 r.in.level = levels[i];
675 r.in.buffer = NULL;
676 r.in.buf_size = &buf_size;
677 r.out.buf_size = &buf_size;
679 printf("Testing GetPrinter level %u\n", r.in.level);
681 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
682 if (!NT_STATUS_IS_OK(status)) {
683 printf("GetPrinter failed - %s\n", nt_errstr(status));
684 ret = False;
685 continue;
688 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
689 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
690 data_blob_clear(&blob);
691 r.in.buffer = &blob;
692 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
695 if (!NT_STATUS_IS_OK(status)) {
696 printf("GetPrinter failed - %s\n", nt_errstr(status));
697 ret = False;
698 continue;
701 if (!W_ERROR_IS_OK(r.out.result)) {
702 printf("GetPrinter failed - %s\n",
703 win_errstr(r.out.result));
704 ret = False;
705 continue;
709 return ret;
713 static BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
714 struct policy_handle *handle)
716 NTSTATUS status;
717 struct spoolss_ClosePrinter r;
719 r.in.handle = handle;
720 r.out.handle = handle;
722 printf("Testing ClosePrinter\n");
724 status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
725 if (!NT_STATUS_IS_OK(status)) {
726 printf("ClosePrinter failed - %s\n", nt_errstr(status));
727 return False;
730 return True;
733 static BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
734 struct policy_handle *handle,
735 const char *form_name)
737 NTSTATUS status;
738 struct spoolss_GetForm r;
739 uint32_t buf_size;
741 r.in.handle = handle;
742 r.in.form_name = form_name;
743 r.in.level = 1;
744 r.in.buffer = NULL;
745 buf_size = 0;
746 r.in.buf_size = r.out.buf_size = &buf_size;
748 printf("Testing GetForm\n");
750 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
752 if (!NT_STATUS_IS_OK(status)) {
753 printf("GetForm failed - %s\n", nt_errstr(status));
754 return False;
757 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
758 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
760 data_blob_clear(&blob);
761 r.in.buffer = &blob;
763 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
765 if (!r.out.info) {
766 printf("No form info returned");
767 return False;
771 return True;
774 static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
775 struct policy_handle *handle)
777 NTSTATUS status;
778 struct spoolss_EnumForms r;
779 uint32_t buf_size;
781 r.in.handle = handle;
782 r.in.level = 1;
783 r.in.buffer = NULL;
784 buf_size = 0;
785 r.in.buf_size = &buf_size;
786 r.out.buf_size = &buf_size;
788 printf("Testing EnumForms\n");
790 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
792 if (!NT_STATUS_IS_OK(status)) {
793 printf("EnumForms failed - %s\n", nt_errstr(status));
794 return False;
797 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
798 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
799 union spoolss_FormInfo *info;
800 int j;
802 data_blob_clear(&blob);
803 r.in.buffer = &blob;
805 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
807 if (!r.out.info) {
808 printf("No forms returned");
809 return False;
812 info = *r.out.info;
814 for (j = 0; j < r.out.count; j++) {
815 test_GetForm(p, mem_ctx, handle, info[j].info1.form_name);
819 if (!NT_STATUS_IS_OK(status)) {
820 printf("EnumForms failed - %s\n", nt_errstr(status));
821 return False;
824 if (!W_ERROR_IS_OK(r.out.result)) {
825 printf("EnumForms failed - %s\n", win_errstr(r.out.result));
826 return False;
829 return True;
832 static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
833 struct policy_handle *handle,
834 const char *form_name)
836 NTSTATUS status;
837 struct spoolss_DeleteForm r;
839 r.in.handle = handle;
840 r.in.form_name = form_name;
842 status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
844 if (!NT_STATUS_IS_OK(status)) {
845 printf("DeleteForm failed - %s\n", nt_errstr(status));
846 return False;
849 if (!W_ERROR_IS_OK(r.out.result)) {
850 printf("DeleteForm failed - %s\n", win_errstr(r.out.result));
851 return False;
854 return True;
857 static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
858 struct policy_handle *handle)
860 struct spoolss_AddForm r;
861 struct spoolss_AddFormInfo1 addform;
862 const char *form_name = "testform3";
863 NTSTATUS status;
864 BOOL ret = True;
866 r.in.handle = handle;
867 r.in.level = 1;
868 r.in.info.info1 = &addform;
869 addform.flags = SPOOLSS_FORM_USER;
870 addform.form_name = form_name;
871 addform.size.width = 50;
872 addform.size.height = 25;
873 addform.area.left = 5;
874 addform.area.top = 10;
875 addform.area.right = 45;
876 addform.area.bottom = 15;
878 status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
880 if (!NT_STATUS_IS_OK(status)) {
881 printf("AddForm failed - %s\n", nt_errstr(status));
882 return False;
885 if (!W_ERROR_IS_OK(r.out.result)) {
886 printf("AddForm failed - %s\n", nt_errstr(status));
887 goto done;
891 struct spoolss_SetForm sf;
892 struct spoolss_SetFormInfo1 setform;
894 sf.in.handle = handle;
895 sf.in.form_name = form_name;
896 sf.in.level = 1;
897 sf.in.info.info1= &setform;
898 setform.flags = addform.flags;
899 setform.form_name = addform.form_name;
900 setform.size = addform.size;
901 setform.area = addform.area;
903 setform.size.width = 1234;
905 status = dcerpc_spoolss_SetForm(p, mem_ctx, &sf);
907 if (!NT_STATUS_IS_OK(status)) {
908 printf("SetForm failed - %s\n", nt_errstr(status));
909 ret = False;
910 goto done;
913 if (!W_ERROR_IS_OK(r.out.result)) {
914 printf("SetForm failed - %s\n",
915 win_errstr(r.out.result));
916 ret = False;
917 goto done;
921 done:
922 if (!test_DeleteForm(p, mem_ctx, handle, form_name)) {
923 printf("DeleteForm failed\n");
924 ret = False;
927 return ret;
930 static BOOL test_EnumPorts_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
932 NTSTATUS status;
933 struct spoolss_EnumPorts r;
934 uint32_t buf_size;
936 r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s",
937 dcerpc_server_name(p));
938 r.in.level = 2;
939 r.in.buffer = NULL;
940 buf_size = 0;
941 r.in.buf_size = &buf_size;
942 r.out.buf_size = &buf_size;
944 printf("Testing EnumPorts\n");
946 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
948 if (!NT_STATUS_IS_OK(status)) {
949 printf("EnumPorts failed - %s\n", nt_errstr(status));
950 return False;
953 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
954 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
956 data_blob_clear(&blob);
957 r.in.buffer = &blob;
959 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
961 if (!NT_STATUS_IS_OK(status)) {
962 printf("EnumPorts failed - %s\n", nt_errstr(status));
963 return False;
966 if (!r.out.info) {
967 printf("No ports returned");
968 return False;
972 return True;
975 static BOOL test_AddPort(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
977 NTSTATUS status;
978 struct spoolss_AddPort r;
980 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s",
981 dcerpc_server_name(p));
982 r.in.unknown = 0;
983 r.in.monitor_name = "foo";
985 printf ("Testing AddPort\n");
987 status = dcerpc_spoolss_AddPort(p, mem_ctx, &r);
989 if (!NT_STATUS_IS_OK(status)) {
990 printf("AddPort failed - %s\n", nt_errstr(status));
991 return False;
994 /* win2k3 returns WERR_NOT_SUPPORTED */
996 #if 0
998 if (!W_ERROR_IS_OK(r.out.result)) {
999 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1000 return False;
1003 #endif
1005 return True;
1008 static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1009 struct policy_handle *handle, uint32_t job_id)
1011 NTSTATUS status;
1012 struct spoolss_GetJob r;
1013 uint32_t buf_size;
1015 r.in.handle = handle;
1016 r.in.job_id = job_id;
1017 r.in.level = 1;
1018 r.in.buffer = NULL;
1019 buf_size = 0;
1020 r.in.buf_size = r.out.buf_size = &buf_size;
1022 printf("Testing GetJob\n");
1024 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 printf("GetJob failed - %s\n", nt_errstr(status));
1028 return False;
1031 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1032 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
1034 data_blob_clear(&blob);
1035 r.in.buffer = &blob;
1037 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
1039 if (!r.out.info) {
1040 printf("No job info returned");
1041 return False;
1045 return True;
1048 static BOOL test_SetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1049 struct policy_handle *handle, uint32_t job_id, uint32_t command)
1051 NTSTATUS status;
1052 struct spoolss_SetJob r;
1054 r.in.handle = handle;
1055 r.in.job_id = job_id;
1056 r.in.level = 0;
1057 r.in.command = command;
1059 printf("Testing SetJob\n");
1061 status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 printf("SetJob failed - %s\n", nt_errstr(status));
1065 return False;
1068 return True;
1071 static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1072 struct policy_handle *handle)
1074 NTSTATUS status;
1075 struct spoolss_EnumJobs r;
1076 uint32_t buf_size;
1078 r.in.handle = handle;
1079 r.in.firstjob = 0;
1080 r.in.numjobs = 0xffffffff;
1081 r.in.level = 1;
1082 r.in.buffer = NULL;
1083 buf_size = 0;
1084 r.in.buf_size = &buf_size;
1085 r.out.buf_size = &buf_size;
1087 printf("Testing EnumJobs\n");
1089 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 printf("EnumJobs failed - %s\n", nt_errstr(status));
1093 return False;
1096 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1097 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
1098 union spoolss_JobInfo *info;
1099 int j;
1101 data_blob_clear(&blob);
1102 r.in.buffer = &blob;
1104 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1106 if (!r.out.info) {
1107 printf("No jobs returned");
1108 return True;
1111 info = *r.out.info;
1113 for (j = 0; j < r.out.count; j++) {
1114 test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
1115 test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, 1);
1118 } else if (!W_ERROR_IS_OK(r.out.result)) {
1119 printf("EnumJobs failed - %s\n", win_errstr(r.out.result));
1120 return False;
1123 return True;
1126 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1127 struct policy_handle *handle,
1128 const char *value_name)
1130 NTSTATUS status;
1131 struct spoolss_GetPrinterData r;
1132 uint32_t buf_size;
1134 r.in.handle = handle;
1135 r.in.value_name = value_name;
1136 buf_size = 0;
1137 r.in.buf_size = r.out.buf_size = &buf_size;
1139 printf("Testing GetPrinterData\n");
1141 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 printf("GetPrinterData failed - %s\n", nt_errstr(status));
1145 return False;
1148 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1150 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 printf("GetPrinterData failed - %s\n",
1154 nt_errstr(status));
1155 return False;
1158 if (!W_ERROR_IS_OK(r.out.result)) {
1159 printf("GetPrinterData failed - %s\n",
1160 win_errstr(r.out.result));
1161 return False;
1165 return True;
1168 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1169 struct policy_handle *handle,
1170 const char *key_name,
1171 const char *value_name)
1173 NTSTATUS status;
1174 struct spoolss_GetPrinterDataEx r;
1175 uint32_t buf_size;
1177 r.in.handle = handle;
1178 r.in.key_name = key_name;
1179 r.in.value_name = value_name;
1180 buf_size = 0;
1181 r.in.buf_size = r.out.buf_size = &buf_size;
1183 printf("Testing GetPrinterDataEx\n");
1185 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1186 if (!NT_STATUS_IS_OK(status)) {
1187 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1188 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1189 printf("GetPrinterDataEx not supported by server\n");
1190 return True;
1192 printf("GetPrinterDataEx failed - %s\n", nt_errstr(status));
1193 return False;
1196 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1198 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1200 if (!NT_STATUS_IS_OK(status)) {
1201 printf("GetPrinterDataEx failed - %s\n",
1202 nt_errstr(status));
1203 return False;
1206 if (!W_ERROR_IS_OK(r.out.result)) {
1207 printf("GetPrinterDataEx failed - %s\n",
1208 win_errstr(r.out.result));
1209 return False;
1213 return True;
1216 static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1217 struct policy_handle *handle)
1219 NTSTATUS status;
1220 struct spoolss_EnumPrinterData r;
1222 r.in.handle = handle;
1223 r.in.enum_index = 0;
1225 do {
1226 uint32_t data_size;
1228 r.in.value_offered = 0;
1229 data_size = 0;
1230 r.in.data_size = &data_size;
1231 r.out.data_size = &data_size;
1233 printf("Testing EnumPrinterData\n");
1235 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1239 return False;
1242 r.in.value_offered = r.out.value_needed;
1244 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1246 if (!NT_STATUS_IS_OK(status)) {
1247 printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1248 return False;
1251 test_GetPrinterData(p, mem_ctx, handle, r.out.value_name);
1253 test_GetPrinterDataEx(
1254 p, mem_ctx, handle, "PrinterDriverData",
1255 r.out.value_name);
1257 r.in.enum_index++;
1259 } while (W_ERROR_IS_OK(r.out.result));
1261 return True;
1264 static BOOL test_EnumPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1265 struct policy_handle *handle)
1267 NTSTATUS status;
1268 struct spoolss_EnumPrinterDataEx r;
1270 r.in.handle = handle;
1271 r.in.key_name = "PrinterDriverData";
1272 r.in.buf_size = 0;
1274 printf("Testing EnumPrinterDataEx\n");
1276 status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1280 return False;
1283 r.in.buf_size = r.out.buf_size;
1285 status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1289 return False;
1292 return True;
1296 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1297 struct policy_handle *handle,
1298 const char *value_name)
1300 NTSTATUS status;
1301 struct spoolss_DeletePrinterData r;
1303 r.in.handle = handle;
1304 r.in.value_name = value_name;
1306 printf("Testing DeletePrinterData\n");
1308 status = dcerpc_spoolss_DeletePrinterData(p, mem_ctx, &r);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 printf("DeletePrinterData failed - %s\n", nt_errstr(status));
1312 return False;
1315 return True;
1318 static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1319 struct policy_handle *handle)
1321 NTSTATUS status;
1322 struct spoolss_SetPrinterData r;
1323 const char *value_name = "spottyfoot";
1325 r.in.handle = handle;
1326 r.in.value_name = value_name;
1327 r.in.type = 0;
1328 r.in.buffer = data_blob_talloc(mem_ctx, "dog", 4);
1329 r.in.real_len = 4;
1331 printf("Testing SetPrinterData\n");
1333 status = dcerpc_spoolss_SetPrinterData(p, mem_ctx, &r);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 printf("SetPrinterData failed - %s\n", nt_errstr(status));
1337 return False;
1340 if (!test_DeletePrinterData(p, mem_ctx, handle, value_name)) {
1341 return False;
1344 return True;
1347 static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1348 struct policy_handle *handle)
1350 NTSTATUS status;
1351 struct dcerpc_binding *b;
1352 struct dcerpc_pipe *p2;
1353 BOOL ret = True;
1355 /* only makes sense on SMB */
1356 if (p->conn->transport.transport != NCACN_NP) {
1357 return True;
1360 printf("testing close on secondary pipe\n");
1362 status = dcerpc_parse_binding(mem_ctx, p->conn->binding_string, &b);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 printf("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string);
1365 return False;
1368 status = dcerpc_secondary_connection(p, &p2, b);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 printf("Failed to create secondary connection\n");
1371 return False;
1374 status = dcerpc_bind_auth_none(p2, DCERPC_SPOOLSS_UUID,
1375 DCERPC_SPOOLSS_VERSION);
1376 if (!NT_STATUS_IS_OK(status)) {
1377 printf("Failed to create bind on secondary connection\n");
1378 talloc_free(p2);
1380 return False;
1383 if (test_ClosePrinter(p2, mem_ctx, handle)) {
1384 printf("ERROR: Allowed close on secondary connection!\n");
1385 ret = False;
1388 if (p2->last_fault_code != DCERPC_FAULT_CONTEXT_MISMATCH) {
1389 printf("Unexpected fault code 0x%x - expected 0x%x\n",
1390 p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH);
1391 ret = False;
1394 talloc_free(p2);
1396 return ret;
1399 static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name)
1401 NTSTATUS status;
1402 struct spoolss_OpenPrinter op;
1403 struct spoolss_OpenPrinterEx opEx;
1404 struct policy_handle handle;
1405 BOOL ret = True;
1407 op.in.printername = name;
1408 op.in.datatype = NULL;
1409 op.in.devmode_ctr.size = 0;
1410 op.in.devmode_ctr.devmode= NULL;
1411 op.in.access_mask = 0;
1412 op.out.handle = &handle;
1414 printf("\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1416 status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &op);
1417 if (!NT_STATUS_IS_OK(status)) {
1418 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1419 ret = False;
1421 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1422 printf("OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1423 name, win_errstr(op.out.result));
1426 if (W_ERROR_IS_OK(op.out.result)) {
1427 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1430 opEx.in.printername = name;
1431 opEx.in.datatype = NULL;
1432 opEx.in.devmode_ctr.size = 0;
1433 opEx.in.devmode_ctr.devmode = NULL;
1434 opEx.in.access_mask = 0;
1435 opEx.in.level = 1;
1436 opEx.in.userlevel.level1 = NULL;
1437 opEx.out.handle = &handle;
1439 printf("\nTesting OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1441 status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &opEx);
1442 if (!NT_STATUS_IS_OK(status)) {
1443 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1444 ret = False;
1446 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,opEx.out.result)) {
1447 printf("OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1448 name, win_errstr(opEx.out.result));
1451 if (W_ERROR_IS_OK(opEx.out.result)) {
1452 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1455 return ret;
1458 static BOOL test_OpenPrinter_badnames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1460 BOOL ret = True;
1461 char *name;
1463 ret &= test_OpenPrinter_badname(p, mem_ctx, "__INVALID_PRINTER__");
1464 ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\__INVALID_HOST__");
1465 ret &= test_OpenPrinter_badname(p, mem_ctx, "");
1466 ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\");
1467 ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\__INVALID_PRINTER__");
1469 name = talloc_asprintf(mem_ctx, "\\\\%s\\", dcerpc_server_name(p));
1470 ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1471 talloc_free(name);
1473 name = talloc_asprintf(mem_ctx, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p));
1474 ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1475 talloc_free(name);
1477 return ret;
1480 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1481 const char *name)
1483 NTSTATUS status;
1484 struct spoolss_OpenPrinter r;
1485 struct policy_handle handle;
1486 BOOL ret = True;
1488 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1489 r.in.datatype = NULL;
1490 r.in.devmode_ctr.size = 0;
1491 r.in.devmode_ctr.devmode= NULL;
1492 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1493 r.out.handle = &handle;
1495 printf("\nTesting OpenPrinter(%s)\n", r.in.printername);
1497 status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1501 return False;
1504 if (!W_ERROR_IS_OK(r.out.result)) {
1505 printf("OpenPrinter failed - %s\n", win_errstr(r.out.result));
1506 return False;
1509 if (!test_GetPrinter(p, mem_ctx, &handle)) {
1510 ret = False;
1513 if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1514 ret = False;
1517 if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1518 ret = False;
1521 return ret;
1524 static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1525 const char *name, struct policy_handle *handle)
1527 struct spoolss_OpenPrinterEx r;
1528 struct spoolss_UserLevel1 userlevel1;
1529 NTSTATUS status;
1531 if (name && name[0]) {
1532 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
1533 dcerpc_server_name(p), name);
1534 } else {
1535 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s",
1536 dcerpc_server_name(p));
1539 r.in.datatype = NULL;
1540 r.in.devmode_ctr.size = 0;
1541 r.in.devmode_ctr.devmode= NULL;
1542 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1543 r.in.level = 1;
1544 r.in.userlevel.level1 = &userlevel1;
1545 r.out.handle = handle;
1547 userlevel1.size = 1234;
1548 userlevel1.client = "hello";
1549 userlevel1.user = "spottyfoot!";
1550 userlevel1.build = 1;
1551 userlevel1.major = 2;
1552 userlevel1.minor = 3;
1553 userlevel1.processor = 4;
1555 printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
1557 status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
1561 return False;
1564 if (!W_ERROR_IS_OK(r.out.result)) {
1565 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
1566 return False;
1569 return True;
1572 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1573 const char *name)
1575 struct policy_handle handle;
1576 BOOL ret = True;
1578 if (!call_OpenPrinterEx(p, mem_ctx, name, &handle)) {
1579 return False;
1582 if (!test_GetPrinter(p, mem_ctx, &handle)) {
1583 ret = False;
1586 if (!test_EnumForms(p, mem_ctx, &handle)) {
1587 ret = False;
1590 if (!test_AddForm(p, mem_ctx, &handle)) {
1591 ret = False;
1594 if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
1595 ret = False;
1598 if (!test_EnumPrinterDataEx(p, mem_ctx, &handle)) {
1599 ret = False;
1602 if (!test_EnumJobs(p, mem_ctx, &handle)) {
1603 ret = False;
1606 if (!test_SetPrinterData(p, mem_ctx, &handle)) {
1607 ret = False;
1610 if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1611 ret = False;
1614 if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1615 ret = False;
1618 return ret;
1621 static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1623 struct spoolss_EnumPrinters r;
1624 NTSTATUS status;
1625 uint16_t levels[] = {1, 2, 4, 5};
1626 int i;
1627 BOOL ret = True;
1629 for (i=0;i<ARRAY_SIZE(levels);i++) {
1630 uint32_t buf_size = 0;
1631 union spoolss_PrinterInfo *info;
1632 int j;
1634 r.in.flags = PRINTER_ENUM_LOCAL;
1635 r.in.server = "";
1636 r.in.level = levels[i];
1637 r.in.buffer = NULL;
1638 r.in.buf_size = &buf_size;
1639 r.out.buf_size = &buf_size;
1641 printf("\nTesting EnumPrinters level %u\n", r.in.level);
1643 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 printf("EnumPrinters failed - %s\n", nt_errstr(status));
1646 ret = False;
1647 continue;
1650 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1651 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
1652 data_blob_clear(&blob);
1653 r.in.buffer = &blob;
1654 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1657 if (!NT_STATUS_IS_OK(status)) {
1658 printf("EnumPrinters failed - %s\n",
1659 nt_errstr(status));
1660 continue;
1663 if (!W_ERROR_IS_OK(r.out.result)) {
1664 printf("EnumPrinters failed - %s\n",
1665 win_errstr(r.out.result));
1666 continue;
1669 if (!r.out.info) {
1670 printf("No printers returned");
1671 continue;
1674 info = *r.out.info;
1676 for (j=0;j<r.out.count;j++) {
1677 if (r.in.level == 1) {
1678 /* the names appear to be comma-separated name lists? */
1679 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
1680 char *comma = strchr(name, ',');
1681 if (comma) *comma = 0;
1682 if (!test_OpenPrinter(p, mem_ctx, name)) {
1683 ret = False;
1685 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
1686 ret = False;
1692 return ret;
1695 #if 0
1696 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1697 struct policy_handle *handle,
1698 const char *driver_name)
1700 NTSTATUS status;
1701 struct spoolss_GetPrinterDriver2 r;
1702 uint32_t buf_size;
1704 r.in.handle = handle;
1705 r.in.architecture = "W32X86";
1706 r.in.level = 1;
1707 buf_size = 0;
1708 r.in.buffer = NULL;
1709 r.in.buf_size = r.out.buf_size = &buf_size;
1710 r.in.client_major_version = 0;
1711 r.in.client_minor_version = 0;
1713 printf("Testing GetPrinterDriver2\n");
1715 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1719 return False;
1722 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1723 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 printf("GetPrinterDriver2 failed - %s\n",
1728 nt_errstr(status));
1729 return False;
1732 if (!W_ERROR_IS_OK(r.out.result)) {
1733 printf("GetPrinterDriver2 failed - %s\n",
1734 win_errstr(r.out.result));
1735 return False;
1738 return True;
1740 #endif
1742 static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1744 struct spoolss_EnumPrinterDrivers r;
1745 NTSTATUS status;
1746 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1747 int i;
1748 BOOL ret = True;
1750 for (i=0;i<ARRAY_SIZE(levels);i++) {
1751 uint32_t buf_size;
1753 r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1754 r.in.environment = "Windows NT x86";
1755 r.in.level = levels[i];
1756 r.in.buffer = NULL;
1757 buf_size = 0;
1758 r.in.buf_size = &buf_size;
1759 r.out.buf_size = &buf_size;
1761 printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
1763 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 printf("EnumPrinterDrivers failed - %s\n",
1767 nt_errstr(status));
1768 ret = False;
1769 continue;
1772 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1773 DATA_BLOB blob = data_blob_talloc(
1774 mem_ctx, NULL, buf_size);
1776 data_blob_clear(&blob);
1777 r.in.buffer = &blob;
1778 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 printf("EnumPrinterDrivers failed - %s\n",
1783 nt_errstr(status));
1784 ret = False;
1785 break;
1788 if (!W_ERROR_IS_OK(r.out.result)) {
1789 printf("EnumPrinterDrivers failed - %s\n",
1790 win_errstr(r.out.result));
1791 ret = False;
1792 break;
1795 if (!r.out.info) {
1796 printf("No printer drivers returned");
1797 break;
1801 return ret;
1804 BOOL torture_rpc_spoolss(void)
1806 NTSTATUS status;
1807 struct dcerpc_pipe *p;
1808 TALLOC_CTX *mem_ctx;
1809 BOOL ret = True;
1810 struct test_spoolss_context *ctx;
1812 mem_ctx = talloc_init("torture_rpc_spoolss");
1814 status = torture_rpc_connection(mem_ctx,
1815 &p,
1816 DCERPC_SPOOLSS_NAME,
1817 DCERPC_SPOOLSS_UUID,
1818 DCERPC_SPOOLSS_VERSION);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 talloc_free(mem_ctx);
1821 return False;
1824 ctx = talloc_zero(mem_ctx, struct test_spoolss_context);
1825 ctx->p = p;
1827 ret &= test_OpenPrinter_server(ctx);
1829 ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, SPOOLSS_ARCHITECTURE_NT_X86);
1831 ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DefaultSpoolDirectory");
1833 ret &= test_EnumPorts(ctx);
1835 ret &= test_EnumPrinterDrivers(ctx);
1837 ret &= test_EnumMonitors(ctx);
1839 ret &= test_EnumPrintProcessors(ctx);
1841 ret &= test_EnumPrinters(ctx);
1843 ret &= test_OpenPrinter_badnames(p, mem_ctx);
1845 ret &= test_AddPort(p, mem_ctx);
1847 ret &= test_EnumPorts_old(p, mem_ctx);
1849 ret &= test_EnumPrinters_old(p, mem_ctx);
1851 ret &= test_EnumPrinterDrivers_old(p, mem_ctx);
1853 talloc_free(mem_ctx);
1855 return ret;