r5941: Commit this patch much earlier than I would normally prefer, but metze needs...
[Samba/aatanasov.git] / source / torture / rpc / spoolss.c
blobacaa5828dc9cb6a3836401a8bcb63859d13f4725
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
5 Copyright (C) Tim Potter 2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
23 #include "librpc/gen_ndr/ndr_spoolss.h"
25 static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
26 struct policy_handle *handle)
28 NTSTATUS status;
29 struct spoolss_GetPrinter r;
30 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
31 int i;
32 BOOL ret = True;
34 for (i=0;i<ARRAY_SIZE(levels);i++) {
35 uint32_t buf_size = 0;
36 r.in.handle = handle;
37 r.in.level = levels[i];
38 r.in.buffer = NULL;
39 r.in.buf_size = &buf_size;
40 r.out.buf_size = &buf_size;
42 printf("Testing GetPrinter level %u\n", r.in.level);
44 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
45 if (!NT_STATUS_IS_OK(status)) {
46 printf("GetPrinter failed - %s\n", nt_errstr(status));
47 ret = False;
48 continue;
51 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
52 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
53 data_blob_clear(&blob);
54 r.in.buffer = &blob;
55 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
58 if (!NT_STATUS_IS_OK(status)) {
59 printf("GetPrinter failed - %s\n", nt_errstr(status));
60 ret = False;
61 continue;
64 if (!W_ERROR_IS_OK(r.out.result)) {
65 printf("GetPrinter failed - %s\n",
66 win_errstr(r.out.result));
67 ret = False;
68 continue;
72 return ret;
76 static BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
77 struct policy_handle *handle)
79 NTSTATUS status;
80 struct spoolss_ClosePrinter r;
82 r.in.handle = handle;
83 r.out.handle = handle;
85 printf("Testing ClosePrinter\n");
87 status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
88 if (!NT_STATUS_IS_OK(status)) {
89 printf("ClosePrinter failed - %s\n", nt_errstr(status));
90 return False;
93 return True;
96 static BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
97 struct policy_handle *handle,
98 const char *formname)
100 NTSTATUS status;
101 struct spoolss_GetForm r;
102 uint32_t buf_size;
104 r.in.handle = handle;
105 r.in.formname = formname;
106 r.in.level = 1;
107 r.in.buffer = NULL;
108 buf_size = 0;
109 r.in.buf_size = r.out.buf_size = &buf_size;
111 printf("Testing GetForm\n");
113 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
115 if (!NT_STATUS_IS_OK(status)) {
116 printf("GetForm failed - %s\n", nt_errstr(status));
117 return False;
120 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
121 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
123 data_blob_clear(&blob);
124 r.in.buffer = &blob;
126 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
128 if (!r.out.info) {
129 printf("No form info returned");
130 return False;
134 return True;
137 static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
138 struct policy_handle *handle)
140 NTSTATUS status;
141 struct spoolss_EnumForms r;
142 uint32_t buf_size;
144 r.in.handle = handle;
145 r.in.level = 1;
146 r.in.buffer = NULL;
147 buf_size = 0;
148 r.in.buf_size = &buf_size;
149 r.out.buf_size = &buf_size;
151 printf("Testing EnumForms\n");
153 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
155 if (!NT_STATUS_IS_OK(status)) {
156 printf("EnumForms failed - %s\n", nt_errstr(status));
157 return False;
160 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
161 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
162 union spoolss_FormInfo *info;
163 int j;
165 data_blob_clear(&blob);
166 r.in.buffer = &blob;
168 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
170 if (!r.out.info) {
171 printf("No forms returned");
172 return False;
175 info = *r.out.info;
177 for (j = 0; j < r.out.count; j++) {
178 test_GetForm(p, mem_ctx, handle, info[j].info1.formname);
182 if (!NT_STATUS_IS_OK(status)) {
183 printf("EnumForms failed - %s\n", nt_errstr(status));
184 return False;
187 if (!W_ERROR_IS_OK(r.out.result)) {
188 printf("EnumForms failed - %s\n", win_errstr(r.out.result));
189 return False;
192 return True;
195 static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
196 struct policy_handle *handle,
197 const char *formname)
199 NTSTATUS status;
200 struct spoolss_DeleteForm r;
202 r.in.handle = handle;
203 r.in.formname = formname;
205 status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
207 if (!NT_STATUS_IS_OK(status)) {
208 printf("DeleteForm failed - %s\n", nt_errstr(status));
209 return False;
212 if (!W_ERROR_IS_OK(r.out.result)) {
213 printf("DeleteForm failed - %s\n", win_errstr(r.out.result));
214 return False;
217 return True;
220 static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
221 struct policy_handle *handle)
223 struct spoolss_AddForm r;
224 struct spoolss_AddFormInfo1 form;
225 NTSTATUS status;
226 const char *formname = "testform3";
227 BOOL ret = True;
229 r.in.handle = handle;
230 r.in.level = 1;
231 form.flags = 2; /* User form */
232 form.formname = formname;
233 form.width = 1;
234 form.length = 2;
235 form.left = 3;
236 form.top = 4;
237 form.right = 5;
238 form.bottom = 6;
239 r.in.info.info1 = &form;
241 status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
243 if (!NT_STATUS_IS_OK(status)) {
244 printf("AddForm failed - %s\n", nt_errstr(status));
245 return False;
248 if (!W_ERROR_IS_OK(r.out.result)) {
249 printf("AddForm failed - %s\n", nt_errstr(status));
250 goto done;
254 struct spoolss_SetForm sf;
256 sf.in.handle = handle;
257 sf.in.formname = formname;
258 sf.in.level = 1;
259 sf.in.info.info1 = &form;
260 form.width = 1234;
262 status = dcerpc_spoolss_SetForm(p, mem_ctx, &sf);
264 if (!NT_STATUS_IS_OK(status)) {
265 printf("SetForm failed - %s\n", nt_errstr(status));
266 ret = False;
267 goto done;
270 if (!W_ERROR_IS_OK(r.out.result)) {
271 printf("SetForm failed - %s\n",
272 win_errstr(r.out.result));
273 ret = False;
274 goto done;
278 done:
279 if (!test_DeleteForm(p, mem_ctx, handle, formname)) {
280 printf("DeleteForm failed\n");
281 ret = False;
284 return ret;
287 static BOOL test_EnumPorts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
289 NTSTATUS status;
290 struct spoolss_EnumPorts r;
291 uint32_t buf_size;
293 r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s",
294 dcerpc_server_name(p));
295 r.in.level = 2;
296 r.in.buffer = NULL;
297 buf_size = 0;
298 r.in.buf_size = &buf_size;
299 r.out.buf_size = &buf_size;
301 printf("Testing EnumPorts\n");
303 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
305 if (!NT_STATUS_IS_OK(status)) {
306 printf("EnumPorts failed - %s\n", nt_errstr(status));
307 return False;
310 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
311 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
313 data_blob_clear(&blob);
314 r.in.buffer = &blob;
316 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
318 if (!NT_STATUS_IS_OK(status)) {
319 printf("EnumPorts failed - %s\n", nt_errstr(status));
320 return False;
323 if (!r.out.info) {
324 printf("No ports returned");
325 return False;
329 return True;
332 static BOOL test_AddPort(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
334 NTSTATUS status;
335 struct spoolss_AddPort r;
337 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s",
338 dcerpc_server_name(p));
339 r.in.unknown = 0;
340 r.in.monitor_name = "foo";
342 printf ("Testing AddPort\n");
344 status = dcerpc_spoolss_AddPort(p, mem_ctx, &r);
346 if (!NT_STATUS_IS_OK(status)) {
347 printf("AddPort failed - %s\n", nt_errstr(status));
348 return False;
351 /* win2k3 returns WERR_NOT_SUPPORTED */
353 #if 0
355 if (!W_ERROR_IS_OK(r.out.result)) {
356 printf("AddPort failed - %s\n", win_errstr(r.out.result));
357 return False;
360 #endif
362 return True;
365 static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
366 struct policy_handle *handle, uint32_t job_id)
368 NTSTATUS status;
369 struct spoolss_GetJob r;
370 uint32_t buf_size;
372 r.in.handle = handle;
373 r.in.job_id = job_id;
374 r.in.level = 1;
375 r.in.buffer = NULL;
376 buf_size = 0;
377 r.in.buf_size = r.out.buf_size = &buf_size;
379 printf("Testing GetJob\n");
381 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
383 if (!NT_STATUS_IS_OK(status)) {
384 printf("GetJob failed - %s\n", nt_errstr(status));
385 return False;
388 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
389 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
391 data_blob_clear(&blob);
392 r.in.buffer = &blob;
394 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
396 if (!r.out.info) {
397 printf("No job info returned");
398 return False;
402 return True;
405 static BOOL test_SetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
406 struct policy_handle *handle, uint32_t job_id, uint32_t command)
408 NTSTATUS status;
409 struct spoolss_SetJob r;
411 r.in.handle = handle;
412 r.in.job_id = job_id;
413 r.in.level = 0;
414 r.in.command = command;
416 printf("Testing SetJob\n");
418 status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
420 if (!NT_STATUS_IS_OK(status)) {
421 printf("SetJob failed - %s\n", nt_errstr(status));
422 return False;
425 return True;
428 static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
429 struct policy_handle *handle)
431 NTSTATUS status;
432 struct spoolss_EnumJobs r;
433 uint32_t buf_size;
435 r.in.handle = handle;
436 r.in.firstjob = 0;
437 r.in.numjobs = 0xffffffff;
438 r.in.level = 1;
439 r.in.buffer = NULL;
440 buf_size = 0;
441 r.in.buf_size = &buf_size;
442 r.out.buf_size = &buf_size;
444 printf("Testing EnumJobs\n");
446 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
448 if (!NT_STATUS_IS_OK(status)) {
449 printf("EnumJobs failed - %s\n", nt_errstr(status));
450 return False;
453 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
454 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
455 union spoolss_JobInfo *info;
456 int j;
458 data_blob_clear(&blob);
459 r.in.buffer = &blob;
461 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
463 if (!r.out.info) {
464 printf("No jobs returned");
465 return True;
468 info = *r.out.info;
470 for (j = 0; j < r.out.count; j++) {
471 test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
472 test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, 1);
475 } else if (!W_ERROR_IS_OK(r.out.result)) {
476 printf("EnumJobs failed - %s\n", win_errstr(r.out.result));
477 return False;
480 return True;
483 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
484 struct policy_handle *handle,
485 const char *value_name)
487 NTSTATUS status;
488 struct spoolss_GetPrinterData r;
489 uint32_t buf_size;
491 r.in.handle = handle;
492 r.in.value_name = value_name;
493 buf_size = 0;
494 r.in.buf_size = r.out.buf_size = &buf_size;
496 printf("Testing GetPrinterData\n");
498 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
500 if (!NT_STATUS_IS_OK(status)) {
501 printf("GetPrinterData failed - %s\n", nt_errstr(status));
502 return False;
505 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
507 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
509 if (!NT_STATUS_IS_OK(status)) {
510 printf("GetPrinterData failed - %s\n",
511 nt_errstr(status));
512 return False;
515 if (!W_ERROR_IS_OK(r.out.result)) {
516 printf("GetPrinterData failed - %s\n",
517 win_errstr(r.out.result));
518 return False;
522 return True;
525 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
526 struct policy_handle *handle,
527 const char *key_name,
528 const char *value_name)
530 NTSTATUS status;
531 struct spoolss_GetPrinterDataEx r;
532 uint32_t buf_size;
534 r.in.handle = handle;
535 r.in.key_name = key_name;
536 r.in.value_name = value_name;
537 buf_size = 0;
538 r.in.buf_size = r.out.buf_size = &buf_size;
540 printf("Testing GetPrinterDataEx\n");
542 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
543 if (!NT_STATUS_IS_OK(status)) {
544 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
545 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
546 printf("GetPrinterDataEx not supported by server\n");
547 return True;
549 printf("GetPrinterDataEx failed - %s\n", nt_errstr(status));
550 return False;
553 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
555 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
557 if (!NT_STATUS_IS_OK(status)) {
558 printf("GetPrinterDataEx failed - %s\n",
559 nt_errstr(status));
560 return False;
563 if (!W_ERROR_IS_OK(r.out.result)) {
564 printf("GetPrinterDataEx failed - %s\n",
565 win_errstr(r.out.result));
566 return False;
570 return True;
573 static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
574 struct policy_handle *handle)
576 NTSTATUS status;
577 struct spoolss_EnumPrinterData r;
579 r.in.handle = handle;
580 r.in.enum_index = 0;
582 do {
583 uint32_t data_size;
585 r.in.value_offered = 0;
586 data_size = 0;
587 r.in.data_size = &data_size;
588 r.out.data_size = &data_size;
590 printf("Testing EnumPrinterData\n");
592 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
594 if (!NT_STATUS_IS_OK(status)) {
595 printf("EnumPrinterData failed - %s\n", nt_errstr(status));
596 return False;
599 r.in.value_offered = r.out.value_needed;
601 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
603 if (!NT_STATUS_IS_OK(status)) {
604 printf("EnumPrinterData failed - %s\n", nt_errstr(status));
605 return False;
608 test_GetPrinterData(p, mem_ctx, handle, r.out.value_name);
610 test_GetPrinterDataEx(
611 p, mem_ctx, handle, "PrinterDriverData",
612 r.out.value_name);
614 r.in.enum_index++;
616 } while (W_ERROR_IS_OK(r.out.result));
618 return True;
621 static BOOL test_EnumPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
622 struct policy_handle *handle)
624 NTSTATUS status;
625 struct spoolss_EnumPrinterDataEx r;
627 r.in.handle = handle;
628 r.in.key_name = "PrinterDriverData";
629 r.in.buf_size = 0;
631 printf("Testing EnumPrinterDataEx\n");
633 status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
635 if (!NT_STATUS_IS_OK(status)) {
636 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
637 return False;
640 r.in.buf_size = r.out.buf_size;
642 status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
644 if (!NT_STATUS_IS_OK(status)) {
645 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
646 return False;
649 return True;
653 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
654 struct policy_handle *handle,
655 const char *value_name)
657 NTSTATUS status;
658 struct spoolss_DeletePrinterData r;
660 r.in.handle = handle;
661 r.in.value_name = value_name;
663 printf("Testing DeletePrinterData\n");
665 status = dcerpc_spoolss_DeletePrinterData(p, mem_ctx, &r);
667 if (!NT_STATUS_IS_OK(status)) {
668 printf("DeletePrinterData failed - %s\n", nt_errstr(status));
669 return False;
672 return True;
675 static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
676 struct policy_handle *handle)
678 NTSTATUS status;
679 struct spoolss_SetPrinterData r;
680 const char *value_name = "spottyfoot";
682 r.in.handle = handle;
683 r.in.value_name = value_name;
684 r.in.type = 0;
685 r.in.buffer = data_blob_talloc(mem_ctx, "dog", 4);
686 r.in.real_len = 4;
688 printf("Testing SetPrinterData\n");
690 status = dcerpc_spoolss_SetPrinterData(p, mem_ctx, &r);
692 if (!NT_STATUS_IS_OK(status)) {
693 printf("SetPrinterData failed - %s\n", nt_errstr(status));
694 return False;
697 if (!test_DeletePrinterData(p, mem_ctx, handle, value_name)) {
698 return False;
701 return True;
704 static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
705 struct policy_handle *handle)
707 NTSTATUS status;
708 struct dcerpc_binding *b;
709 struct dcerpc_pipe *p2;
710 BOOL ret = True;
712 /* only makes sense on SMB */
713 if (p->conn->transport.transport != NCACN_NP) {
714 return True;
717 printf("testing close on secondary pipe\n");
719 status = dcerpc_parse_binding(mem_ctx, p->conn->binding_string, &b);
720 if (!NT_STATUS_IS_OK(status)) {
721 printf("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string);
722 return False;
725 status = dcerpc_secondary_connection(p, &p2, b);
726 if (!NT_STATUS_IS_OK(status)) {
727 printf("Failed to create secondary connection\n");
728 return False;
731 status = dcerpc_bind_auth_none(p2, DCERPC_SPOOLSS_UUID,
732 DCERPC_SPOOLSS_VERSION);
733 if (!NT_STATUS_IS_OK(status)) {
734 printf("Failed to create bind on secondary connection\n");
735 talloc_free(p2);
737 return False;
740 if (test_ClosePrinter(p2, mem_ctx, handle)) {
741 printf("ERROR: Allowed close on secondary connection!\n");
742 ret = False;
745 if (p2->last_fault_code != DCERPC_FAULT_CONTEXT_MISMATCH) {
746 printf("Unexpected fault code 0x%x - expected 0x%x\n",
747 p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH);
748 ret = False;
751 talloc_free(p2);
753 return ret;
756 static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name)
758 NTSTATUS status;
759 struct spoolss_OpenPrinter op;
760 struct spoolss_OpenPrinterEx opEx;
761 struct policy_handle handle;
762 BOOL ret = True;
764 op.in.printername = name;
765 op.in.datatype = NULL;
766 op.in.devmode_ctr.size = 0;
767 op.in.devmode_ctr.devmode= NULL;
768 op.in.access_mask = 0;
769 op.out.handle = &handle;
771 printf("\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
773 status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &op);
774 if (!NT_STATUS_IS_OK(status)) {
775 printf("OpenPrinter failed - %s\n", nt_errstr(status));
776 ret = False;
778 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
779 printf("OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
780 name, win_errstr(op.out.result));
783 if (W_ERROR_IS_OK(op.out.result)) {
784 ret &=test_ClosePrinter(p, mem_ctx, &handle);
787 opEx.in.printername = name;
788 opEx.in.datatype = NULL;
789 opEx.in.devmode_ctr.size = 0;
790 opEx.in.devmode_ctr.devmode = NULL;
791 opEx.in.access_mask = 0;
792 opEx.in.level = 1;
793 opEx.in.userlevel.level1 = NULL;
794 opEx.out.handle = &handle;
796 printf("\nTesting OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
798 status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &opEx);
799 if (!NT_STATUS_IS_OK(status)) {
800 printf("OpenPrinter failed - %s\n", nt_errstr(status));
801 ret = False;
803 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,opEx.out.result)) {
804 printf("OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
805 name, win_errstr(opEx.out.result));
808 if (W_ERROR_IS_OK(opEx.out.result)) {
809 ret &=test_ClosePrinter(p, mem_ctx, &handle);
812 return ret;
815 static BOOL test_OpenPrinter_badnames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
817 BOOL ret = True;
818 char *name;
820 ret &= test_OpenPrinter_badname(p, mem_ctx, "__INVALID_PRINTER__");
821 ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\__INVALID_HOST__");
822 ret &= test_OpenPrinter_badname(p, mem_ctx, "");
823 ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\");
824 ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\__INVALID_PRINTER__");
826 name = talloc_asprintf(mem_ctx, "\\\\%s\\", dcerpc_server_name(p));
827 ret &= test_OpenPrinter_badname(p, mem_ctx, name);
828 talloc_free(name);
830 name = talloc_asprintf(mem_ctx, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p));
831 ret &= test_OpenPrinter_badname(p, mem_ctx, name);
832 talloc_free(name);
834 return ret;
837 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
838 const char *name)
840 NTSTATUS status;
841 struct spoolss_OpenPrinter r;
842 struct policy_handle handle;
843 BOOL ret = True;
845 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
846 r.in.datatype = NULL;
847 r.in.devmode_ctr.size = 0;
848 r.in.devmode_ctr.devmode= NULL;
849 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
850 r.out.handle = &handle;
852 printf("\nTesting OpenPrinter(%s)\n", r.in.printername);
854 status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
856 if (!NT_STATUS_IS_OK(status)) {
857 printf("OpenPrinter failed - %s\n", nt_errstr(status));
858 return False;
861 if (!W_ERROR_IS_OK(r.out.result)) {
862 printf("OpenPrinter failed - %s\n", win_errstr(r.out.result));
863 return False;
866 if (!test_GetPrinter(p, mem_ctx, &handle)) {
867 ret = False;
870 if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
871 ret = False;
874 if (!test_ClosePrinter(p, mem_ctx, &handle)) {
875 ret = False;
878 return ret;
881 static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
882 const char *name, struct policy_handle *handle)
884 struct spoolss_OpenPrinterEx r;
885 struct spoolss_UserLevel1 userlevel1;
886 NTSTATUS status;
888 if (name && name[0]) {
889 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
890 dcerpc_server_name(p), name);
891 } else {
892 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s",
893 dcerpc_server_name(p));
896 r.in.datatype = NULL;
897 r.in.devmode_ctr.size = 0;
898 r.in.devmode_ctr.devmode= NULL;
899 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
900 r.in.level = 1;
901 r.in.userlevel.level1 = &userlevel1;
902 r.out.handle = handle;
904 userlevel1.size = 1234;
905 userlevel1.client = "hello";
906 userlevel1.user = "spottyfoot!";
907 userlevel1.build = 1;
908 userlevel1.major = 2;
909 userlevel1.minor = 3;
910 userlevel1.processor = 4;
912 printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
914 status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
916 if (!NT_STATUS_IS_OK(status)) {
917 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
918 return False;
921 if (!W_ERROR_IS_OK(r.out.result)) {
922 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
923 return False;
926 return True;
929 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
930 const char *name)
932 struct policy_handle handle;
933 BOOL ret = True;
935 if (!call_OpenPrinterEx(p, mem_ctx, name, &handle)) {
936 return False;
939 if (!test_GetPrinter(p, mem_ctx, &handle)) {
940 ret = False;
943 if (!test_EnumForms(p, mem_ctx, &handle)) {
944 ret = False;
947 if (!test_AddForm(p, mem_ctx, &handle)) {
948 ret = False;
951 if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
952 ret = False;
955 if (!test_EnumPrinterDataEx(p, mem_ctx, &handle)) {
956 ret = False;
959 if (!test_EnumJobs(p, mem_ctx, &handle)) {
960 ret = False;
963 if (!test_SetPrinterData(p, mem_ctx, &handle)) {
964 ret = False;
967 if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
968 ret = False;
971 if (!test_ClosePrinter(p, mem_ctx, &handle)) {
972 ret = False;
975 return ret;
978 static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
980 struct spoolss_EnumPrinters r;
981 NTSTATUS status;
982 uint16_t levels[] = {1, 2, 4, 5};
983 int i;
984 BOOL ret = True;
986 for (i=0;i<ARRAY_SIZE(levels);i++) {
987 uint32_t buf_size = 0;
988 union spoolss_PrinterInfo *info;
989 int j;
991 r.in.flags = PRINTER_ENUM_LOCAL;
992 r.in.server = "";
993 r.in.level = levels[i];
994 r.in.buffer = NULL;
995 r.in.buf_size = &buf_size;
996 r.out.buf_size = &buf_size;
998 printf("\nTesting EnumPrinters level %u\n", r.in.level);
1000 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 printf("EnumPrinters failed - %s\n", nt_errstr(status));
1003 ret = False;
1004 continue;
1007 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1008 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
1009 data_blob_clear(&blob);
1010 r.in.buffer = &blob;
1011 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 printf("EnumPrinters failed - %s\n",
1016 nt_errstr(status));
1017 continue;
1020 if (!W_ERROR_IS_OK(r.out.result)) {
1021 printf("EnumPrinters failed - %s\n",
1022 win_errstr(r.out.result));
1023 continue;
1026 if (!r.out.info) {
1027 printf("No printers returned");
1028 continue;
1031 info = *r.out.info;
1033 for (j=0;j<r.out.count;j++) {
1034 if (r.in.level == 1) {
1035 /* the names appear to be comma-separated name lists? */
1036 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
1037 char *comma = strchr(name, ',');
1038 if (comma) *comma = 0;
1039 if (!test_OpenPrinter(p, mem_ctx, name)) {
1040 ret = False;
1042 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
1043 ret = False;
1049 return ret;
1052 #if 0
1053 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1054 struct policy_handle *handle,
1055 const char *driver_name)
1057 NTSTATUS status;
1058 struct spoolss_GetPrinterDriver2 r;
1059 uint32_t buf_size;
1061 r.in.handle = handle;
1062 r.in.architecture = "W32X86";
1063 r.in.level = 1;
1064 buf_size = 0;
1065 r.in.buffer = NULL;
1066 r.in.buf_size = r.out.buf_size = &buf_size;
1067 r.in.client_major_version = 0;
1068 r.in.client_minor_version = 0;
1070 printf("Testing GetPrinterDriver2\n");
1072 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1074 if (!NT_STATUS_IS_OK(status)) {
1075 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1076 return False;
1079 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1080 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1083 if (!NT_STATUS_IS_OK(status)) {
1084 printf("GetPrinterDriver2 failed - %s\n",
1085 nt_errstr(status));
1086 return False;
1089 if (!W_ERROR_IS_OK(r.out.result)) {
1090 printf("GetPrinterDriver2 failed - %s\n",
1091 win_errstr(r.out.result));
1092 return False;
1095 return True;
1097 #endif
1099 static BOOL test_EnumPrinterDrivers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1101 struct spoolss_EnumPrinterDrivers r;
1102 NTSTATUS status;
1103 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1104 int i;
1105 BOOL ret = True;
1107 for (i=0;i<ARRAY_SIZE(levels);i++) {
1108 uint32_t buf_size;
1110 r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1111 r.in.environment = "Windows NT x86";
1112 r.in.level = levels[i];
1113 r.in.buffer = NULL;
1114 buf_size = 0;
1115 r.in.buf_size = &buf_size;
1116 r.out.buf_size = &buf_size;
1118 printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
1120 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 printf("EnumPrinterDrivers failed - %s\n",
1124 nt_errstr(status));
1125 ret = False;
1126 continue;
1129 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1130 DATA_BLOB blob = data_blob_talloc(
1131 mem_ctx, NULL, buf_size);
1133 data_blob_clear(&blob);
1134 r.in.buffer = &blob;
1135 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
1138 if (!NT_STATUS_IS_OK(status)) {
1139 printf("EnumPrinterDrivers failed - %s\n",
1140 nt_errstr(status));
1141 ret = False;
1142 break;
1145 if (!W_ERROR_IS_OK(r.out.result)) {
1146 printf("EnumPrinterDrivers failed - %s\n",
1147 win_errstr(r.out.result));
1148 ret = False;
1149 break;
1152 if (!r.out.info) {
1153 printf("No printer drivers returned");
1154 break;
1158 return ret;
1161 BOOL torture_rpc_spoolss(void)
1163 NTSTATUS status;
1164 struct dcerpc_pipe *p;
1165 TALLOC_CTX *mem_ctx;
1166 BOOL ret = True;
1168 mem_ctx = talloc_init("torture_rpc_spoolss");
1170 status = torture_rpc_connection(mem_ctx,
1171 &p,
1172 DCERPC_SPOOLSS_NAME,
1173 DCERPC_SPOOLSS_UUID,
1174 DCERPC_SPOOLSS_VERSION);
1175 if (!NT_STATUS_IS_OK(status)) {
1176 talloc_free(mem_ctx);
1177 return False;
1180 ret &= test_OpenPrinter_badnames(p, mem_ctx);
1182 ret &= test_AddPort(p, mem_ctx);
1184 ret &= test_EnumPorts(p, mem_ctx);
1186 ret &= test_EnumPrinters(p, mem_ctx);
1188 ret &= test_EnumPrinterDrivers(p, mem_ctx);
1190 talloc_free(mem_ctx);
1192 return ret;