r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / rpcclient / cmd_spoolss.c
bloba16c7ea52073e2aec96d35ed89680dd522368ab5
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "rpcclient.h"
28 struct table_node {
29 const char *long_archi;
30 const char *short_archi;
31 int version;
34 /* The version int is used by getdrivers. Note that
35 all architecture strings that support mutliple
36 versions must be grouped together since enumdrivers
37 uses this property to prevent issuing multiple
38 enumdriver calls for the same arch */
41 static const struct table_node archi_table[]= {
43 {"Windows 4.0", "WIN40", 0 },
44 {"Windows NT x86", "W32X86", 2 },
45 {"Windows NT x86", "W32X86", 3 },
46 {"Windows NT R4000", "W32MIPS", 2 },
47 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
48 {"Windows NT PowerPC", "W32PPC", 2 },
49 {"Windows IA64", "IA64", 3 },
50 {"Windows x64", "x64", 3 },
51 {NULL, "", -1 }
54 /**
55 * @file
57 * rpcclient module for SPOOLSS rpc pipe.
59 * This generally just parses and checks command lines, and then calls
60 * a cli_spoolss function.
61 **/
63 /****************************************************************************
64 function to do the mapping between the long architecture name and
65 the short one.
66 ****************************************************************************/
68 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
70 int i=-1;
72 DEBUG(107,("Getting architecture dependant directory\n"));
73 do {
74 i++;
75 } while ( (archi_table[i].long_archi!=NULL ) &&
76 StrCaseCmp(long_archi, archi_table[i].long_archi) );
78 if (archi_table[i].long_archi==NULL) {
79 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
80 return NULL;
83 /* this might be client code - but shouldn't this be an fstrcpy etc? */
86 DEBUGADD(108,("index: [%d]\n", i));
87 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
88 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
90 return archi_table[i].short_archi;
93 /****************************************************************************
94 ****************************************************************************/
96 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
97 TALLOC_CTX *mem_ctx,
98 int argc, const char **argv)
100 WERROR werror;
101 fstring printername;
102 fstring servername, user;
103 POLICY_HND hnd;
105 if (argc != 2) {
106 printf("Usage: %s <printername>\n", argv[0]);
107 return WERR_OK;
110 if (!cli)
111 return WERR_GENERAL_FAILURE;
113 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
114 strupper_m(servername);
115 fstrcpy(user, cli->user_name);
116 fstrcpy(printername, argv[1]);
118 /* Open the printer handle */
120 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
121 "", PRINTER_ALL_ACCESS,
122 servername, user, &hnd);
124 if (W_ERROR_IS_OK(werror)) {
125 printf("Printer %s opened successfully\n", printername);
126 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
128 if (!W_ERROR_IS_OK(werror)) {
129 printf("Error closing printer handle! (%s)\n",
130 get_dos_error_msg(werror));
134 return werror;
138 /****************************************************************************
139 ****************************************************************************/
141 static void display_print_info_0(PRINTER_INFO_0 *i0)
143 fstring name = "";
144 fstring servername = "";
146 if (!i0)
147 return;
149 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
151 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
153 printf("\tprintername:[%s]\n", name);
154 printf("\tservername:[%s]\n", servername);
155 printf("\tcjobs:[0x%x]\n", i0->cjobs);
156 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
158 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
159 i0->day, i0->dayofweek);
160 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
161 i0->second, i0->milliseconds);
163 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
164 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
166 printf("\tmajorversion:[0x%x]\n", i0->major_version);
167 printf("\tbuildversion:[0x%x]\n", i0->build_version);
169 printf("\tunknown7:[0x%x]\n", i0->unknown7);
170 printf("\tunknown8:[0x%x]\n", i0->unknown8);
171 printf("\tunknown9:[0x%x]\n", i0->unknown9);
172 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
173 printf("\tunknown11:[0x%x]\n", i0->unknown11);
174 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
175 printf("\tunknown13:[0x%x]\n", i0->unknown13);
176 printf("\tunknown14:[0x%x]\n", i0->unknown14);
177 printf("\tunknown15:[0x%x]\n", i0->unknown15);
178 printf("\tunknown16:[0x%x]\n", i0->unknown16);
179 printf("\tchange_id:[0x%x]\n", i0->change_id);
180 printf("\tunknown18:[0x%x]\n", i0->unknown18);
181 printf("\tstatus:[0x%x]\n", i0->status);
182 printf("\tunknown20:[0x%x]\n", i0->unknown20);
183 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
184 printf("\tunknown22:[0x%x]\n", i0->unknown22);
185 printf("\tunknown23:[0x%x]\n", i0->unknown23);
186 printf("\tunknown24:[0x%x]\n", i0->unknown24);
187 printf("\tunknown25:[0x%x]\n", i0->unknown25);
188 printf("\tunknown26:[0x%x]\n", i0->unknown26);
189 printf("\tunknown27:[0x%x]\n", i0->unknown27);
190 printf("\tunknown28:[0x%x]\n", i0->unknown28);
191 printf("\tunknown29:[0x%x]\n", i0->unknown29);
193 printf("\n");
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info_1(PRINTER_INFO_1 *i1)
201 fstring desc = "";
202 fstring name = "";
203 fstring comm = "";
205 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
206 STR_TERMINATE);
208 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
209 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
211 printf("\tflags:[0x%x]\n", i1->flags);
212 printf("\tname:[%s]\n", name);
213 printf("\tdescription:[%s]\n", desc);
214 printf("\tcomment:[%s]\n", comm);
216 printf("\n");
219 /****************************************************************************
220 ****************************************************************************/
222 static void display_print_info_2(PRINTER_INFO_2 *i2)
224 fstring servername = "";
225 fstring printername = "";
226 fstring sharename = "";
227 fstring portname = "";
228 fstring drivername = "";
229 fstring comment = "";
230 fstring location = "";
231 fstring sepfile = "";
232 fstring printprocessor = "";
233 fstring datatype = "";
234 fstring parameters = "";
236 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
237 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
238 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
239 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
240 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
241 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
242 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
243 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
244 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
245 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
246 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
248 printf("\tservername:[%s]\n", servername);
249 printf("\tprintername:[%s]\n", printername);
250 printf("\tsharename:[%s]\n", sharename);
251 printf("\tportname:[%s]\n", portname);
252 printf("\tdrivername:[%s]\n", drivername);
253 printf("\tcomment:[%s]\n", comment);
254 printf("\tlocation:[%s]\n", location);
255 printf("\tsepfile:[%s]\n", sepfile);
256 printf("\tprintprocessor:[%s]\n", printprocessor);
257 printf("\tdatatype:[%s]\n", datatype);
258 printf("\tparameters:[%s]\n", parameters);
259 printf("\tattributes:[0x%x]\n", i2->attributes);
260 printf("\tpriority:[0x%x]\n", i2->priority);
261 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
262 printf("\tstarttime:[0x%x]\n", i2->starttime);
263 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
264 printf("\tstatus:[0x%x]\n", i2->status);
265 printf("\tcjobs:[0x%x]\n", i2->cjobs);
266 printf("\taverageppm:[0x%x]\n", i2->averageppm);
268 if (i2->secdesc)
269 display_sec_desc(i2->secdesc);
271 printf("\n");
274 /****************************************************************************
275 ****************************************************************************/
277 static void display_print_info_3(PRINTER_INFO_3 *i3)
279 display_sec_desc(i3->secdesc);
281 printf("\n");
284 /****************************************************************************
285 ****************************************************************************/
287 static void display_print_info_7(PRINTER_INFO_7 *i7)
289 fstring guid = "";
290 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
291 printf("\tguid:[%s]\n", guid);
292 printf("\taction:[0x%x]\n", i7->action);
296 /****************************************************************************
297 ****************************************************************************/
299 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
300 TALLOC_CTX *mem_ctx,
301 int argc, const char **argv)
303 WERROR result;
304 uint32 info_level = 1;
305 PRINTER_INFO_CTR ctr;
306 uint32 i = 0, num_printers;
307 fstring name;
309 if (argc > 3)
311 printf("Usage: %s [level] [name]\n", argv[0]);
312 return WERR_OK;
315 if (argc >= 2)
316 info_level = atoi(argv[1]);
318 if (argc == 3)
319 fstrcpy(name, argv[2]);
320 else {
321 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
322 strupper_m(name);
325 ZERO_STRUCT(ctr);
327 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
328 info_level, &num_printers, &ctr);
330 if (W_ERROR_IS_OK(result)) {
332 if (!num_printers) {
333 printf ("No printers returned.\n");
334 goto done;
337 for (i = 0; i < num_printers; i++) {
338 switch(info_level) {
339 case 0:
340 display_print_info_0(&ctr.printers_0[i]);
341 break;
342 case 1:
343 display_print_info_1(&ctr.printers_1[i]);
344 break;
345 case 2:
346 display_print_info_2(&ctr.printers_2[i]);
347 break;
348 case 3:
349 display_print_info_3(&ctr.printers_3[i]);
350 break;
351 default:
352 printf("unknown info level %d\n", info_level);
353 goto done;
357 done:
359 return result;
362 /****************************************************************************
363 ****************************************************************************/
365 static void display_port_info_1(PORT_INFO_1 *i1)
367 fstring buffer;
369 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
370 printf("\tPort Name:\t[%s]\n", buffer);
373 /****************************************************************************
374 ****************************************************************************/
376 static void display_port_info_2(PORT_INFO_2 *i2)
378 fstring buffer;
380 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
381 printf("\tPort Name:\t[%s]\n", buffer);
382 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
384 printf("\tMonitor Name:\t[%s]\n", buffer);
385 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
387 printf("\tDescription:\t[%s]\n", buffer);
388 printf("\tPort Type:\t" );
389 if ( i2->port_type ) {
390 int comma = 0; /* hack */
391 printf( "[" );
392 if ( i2->port_type & PORT_TYPE_READ ) {
393 printf( "Read" );
394 comma = 1;
396 if ( i2->port_type & PORT_TYPE_WRITE ) {
397 printf( "%sWrite", comma ? ", " : "" );
398 comma = 1;
400 /* These two have slightly different interpretations
401 on 95/98/ME but I'm disregarding that for now */
402 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
403 printf( "%sRedirected", comma ? ", " : "" );
404 comma = 1;
406 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
407 printf( "%sNet-Attached", comma ? ", " : "" );
409 printf( "]\n" );
410 } else {
411 printf( "[Unset]\n" );
413 printf("\tReserved:\t[%d]\n", i2->reserved);
414 printf("\n");
417 /****************************************************************************
418 ****************************************************************************/
420 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
421 TALLOC_CTX *mem_ctx, int argc,
422 const char **argv)
424 WERROR result;
425 uint32 info_level = 1;
426 PORT_INFO_CTR ctr;
427 uint32 returned;
429 if (argc > 2) {
430 printf("Usage: %s [level]\n", argv[0]);
431 return WERR_OK;
434 if (argc == 2)
435 info_level = atoi(argv[1]);
437 /* Enumerate ports */
439 ZERO_STRUCT(ctr);
441 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
443 if (W_ERROR_IS_OK(result)) {
444 int i;
446 for (i = 0; i < returned; i++) {
447 switch (info_level) {
448 case 1:
449 display_port_info_1(&ctr.port.info_1[i]);
450 break;
451 case 2:
452 display_port_info_2(&ctr.port.info_2[i]);
453 break;
454 default:
455 printf("unknown info level %d\n", info_level);
456 break;
461 return result;
464 /****************************************************************************
465 ****************************************************************************/
467 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
468 TALLOC_CTX *mem_ctx,
469 int argc, const char **argv)
471 POLICY_HND pol;
472 WERROR result;
473 uint32 info_level = 2;
474 BOOL opened_hnd = False;
475 PRINTER_INFO_CTR ctr;
476 fstring printername,
477 servername,
478 user,
479 comment;
481 if (argc == 1 || argc > 3) {
482 printf("Usage: %s printername comment\n", argv[0]);
484 return WERR_OK;
487 /* Open a printer handle */
488 if (argc == 3) {
489 fstrcpy(comment, argv[2]);
492 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
493 strupper_m(servername);
494 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
495 fstrcpy(user, cli->user_name);
497 /* get a printer handle */
498 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
499 PRINTER_ALL_ACCESS, servername,
500 user, &pol);
502 if (!W_ERROR_IS_OK(result))
503 goto done;
505 opened_hnd = True;
507 /* Get printer info */
508 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
510 if (!W_ERROR_IS_OK(result))
511 goto done;
514 /* Modify the comment. */
515 init_unistr(&ctr.printers_2->comment, comment);
516 ctr.printers_2->devmode = NULL;
517 ctr.printers_2->secdesc = NULL;
519 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
520 if (W_ERROR_IS_OK(result))
521 printf("Success in setting comment.\n");
523 done:
524 if (opened_hnd)
525 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
527 return result;
530 /****************************************************************************
531 ****************************************************************************/
533 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
534 TALLOC_CTX *mem_ctx,
535 int argc, const char **argv)
537 POLICY_HND pol;
538 WERROR result;
539 uint32 info_level = 2;
540 BOOL opened_hnd = False;
541 PRINTER_INFO_CTR ctr;
542 fstring printername,
543 servername,
544 user,
545 new_printername;
547 if (argc == 1 || argc > 3) {
548 printf("Usage: %s printername new_printername\n", argv[0]);
550 return WERR_OK;
553 /* Open a printer handle */
554 if (argc == 3) {
555 fstrcpy(new_printername, argv[2]);
558 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
559 strupper_m(servername);
560 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
561 fstrcpy(user, cli->user_name);
563 /* get a printer handle */
564 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
565 PRINTER_ALL_ACCESS, servername,
566 user, &pol);
568 if (!W_ERROR_IS_OK(result))
569 goto done;
571 opened_hnd = True;
573 /* Get printer info */
574 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
576 if (!W_ERROR_IS_OK(result))
577 goto done;
579 /* Modify the printername. */
580 init_unistr(&ctr.printers_2->printername, new_printername);
581 ctr.printers_2->devmode = NULL;
582 ctr.printers_2->secdesc = NULL;
584 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
585 if (W_ERROR_IS_OK(result))
586 printf("Success in setting printername.\n");
588 done:
589 if (opened_hnd)
590 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
592 return result;
595 /****************************************************************************
596 ****************************************************************************/
598 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
599 TALLOC_CTX *mem_ctx,
600 int argc, const char **argv)
602 POLICY_HND pol;
603 WERROR result;
604 uint32 info_level = 1;
605 BOOL opened_hnd = False;
606 PRINTER_INFO_CTR ctr;
607 fstring printername,
608 servername,
609 user;
611 if (argc == 1 || argc > 3) {
612 printf("Usage: %s <printername> [level]\n", argv[0]);
613 return WERR_OK;
616 /* Open a printer handle */
617 if (argc == 3) {
618 info_level = atoi(argv[2]);
621 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
622 strupper_m(servername);
623 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
624 fstrcpy(user, cli->user_name);
626 /* get a printer handle */
628 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
629 "", MAXIMUM_ALLOWED_ACCESS,
630 servername, user, &pol);
632 if (!W_ERROR_IS_OK(result))
633 goto done;
635 opened_hnd = True;
637 /* Get printer info */
639 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
641 if (!W_ERROR_IS_OK(result))
642 goto done;
644 /* Display printer info */
646 switch (info_level) {
647 case 0:
648 display_print_info_0(ctr.printers_0);
649 break;
650 case 1:
651 display_print_info_1(ctr.printers_1);
652 break;
653 case 2:
654 display_print_info_2(ctr.printers_2);
655 break;
656 case 3:
657 display_print_info_3(ctr.printers_3);
658 break;
659 case 7:
660 display_print_info_7(ctr.printers_7);
661 break;
662 default:
663 printf("unknown info level %d\n", info_level);
664 break;
667 done:
668 if (opened_hnd)
669 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
671 return result;
674 /****************************************************************************
675 ****************************************************************************/
677 static void display_reg_value(REGISTRY_VALUE value)
679 pstring text;
681 switch(value.type) {
682 case REG_DWORD:
683 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
684 *((uint32 *) value.data_p));
685 break;
686 case REG_SZ:
687 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
688 STR_TERMINATE);
689 printf("%s: REG_SZ: %s\n", value.valuename, text);
690 break;
691 case REG_BINARY: {
692 char *hex = hex_encode(NULL, value.data_p, value.size);
693 size_t i, len;
694 printf("%s: REG_BINARY:", value.valuename);
695 len = strlen(hex);
696 for (i=0; i<len; i++) {
697 if (hex[i] == '\0') {
698 break;
700 if (i%40 == 0) {
701 putchar('\n');
703 putchar(hex[i]);
705 TALLOC_FREE(hex);
706 putchar('\n');
707 break;
709 case REG_MULTI_SZ: {
710 uint32 i, num_values;
711 char **values;
713 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
714 value.size, &num_values,
715 &values))) {
716 d_printf("reg_pull_multi_sz failed\n");
717 break;
720 for (i=0; i<num_values; i++) {
721 d_printf("%s\n", values[i]);
723 TALLOC_FREE(values);
724 break;
726 default:
727 printf("%s: unknown type %d\n", value.valuename, value.type);
732 /****************************************************************************
733 ****************************************************************************/
735 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
736 TALLOC_CTX *mem_ctx,
737 int argc, const char **argv)
739 POLICY_HND pol;
740 WERROR result;
741 BOOL opened_hnd = False;
742 fstring printername,
743 servername,
744 user;
745 const char *valuename;
746 REGISTRY_VALUE value;
748 if (argc != 3) {
749 printf("Usage: %s <printername> <valuename>\n", argv[0]);
750 printf("<printername> of . queries print server\n");
751 return WERR_OK;
753 valuename = argv[2];
755 /* Open a printer handle */
757 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
758 strupper_m(servername);
759 if (strncmp(argv[1], ".", sizeof(".")) == 0)
760 fstrcpy(printername, servername);
761 else
762 slprintf(printername, sizeof(servername)-1, "%s\\%s",
763 servername, argv[1]);
764 fstrcpy(user, cli->user_name);
766 /* get a printer handle */
768 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
769 "", MAXIMUM_ALLOWED_ACCESS,
770 servername, user, &pol);
772 if (!W_ERROR_IS_OK(result))
773 goto done;
775 opened_hnd = True;
777 /* Get printer info */
779 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
781 if (!W_ERROR_IS_OK(result))
782 goto done;
784 /* Display printer data */
786 fstrcpy(value.valuename, valuename);
787 display_reg_value(value);
790 done:
791 if (opened_hnd)
792 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
794 return result;
797 /****************************************************************************
798 ****************************************************************************/
800 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
801 TALLOC_CTX *mem_ctx,
802 int argc, const char **argv)
804 POLICY_HND pol;
805 WERROR result;
806 BOOL opened_hnd = False;
807 fstring printername,
808 servername,
809 user;
810 const char *valuename, *keyname;
811 REGISTRY_VALUE value;
813 if (argc != 4) {
814 printf("Usage: %s <printername> <keyname> <valuename>\n",
815 argv[0]);
816 printf("<printername> of . queries print server\n");
817 return WERR_OK;
819 valuename = argv[3];
820 keyname = argv[2];
822 /* Open a printer handle */
824 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
825 strupper_m(servername);
826 if (strncmp(argv[1], ".", sizeof(".")) == 0)
827 fstrcpy(printername, servername);
828 else
829 slprintf(printername, sizeof(printername)-1, "%s\\%s",
830 servername, argv[1]);
831 fstrcpy(user, cli->user_name);
833 /* get a printer handle */
835 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
836 "", MAXIMUM_ALLOWED_ACCESS,
837 servername, user, &pol);
839 if (!W_ERROR_IS_OK(result))
840 goto done;
842 opened_hnd = True;
844 /* Get printer info */
846 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
847 valuename, &value);
849 if (!W_ERROR_IS_OK(result))
850 goto done;
852 /* Display printer data */
854 fstrcpy(value.valuename, valuename);
855 display_reg_value(value);
858 done:
859 if (opened_hnd)
860 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
862 return result;
865 /****************************************************************************
866 ****************************************************************************/
868 static void display_print_driver_1(DRIVER_INFO_1 *i1)
870 fstring name;
871 if (i1 == NULL)
872 return;
874 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
876 printf ("Printer Driver Info 1:\n");
877 printf ("\tDriver Name: [%s]\n\n", name);
879 return;
882 /****************************************************************************
883 ****************************************************************************/
885 static void display_print_driver_2(DRIVER_INFO_2 *i1)
887 fstring name;
888 fstring architecture;
889 fstring driverpath;
890 fstring datafile;
891 fstring configfile;
892 if (i1 == NULL)
893 return;
895 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
896 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
897 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
898 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
899 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
901 printf ("Printer Driver Info 2:\n");
902 printf ("\tVersion: [%x]\n", i1->version);
903 printf ("\tDriver Name: [%s]\n", name);
904 printf ("\tArchitecture: [%s]\n", architecture);
905 printf ("\tDriver Path: [%s]\n", driverpath);
906 printf ("\tDatafile: [%s]\n", datafile);
907 printf ("\tConfigfile: [%s]\n\n", configfile);
909 return;
912 /****************************************************************************
913 ****************************************************************************/
915 static void display_print_driver_3(DRIVER_INFO_3 *i1)
917 fstring name = "";
918 fstring architecture = "";
919 fstring driverpath = "";
920 fstring datafile = "";
921 fstring configfile = "";
922 fstring helpfile = "";
923 fstring dependentfiles = "";
924 fstring monitorname = "";
925 fstring defaultdatatype = "";
927 int length=0;
928 BOOL valid = True;
930 if (i1 == NULL)
931 return;
933 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
934 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
935 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
936 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
937 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
938 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
939 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
940 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
942 printf ("Printer Driver Info 3:\n");
943 printf ("\tVersion: [%x]\n", i1->version);
944 printf ("\tDriver Name: [%s]\n",name);
945 printf ("\tArchitecture: [%s]\n", architecture);
946 printf ("\tDriver Path: [%s]\n", driverpath);
947 printf ("\tDatafile: [%s]\n", datafile);
948 printf ("\tConfigfile: [%s]\n", configfile);
949 printf ("\tHelpfile: [%s]\n\n", helpfile);
951 while (valid)
953 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
955 length+=strlen(dependentfiles)+1;
957 if (strlen(dependentfiles) > 0)
959 printf ("\tDependentfiles: [%s]\n", dependentfiles);
961 else
963 valid = False;
967 printf ("\n");
969 printf ("\tMonitorname: [%s]\n", monitorname);
970 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
972 return;
975 /****************************************************************************
976 ****************************************************************************/
978 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
979 TALLOC_CTX *mem_ctx,
980 int argc, const char **argv)
982 POLICY_HND pol;
983 WERROR werror;
984 uint32 info_level = 3;
985 BOOL opened_hnd = False;
986 PRINTER_DRIVER_CTR ctr;
987 fstring printername,
988 servername,
989 user;
990 uint32 i;
991 BOOL success = False;
993 if ((argc == 1) || (argc > 3))
995 printf("Usage: %s <printername> [level]\n", argv[0]);
996 return WERR_OK;
999 /* get the arguments need to open the printer handle */
1000 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1001 strupper_m(servername);
1002 fstrcpy(user, cli->user_name);
1003 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1004 if (argc == 3)
1005 info_level = atoi(argv[2]);
1007 /* Open a printer handle */
1009 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1010 PRINTER_ACCESS_USE,
1011 servername, user, &pol);
1013 if (!W_ERROR_IS_OK(werror)) {
1014 printf("Error opening printer handle for %s!\n", printername);
1015 return werror;
1018 opened_hnd = True;
1020 /* loop through and print driver info level for each architecture */
1022 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1024 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1025 archi_table[i].long_archi, archi_table[i].version,
1026 &ctr);
1028 if (!W_ERROR_IS_OK(werror))
1029 continue;
1031 /* need at least one success */
1033 success = True;
1035 printf ("\n[%s]\n", archi_table[i].long_archi);
1037 switch (info_level) {
1038 case 1:
1039 display_print_driver_1 (ctr.info1);
1040 break;
1041 case 2:
1042 display_print_driver_2 (ctr.info2);
1043 break;
1044 case 3:
1045 display_print_driver_3 (ctr.info3);
1046 break;
1047 default:
1048 printf("unknown info level %d\n", info_level);
1049 break;
1053 /* Cleanup */
1055 if (opened_hnd)
1056 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1058 if ( success )
1059 werror = WERR_OK;
1061 return werror;
1064 /****************************************************************************
1065 ****************************************************************************/
1067 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1068 TALLOC_CTX *mem_ctx,
1069 int argc, const char **argv)
1071 WERROR werror = WERR_OK;
1072 uint32 info_level = 1;
1073 PRINTER_DRIVER_CTR ctr;
1074 uint32 i, j,
1075 returned;
1077 if (argc > 2) {
1078 printf("Usage: enumdrivers [level]\n");
1079 return WERR_OK;
1082 if (argc == 2)
1083 info_level = atoi(argv[1]);
1086 /* loop through and print driver info level for each architecture */
1087 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1088 /* check to see if we already asked for this architecture string */
1090 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1091 continue;
1093 werror = rpccli_spoolss_enumprinterdrivers(
1094 cli, mem_ctx, info_level,
1095 archi_table[i].long_archi, &returned, &ctr);
1097 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1098 printf ("Server does not support environment [%s]\n",
1099 archi_table[i].long_archi);
1100 werror = WERR_OK;
1101 continue;
1104 if (returned == 0)
1105 continue;
1107 if (!W_ERROR_IS_OK(werror)) {
1108 printf ("Error getting driver for environment [%s] - %d\n",
1109 archi_table[i].long_archi, W_ERROR_V(werror));
1110 continue;
1113 printf ("\n[%s]\n", archi_table[i].long_archi);
1114 switch (info_level)
1117 case 1:
1118 for (j=0; j < returned; j++) {
1119 display_print_driver_1 (&ctr.info1[j]);
1121 break;
1122 case 2:
1123 for (j=0; j < returned; j++) {
1124 display_print_driver_2 (&ctr.info2[j]);
1126 break;
1127 case 3:
1128 for (j=0; j < returned; j++) {
1129 display_print_driver_3 (&ctr.info3[j]);
1131 break;
1132 default:
1133 printf("unknown info level %d\n", info_level);
1134 return WERR_UNKNOWN_LEVEL;
1138 return werror;
1141 /****************************************************************************
1142 ****************************************************************************/
1144 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1146 fstring name;
1147 if (i1 == NULL)
1148 return;
1150 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1152 printf ("\tDirectory Name:[%s]\n", name);
1155 /****************************************************************************
1156 ****************************************************************************/
1158 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1159 TALLOC_CTX *mem_ctx,
1160 int argc, const char **argv)
1162 WERROR result;
1163 fstring env;
1164 DRIVER_DIRECTORY_CTR ctr;
1166 if (argc > 2) {
1167 printf("Usage: %s [environment]\n", argv[0]);
1168 return WERR_OK;
1171 /* Get the arguments need to open the printer handle */
1173 if (argc == 2)
1174 fstrcpy (env, argv[1]);
1175 else
1176 fstrcpy (env, "Windows NT x86");
1178 /* Get the directory. Only use Info level 1 */
1180 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1182 if (W_ERROR_IS_OK(result))
1183 display_printdriverdir_1(ctr.info1);
1185 return result;
1188 /****************************************************************************
1189 ****************************************************************************/
1191 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1194 int i;
1196 for (i=0; archi_table[i].long_archi != NULL; i++)
1198 if (strcmp(arch, archi_table[i].short_archi) == 0)
1200 info->version = archi_table[i].version;
1201 init_unistr (&info->architecture, archi_table[i].long_archi);
1202 break;
1206 if (archi_table[i].long_archi == NULL)
1208 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1211 return;
1215 /**************************************************************************
1216 wrapper for strtok to get the next parameter from a delimited list.
1217 Needed to handle the empty parameter string denoted by "NULL"
1218 *************************************************************************/
1220 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1222 char *ptr;
1224 /* get the next token */
1225 ptr = strtok(str, delim);
1227 /* a string of 'NULL' is used to represent an empty
1228 parameter because two consecutive delimiters
1229 will not return an empty string. See man strtok(3)
1230 for details */
1231 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1232 ptr = NULL;
1234 if (dest != NULL)
1235 init_unistr(dest, ptr);
1237 return ptr;
1240 /********************************************************************************
1241 fill in the members of a DRIVER_INFO_3 struct using a character
1242 string in the form of
1243 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1244 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1245 <Default Data Type>:<Comma Separated list of Files>
1246 *******************************************************************************/
1247 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1248 char *args )
1250 char *str, *str2;
1251 uint32 len, i;
1253 /* fill in the UNISTR fields */
1254 str = get_driver_3_param (args, ":", &info->name);
1255 str = get_driver_3_param (NULL, ":", &info->driverpath);
1256 str = get_driver_3_param (NULL, ":", &info->datafile);
1257 str = get_driver_3_param (NULL, ":", &info->configfile);
1258 str = get_driver_3_param (NULL, ":", &info->helpfile);
1259 str = get_driver_3_param (NULL, ":", &info->monitorname);
1260 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1262 /* <Comma Separated List of Dependent Files> */
1263 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1264 str = str2;
1266 /* begin to strip out each filename */
1267 str = strtok(str, ",");
1268 len = 0;
1269 while (str != NULL)
1271 /* keep a cumlative count of the str lengths */
1272 len += strlen(str)+1;
1273 str = strtok(NULL, ",");
1276 /* allocate the space; add one extra slot for a terminating NULL.
1277 Each filename is NULL terminated and the end contains a double
1278 NULL */
1279 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1281 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1282 return False;
1284 for (i=0; i<len; i++)
1286 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1288 info->dependentfiles[len] = '\0';
1290 return True;
1294 /****************************************************************************
1295 ****************************************************************************/
1297 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1298 TALLOC_CTX *mem_ctx,
1299 int argc, const char **argv)
1301 WERROR result;
1302 uint32 level = 3;
1303 PRINTER_DRIVER_CTR ctr;
1304 DRIVER_INFO_3 info3;
1305 const char *arch;
1306 fstring driver_name;
1307 char *driver_args;
1309 /* parse the command arguements */
1310 if (argc != 3 && argc != 4)
1312 printf ("Usage: %s <Environment> \\\n", argv[0]);
1313 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1314 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1315 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1316 printf ("\t[version]\n");
1318 return WERR_OK;
1321 /* Fill in the DRIVER_INFO_3 struct */
1322 ZERO_STRUCT(info3);
1323 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1325 printf ("Error Unknown architechture [%s]\n", argv[1]);
1326 return WERR_INVALID_PARAM;
1328 else
1329 set_drv_info_3_env(&info3, arch);
1331 driver_args = talloc_strdup( mem_ctx, argv[2] );
1332 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1334 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1335 return WERR_INVALID_PARAM;
1338 /* if printer driver version specified, override the default version
1339 * used by the architecture. This allows installation of Windows
1340 * 2000 (version 3) printer drivers. */
1341 if (argc == 4)
1343 info3.version = atoi(argv[3]);
1347 ctr.info3 = &info3;
1348 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1350 if (W_ERROR_IS_OK(result)) {
1351 rpcstr_pull(driver_name, info3.name.buffer,
1352 sizeof(driver_name), -1, STR_TERMINATE);
1353 printf ("Printer Driver %s successfully installed.\n",
1354 driver_name);
1357 return result;
1361 /****************************************************************************
1362 ****************************************************************************/
1364 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1365 TALLOC_CTX *mem_ctx,
1366 int argc, const char **argv)
1368 WERROR result;
1369 uint32 level = 2;
1370 PRINTER_INFO_CTR ctr;
1371 PRINTER_INFO_2 info2;
1372 fstring servername;
1374 /* parse the command arguements */
1375 if (argc != 5)
1377 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1378 return WERR_OK;
1381 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1382 strupper_m(servername);
1384 /* Fill in the DRIVER_INFO_2 struct */
1385 ZERO_STRUCT(info2);
1387 init_unistr( &info2.printername, argv[1]);
1388 init_unistr( &info2.sharename, argv[2]);
1389 init_unistr( &info2.drivername, argv[3]);
1390 init_unistr( &info2.portname, argv[4]);
1391 init_unistr( &info2.comment, "Created by rpcclient");
1392 init_unistr( &info2.printprocessor, "winprint");
1393 init_unistr( &info2.datatype, "RAW");
1394 info2.devmode = NULL;
1395 info2.secdesc = NULL;
1396 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1397 info2.priority = 0;
1398 info2.defaultpriority = 0;
1399 info2.starttime = 0;
1400 info2.untiltime = 0;
1402 /* These three fields must not be used by AddPrinter()
1403 as defined in the MS Platform SDK documentation..
1404 --jerry
1405 info2.status = 0;
1406 info2.cjobs = 0;
1407 info2.averageppm = 0;
1410 ctr.printers_2 = &info2;
1411 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1413 if (W_ERROR_IS_OK(result))
1414 printf ("Printer %s successfully installed.\n", argv[1]);
1416 return result;
1419 /****************************************************************************
1420 ****************************************************************************/
1422 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1423 TALLOC_CTX *mem_ctx,
1424 int argc, const char **argv)
1426 POLICY_HND pol;
1427 WERROR result;
1428 uint32 level = 2;
1429 BOOL opened_hnd = False;
1430 PRINTER_INFO_CTR ctr;
1431 PRINTER_INFO_2 info2;
1432 fstring servername,
1433 printername,
1434 user;
1436 /* parse the command arguements */
1437 if (argc != 3)
1439 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1440 return WERR_OK;
1443 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1444 strupper_m(servername);
1445 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1446 fstrcpy(user, cli->user_name);
1448 /* Get a printer handle */
1450 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1451 PRINTER_ALL_ACCESS,
1452 servername, user, &pol);
1454 if (!W_ERROR_IS_OK(result))
1455 goto done;
1457 opened_hnd = True;
1459 /* Get printer info */
1461 ZERO_STRUCT (info2);
1462 ctr.printers_2 = &info2;
1464 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1466 if (!W_ERROR_IS_OK(result)) {
1467 printf ("Unable to retrieve printer information!\n");
1468 goto done;
1471 /* Set the printer driver */
1473 init_unistr(&ctr.printers_2->drivername, argv[2]);
1475 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1477 if (!W_ERROR_IS_OK(result)) {
1478 printf("SetPrinter call failed!\n");
1479 goto done;;
1482 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1484 done:
1485 /* Cleanup */
1487 if (opened_hnd)
1488 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1490 return result;
1494 /****************************************************************************
1495 ****************************************************************************/
1497 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1498 TALLOC_CTX *mem_ctx,
1499 int argc, const char **argv)
1501 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1503 int i;
1504 int vers = -1;
1506 const char *arch = NULL;
1508 /* parse the command arguements */
1509 if (argc < 2 || argc > 4) {
1510 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1511 return WERR_OK;
1514 if (argc >= 3)
1515 arch = argv[2];
1516 if (argc == 4)
1517 vers = atoi (argv[3]);
1520 /* delete the driver for all architectures */
1521 for (i=0; archi_table[i].long_archi; i++) {
1523 if (arch && !strequal( archi_table[i].long_archi, arch))
1524 continue;
1526 if (vers >= 0 && archi_table[i].version != vers)
1527 continue;
1529 /* make the call to remove the driver */
1530 result = rpccli_spoolss_deleteprinterdriverex(
1531 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1533 if ( !W_ERROR_IS_OK(result) )
1535 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1536 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1537 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1540 else
1542 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1543 archi_table[i].long_archi, archi_table[i].version);
1544 ret = WERR_OK;
1548 return ret;
1552 /****************************************************************************
1553 ****************************************************************************/
1555 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1556 TALLOC_CTX *mem_ctx,
1557 int argc, const char **argv)
1559 WERROR result = WERR_OK;
1560 fstring servername;
1561 int i;
1563 /* parse the command arguements */
1564 if (argc != 2) {
1565 printf ("Usage: %s <driver>\n", argv[0]);
1566 return WERR_OK;
1569 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1570 strupper_m(servername);
1572 /* delete the driver for all architectures */
1573 for (i=0; archi_table[i].long_archi; i++) {
1574 /* make the call to remove the driver */
1575 result = rpccli_spoolss_deleteprinterdriver(
1576 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1578 if ( !W_ERROR_IS_OK(result) ) {
1579 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1580 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1581 argv[1], archi_table[i].long_archi,
1582 W_ERROR_V(result));
1584 } else {
1585 printf ("Driver %s removed for arch [%s].\n", argv[1],
1586 archi_table[i].long_archi);
1590 return result;
1593 /****************************************************************************
1594 ****************************************************************************/
1596 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1597 TALLOC_CTX *mem_ctx,
1598 int argc, const char **argv)
1600 WERROR result;
1601 char *servername = NULL, *environment = NULL;
1602 fstring procdir;
1604 /* parse the command arguements */
1605 if (argc > 2) {
1606 printf ("Usage: %s [environment]\n", argv[0]);
1607 return WERR_OK;
1610 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1611 return WERR_NOMEM;
1612 strupper_m(servername);
1614 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1615 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1616 SAFE_FREE(servername);
1617 return WERR_NOMEM;
1620 result = rpccli_spoolss_getprintprocessordirectory(
1621 cli, mem_ctx, servername, environment, procdir);
1623 if (W_ERROR_IS_OK(result))
1624 printf("%s\n", procdir);
1626 SAFE_FREE(servername);
1627 SAFE_FREE(environment);
1629 return result;
1632 /****************************************************************************
1633 ****************************************************************************/
1635 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1636 int argc, const char **argv)
1638 POLICY_HND handle;
1639 WERROR werror;
1640 char *servername = NULL, *printername = NULL;
1641 FORM form;
1642 BOOL got_handle = False;
1644 /* Parse the command arguements */
1646 if (argc != 3) {
1647 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1648 return WERR_OK;
1651 /* Get a printer handle */
1653 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1654 strupper_m(servername);
1655 asprintf(&printername, "%s\\%s", servername, argv[1]);
1657 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1658 PRINTER_ALL_ACCESS,
1659 servername, cli->user_name, &handle);
1661 if (!W_ERROR_IS_OK(werror))
1662 goto done;
1664 got_handle = True;
1666 /* Dummy up some values for the form data */
1668 form.flags = FORM_USER;
1669 form.size_x = form.size_y = 100;
1670 form.left = 0;
1671 form.top = 10;
1672 form.right = 20;
1673 form.bottom = 30;
1675 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1677 /* Add the form */
1680 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1682 done:
1683 if (got_handle)
1684 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1686 SAFE_FREE(servername);
1687 SAFE_FREE(printername);
1689 return werror;
1692 /****************************************************************************
1693 ****************************************************************************/
1695 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1696 int argc, const char **argv)
1698 POLICY_HND handle;
1699 WERROR werror;
1700 char *servername = NULL, *printername = NULL;
1701 FORM form;
1702 BOOL got_handle = False;
1704 /* Parse the command arguements */
1706 if (argc != 3) {
1707 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1708 return WERR_OK;
1711 /* Get a printer handle */
1713 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1714 strupper_m(servername);
1715 asprintf(&printername, "%s\\%s", servername, argv[1]);
1717 werror = rpccli_spoolss_open_printer_ex(
1718 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1719 servername, cli->user_name, &handle);
1721 if (!W_ERROR_IS_OK(werror))
1722 goto done;
1724 got_handle = True;
1726 /* Dummy up some values for the form data */
1728 form.flags = FORM_PRINTER;
1729 form.size_x = form.size_y = 100;
1730 form.left = 0;
1731 form.top = 1000;
1732 form.right = 2000;
1733 form.bottom = 3000;
1735 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1737 /* Set the form */
1739 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1741 done:
1742 if (got_handle)
1743 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1745 SAFE_FREE(servername);
1746 SAFE_FREE(printername);
1748 return werror;
1751 /****************************************************************************
1752 ****************************************************************************/
1754 static const char *get_form_flag(int form_flag)
1756 switch (form_flag) {
1757 case FORM_USER:
1758 return "FORM_USER";
1759 case FORM_BUILTIN:
1760 return "FORM_BUILTIN";
1761 case FORM_PRINTER:
1762 return "FORM_PRINTER";
1763 default:
1764 return "unknown";
1768 /****************************************************************************
1769 ****************************************************************************/
1771 static void display_form(FORM_1 *form)
1773 fstring form_name = "";
1775 if (form->name.buffer)
1776 rpcstr_pull(form_name, form->name.buffer,
1777 sizeof(form_name), -1, STR_TERMINATE);
1779 printf("%s\n" \
1780 "\tflag: %s (%d)\n" \
1781 "\twidth: %d, length: %d\n" \
1782 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1783 form_name, get_form_flag(form->flag), form->flag,
1784 form->width, form->length,
1785 form->left, form->right,
1786 form->top, form->bottom);
1789 /****************************************************************************
1790 ****************************************************************************/
1792 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1793 int argc, const char **argv)
1795 POLICY_HND handle;
1796 WERROR werror;
1797 char *servername = NULL, *printername = NULL;
1798 FORM_1 form;
1799 BOOL got_handle = False;
1801 /* Parse the command arguements */
1803 if (argc != 3) {
1804 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1805 return WERR_OK;
1808 /* Get a printer handle */
1810 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1811 strupper_m(servername);
1812 asprintf(&printername, "%s\\%s", servername, argv[1]);
1814 werror = rpccli_spoolss_open_printer_ex(
1815 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1816 servername, cli->user_name, &handle);
1818 if (!W_ERROR_IS_OK(werror))
1819 goto done;
1821 got_handle = True;
1823 /* Get the form */
1825 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1827 if (!W_ERROR_IS_OK(werror))
1828 goto done;
1830 display_form(&form);
1832 done:
1833 if (got_handle)
1834 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1836 SAFE_FREE(servername);
1837 SAFE_FREE(printername);
1839 return werror;
1842 /****************************************************************************
1843 ****************************************************************************/
1845 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1846 TALLOC_CTX *mem_ctx, int argc,
1847 const char **argv)
1849 POLICY_HND handle;
1850 WERROR werror;
1851 char *servername = NULL, *printername = NULL;
1852 BOOL got_handle = False;
1854 /* Parse the command arguements */
1856 if (argc != 3) {
1857 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1858 return WERR_OK;
1861 /* Get a printer handle */
1863 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1864 strupper_m(servername);
1865 asprintf(&printername, "%s\\%s", servername, argv[1]);
1867 werror = rpccli_spoolss_open_printer_ex(
1868 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1869 servername, cli->user_name, &handle);
1871 if (!W_ERROR_IS_OK(werror))
1872 goto done;
1874 got_handle = True;
1876 /* Delete the form */
1878 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1880 done:
1881 if (got_handle)
1882 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1884 SAFE_FREE(servername);
1885 SAFE_FREE(printername);
1887 return werror;
1890 /****************************************************************************
1891 ****************************************************************************/
1893 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1894 TALLOC_CTX *mem_ctx, int argc,
1895 const char **argv)
1897 POLICY_HND handle;
1898 WERROR werror;
1899 char *servername = NULL, *printername = NULL;
1900 BOOL got_handle = False;
1901 uint32 num_forms, level = 1, i;
1902 FORM_1 *forms;
1904 /* Parse the command arguements */
1906 if (argc != 2) {
1907 printf ("Usage: %s <printer>\n", argv[0]);
1908 return WERR_OK;
1911 /* Get a printer handle */
1913 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1914 strupper_m(servername);
1915 asprintf(&printername, "%s\\%s", servername, argv[1]);
1917 werror = rpccli_spoolss_open_printer_ex(
1918 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1919 servername, cli->user_name, &handle);
1921 if (!W_ERROR_IS_OK(werror))
1922 goto done;
1924 got_handle = True;
1926 /* Enumerate forms */
1928 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1930 if (!W_ERROR_IS_OK(werror))
1931 goto done;
1933 /* Display output */
1935 for (i = 0; i < num_forms; i++) {
1937 display_form(&forms[i]);
1941 done:
1942 if (got_handle)
1943 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1945 SAFE_FREE(servername);
1946 SAFE_FREE(printername);
1948 return werror;
1951 /****************************************************************************
1952 ****************************************************************************/
1954 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1955 TALLOC_CTX *mem_ctx,
1956 int argc, const char **argv)
1958 WERROR result;
1959 fstring servername, printername, user;
1960 POLICY_HND pol;
1961 BOOL opened_hnd = False;
1962 PRINTER_INFO_CTR ctr;
1963 PRINTER_INFO_0 info;
1964 REGISTRY_VALUE value;
1966 /* parse the command arguements */
1967 if (argc < 5) {
1968 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1969 " <value> <data>\n",
1970 argv[0]);
1971 return WERR_INVALID_PARAM;
1974 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1975 strupper_m(servername);
1976 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1977 fstrcpy(user, cli->user_name);
1979 value.type = REG_NONE;
1981 if (strequal(argv[2], "string")) {
1982 value.type = REG_SZ;
1985 if (strequal(argv[2], "binary")) {
1986 value.type = REG_BINARY;
1989 if (strequal(argv[2], "dword")) {
1990 value.type = REG_DWORD;
1993 if (strequal(argv[2], "multistring")) {
1994 value.type = REG_MULTI_SZ;
1997 if (value.type == REG_NONE) {
1998 printf("Unknown data type: %s\n", argv[2]);
1999 return WERR_INVALID_PARAM;
2002 /* get a printer handle */
2003 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2004 MAXIMUM_ALLOWED_ACCESS, servername,
2005 user, &pol);
2006 if (!W_ERROR_IS_OK(result))
2007 goto done;
2009 opened_hnd = True;
2011 ctr.printers_0 = &info;
2013 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2015 if (!W_ERROR_IS_OK(result))
2016 goto done;
2018 printf("%s\n", current_timestring(True));
2019 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2021 /* Set the printer data */
2023 fstrcpy(value.valuename, argv[3]);
2025 switch (value.type) {
2026 case REG_SZ: {
2027 UNISTR2 data;
2028 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2029 value.size = data.uni_str_len * 2;
2030 if (value.size) {
2031 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2032 value.size);
2033 } else {
2034 value.data_p = NULL;
2036 break;
2038 case REG_DWORD: {
2039 uint32 data = strtoul(argv[4], NULL, 10);
2040 value.size = sizeof(data);
2041 if (sizeof(data)) {
2042 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2043 sizeof(data));
2044 } else {
2045 value.data_p = NULL;
2047 break;
2049 case REG_BINARY: {
2050 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2051 value.data_p = data.data;
2052 value.size = data.length;
2053 break;
2055 case REG_MULTI_SZ: {
2056 int i;
2057 size_t len = 0;
2058 char *p;
2060 for (i=4; i<argc; i++) {
2061 if (strcmp(argv[i], "NULL") == 0) {
2062 argv[i] = "";
2064 len += strlen(argv[i])+1;
2067 value.size = len*2;
2068 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2069 if (value.data_p == NULL) {
2070 result = WERR_NOMEM;
2071 goto done;
2074 p = (char *)value.data_p;
2075 len = value.size;
2076 for (i=4; i<argc; i++) {
2077 size_t l = (strlen(argv[i])+1)*2;
2078 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2079 p += l;
2080 len -= l;
2082 SMB_ASSERT(len == 0);
2083 break;
2085 default:
2086 printf("Unknown data type: %s\n", argv[2]);
2087 result = WERR_INVALID_PARAM;
2088 goto done;
2091 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2093 if (!W_ERROR_IS_OK(result)) {
2094 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2095 goto done;
2097 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2099 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2101 if (!W_ERROR_IS_OK(result))
2102 goto done;
2104 printf("%s\n", current_timestring(True));
2105 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2107 done:
2108 /* cleanup */
2109 if (opened_hnd)
2110 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2112 return result;
2115 /****************************************************************************
2116 ****************************************************************************/
2118 static void display_job_info_1(JOB_INFO_1 *job)
2120 fstring username = "", document = "", text_status = "";
2122 rpcstr_pull(username, job->username.buffer,
2123 sizeof(username), -1, STR_TERMINATE);
2125 rpcstr_pull(document, job->document.buffer,
2126 sizeof(document), -1, STR_TERMINATE);
2128 rpcstr_pull(text_status, job->text_status.buffer,
2129 sizeof(text_status), -1, STR_TERMINATE);
2131 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2132 username, document, text_status, job->pagesprinted,
2133 job->totalpages);
2136 /****************************************************************************
2137 ****************************************************************************/
2139 static void display_job_info_2(JOB_INFO_2 *job)
2141 fstring username = "", document = "", text_status = "";
2143 rpcstr_pull(username, job->username.buffer,
2144 sizeof(username), -1, STR_TERMINATE);
2146 rpcstr_pull(document, job->document.buffer,
2147 sizeof(document), -1, STR_TERMINATE);
2149 rpcstr_pull(text_status, job->text_status.buffer,
2150 sizeof(text_status), -1, STR_TERMINATE);
2152 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2153 username, document, text_status, job->pagesprinted,
2154 job->totalpages, job->size);
2157 /****************************************************************************
2158 ****************************************************************************/
2160 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2161 TALLOC_CTX *mem_ctx, int argc,
2162 const char **argv)
2164 WERROR result;
2165 uint32 level = 1, num_jobs, i;
2166 BOOL got_hnd = False;
2167 pstring printername;
2168 fstring servername, user;
2169 POLICY_HND hnd;
2170 JOB_INFO_CTR ctr;
2172 if (argc < 2 || argc > 3) {
2173 printf("Usage: %s printername [level]\n", argv[0]);
2174 return WERR_OK;
2177 if (argc == 3)
2178 level = atoi(argv[2]);
2180 /* Open printer handle */
2182 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2183 strupper_m(servername);
2184 fstrcpy(user, cli->user_name);
2185 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2186 strupper_m(printername);
2187 pstrcat(printername, argv[1]);
2189 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2190 "", MAXIMUM_ALLOWED_ACCESS,
2191 servername, user, &hnd);
2193 if (!W_ERROR_IS_OK(result))
2194 goto done;
2196 got_hnd = True;
2198 /* Enumerate ports */
2200 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2201 &num_jobs, &ctr);
2203 if (!W_ERROR_IS_OK(result))
2204 goto done;
2206 for (i = 0; i < num_jobs; i++) {
2207 switch(level) {
2208 case 1:
2209 display_job_info_1(&ctr.job.job_info_1[i]);
2210 break;
2211 case 2:
2212 display_job_info_2(&ctr.job.job_info_2[i]);
2213 break;
2214 default:
2215 d_printf("unknown info level %d\n", level);
2216 break;
2220 done:
2221 if (got_hnd)
2222 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2224 return result;
2227 /****************************************************************************
2228 ****************************************************************************/
2230 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2231 TALLOC_CTX *mem_ctx, int argc,
2232 const char **argv)
2234 WERROR result;
2235 uint32 i=0, val_needed, data_needed;
2236 BOOL got_hnd = False;
2237 pstring printername;
2238 fstring servername, user;
2239 POLICY_HND hnd;
2241 if (argc != 2) {
2242 printf("Usage: %s printername\n", argv[0]);
2243 return WERR_OK;
2246 /* Open printer handle */
2248 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2249 strupper_m(servername);
2250 fstrcpy(user, cli->user_name);
2251 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2252 strupper_m(printername);
2253 pstrcat(printername, argv[1]);
2255 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2256 "", MAXIMUM_ALLOWED_ACCESS,
2257 servername, user, &hnd);
2259 if (!W_ERROR_IS_OK(result))
2260 goto done;
2262 got_hnd = True;
2264 /* Enumerate data */
2266 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2267 &val_needed, &data_needed,
2268 NULL);
2269 while (W_ERROR_IS_OK(result)) {
2270 REGISTRY_VALUE value;
2271 result = rpccli_spoolss_enumprinterdata(
2272 cli, mem_ctx, &hnd, i++, val_needed,
2273 data_needed, 0, 0, &value);
2274 if (W_ERROR_IS_OK(result))
2275 display_reg_value(value);
2277 if (W_ERROR_V(result) == ERRnomoreitems)
2278 result = W_ERROR(ERRsuccess);
2280 done:
2281 if (got_hnd)
2282 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2284 return result;
2287 /****************************************************************************
2288 ****************************************************************************/
2290 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2291 TALLOC_CTX *mem_ctx, int argc,
2292 const char **argv)
2294 WERROR result;
2295 uint32 i;
2296 BOOL got_hnd = False;
2297 pstring printername;
2298 fstring servername, user;
2299 const char *keyname = NULL;
2300 POLICY_HND hnd;
2301 REGVAL_CTR *ctr = NULL;
2303 if (argc != 3) {
2304 printf("Usage: %s printername <keyname>\n", argv[0]);
2305 return WERR_OK;
2308 keyname = argv[2];
2310 /* Open printer handle */
2312 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2313 strupper_m(servername);
2314 fstrcpy(user, cli->user_name);
2315 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2316 strupper_m(printername);
2317 pstrcat(printername, argv[1]);
2319 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2320 "", MAXIMUM_ALLOWED_ACCESS,
2321 servername, user, &hnd);
2323 if (!W_ERROR_IS_OK(result))
2324 goto done;
2326 got_hnd = True;
2328 /* Enumerate subkeys */
2330 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2331 return WERR_NOMEM;
2333 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2335 if (!W_ERROR_IS_OK(result))
2336 goto done;
2338 for (i=0; i < ctr->num_values; i++) {
2339 display_reg_value(*(ctr->values[i]));
2342 TALLOC_FREE( ctr );
2344 done:
2345 if (got_hnd)
2346 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2348 return result;
2351 /****************************************************************************
2352 ****************************************************************************/
2354 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2355 TALLOC_CTX *mem_ctx, int argc,
2356 const char **argv)
2358 WERROR result;
2359 BOOL got_hnd = False;
2360 pstring printername;
2361 fstring servername, user;
2362 const char *keyname = NULL;
2363 POLICY_HND hnd;
2364 uint16 *keylist = NULL, *curkey;
2366 if (argc < 2 || argc > 3) {
2367 printf("Usage: %s printername [keyname]\n", argv[0]);
2368 return WERR_OK;
2371 if (argc == 3)
2372 keyname = argv[2];
2373 else
2374 keyname = "";
2376 /* Open printer handle */
2378 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2379 strupper_m(servername);
2380 fstrcpy(user, cli->user_name);
2381 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2382 strupper_m(printername);
2383 pstrcat(printername, argv[1]);
2385 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2386 "", MAXIMUM_ALLOWED_ACCESS,
2387 servername, user, &hnd);
2389 if (!W_ERROR_IS_OK(result))
2390 goto done;
2392 got_hnd = True;
2394 /* Enumerate subkeys */
2396 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2398 if (!W_ERROR_IS_OK(result))
2399 goto done;
2401 curkey = keylist;
2402 while (*curkey != 0) {
2403 pstring subkey;
2404 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2405 STR_TERMINATE);
2406 printf("%s\n", subkey);
2407 curkey += strlen(subkey) + 1;
2410 done:
2412 SAFE_FREE(keylist);
2414 if (got_hnd)
2415 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2417 return result;
2420 /****************************************************************************
2421 ****************************************************************************/
2423 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2424 TALLOC_CTX *mem_ctx, int argc,
2425 const char **argv)
2427 fstring servername, printername;
2428 POLICY_HND hnd;
2429 BOOL got_hnd = False;
2430 WERROR result;
2431 SPOOL_NOTIFY_OPTION option;
2433 if (argc != 2) {
2434 printf("Usage: %s printername\n", argv[0]);
2435 result = WERR_OK;
2436 goto done;
2439 /* Open printer */
2441 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2442 strupper_m(servername);
2444 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2445 argv[1]);
2446 strupper_m(printername);
2448 result = rpccli_spoolss_open_printer_ex(
2449 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2450 servername, cli->user_name, &hnd);
2452 if (!W_ERROR_IS_OK(result)) {
2453 printf("Error opening %s\n", argv[1]);
2454 goto done;
2457 got_hnd = True;
2459 /* Create spool options */
2461 ZERO_STRUCT(option);
2463 option.version = 2;
2464 option.option_type_ptr = 1;
2465 option.count = option.ctr.count = 2;
2467 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2468 if (option.ctr.type == NULL) {
2469 result = WERR_NOMEM;
2470 goto done;
2473 ZERO_STRUCT(option.ctr.type[0]);
2474 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2475 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2476 option.ctr.type[0].fields_ptr = 1;
2477 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2479 ZERO_STRUCT(option.ctr.type[1]);
2480 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2481 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2482 option.ctr.type[1].fields_ptr = 1;
2483 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2485 /* Send rffpcnex */
2487 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2488 strupper_m(servername);
2490 result = rpccli_spoolss_rffpcnex(
2491 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2493 if (!W_ERROR_IS_OK(result)) {
2494 printf("Error rffpcnex %s\n", argv[1]);
2495 goto done;
2498 done:
2499 if (got_hnd)
2500 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2502 return result;
2505 /****************************************************************************
2506 ****************************************************************************/
2508 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2509 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2511 PRINTER_INFO_CTR ctr1, ctr2;
2512 WERROR werror;
2513 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2515 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2516 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2517 if ( !W_ERROR_IS_OK(werror) ) {
2518 printf("failed (%s)\n", dos_errstr(werror));
2519 talloc_destroy(mem_ctx);
2520 return False;
2522 printf("ok\n");
2524 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2525 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2526 if ( !W_ERROR_IS_OK(werror) ) {
2527 printf("failed (%s)\n", dos_errstr(werror));
2528 talloc_destroy(mem_ctx);
2529 return False;
2531 printf("ok\n");
2533 talloc_destroy(mem_ctx);
2535 return True;
2538 /****************************************************************************
2539 ****************************************************************************/
2541 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2542 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2544 PRINTER_INFO_CTR ctr1, ctr2;
2545 WERROR werror;
2546 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2547 SEC_DESC *sd1, *sd2;
2548 BOOL result = True;
2551 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2552 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2553 if ( !W_ERROR_IS_OK(werror) ) {
2554 printf("failed (%s)\n", dos_errstr(werror));
2555 result = False;
2556 goto done;
2558 printf("ok\n");
2560 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2561 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2562 if ( !W_ERROR_IS_OK(werror) ) {
2563 printf("failed (%s)\n", dos_errstr(werror));
2564 result = False;
2565 goto done;
2567 printf("ok\n");
2570 printf("++ ");
2572 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2573 printf("NULL PRINTER_INFO_3!\n");
2574 result = False;
2575 goto done;
2578 sd1 = ctr1.printers_3->secdesc;
2579 sd2 = ctr2.printers_3->secdesc;
2581 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2582 printf("NULL secdesc!\n");
2583 result = False;
2584 goto done;
2587 if (!sec_desc_equal( sd1, sd2 ) ) {
2588 printf("Security Descriptors *not* equal!\n");
2589 result = False;
2590 goto done;
2593 printf("Security descriptors match\n");
2595 done:
2596 talloc_destroy(mem_ctx);
2597 return result;
2601 /****************************************************************************
2602 ****************************************************************************/
2604 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2605 TALLOC_CTX *mem_ctx, int argc,
2606 const char **argv)
2608 fstring printername, servername1, servername2;
2609 pstring printername_path;
2610 struct cli_state *cli_server1 = cli->cli;
2611 struct cli_state *cli_server2 = NULL;
2612 struct rpc_pipe_client *cli2 = NULL;
2613 POLICY_HND hPrinter1, hPrinter2;
2614 NTSTATUS nt_status;
2615 WERROR werror;
2617 if ( argc != 3 ) {
2618 printf("Usage: %s <printer> <server>\n", argv[0]);
2619 return WERR_OK;
2622 fstrcpy( printername, argv[1] );
2624 fstr_sprintf( servername1, cli->cli->desthost );
2625 fstrcpy( servername2, argv[2] );
2626 strupper_m( servername1 );
2627 strupper_m( servername2 );
2630 /* first get the connection to the remote server */
2632 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2633 NULL, 0,
2634 "IPC$", "IPC",
2635 cmdline_auth_info.username,
2636 lp_workgroup(),
2637 cmdline_auth_info.password,
2638 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2639 cmdline_auth_info.signing_state, NULL);
2641 if ( !NT_STATUS_IS_OK(nt_status) )
2642 return WERR_GENERAL_FAILURE;
2644 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2645 if (!cli2) {
2646 printf("failed to open spoolss pipe on server %s (%s)\n",
2647 servername2, nt_errstr(nt_status));
2648 return WERR_GENERAL_FAILURE;
2651 /* now open up both printers */
2653 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2654 printf("Opening %s...", printername_path);
2655 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2656 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2657 if ( !W_ERROR_IS_OK(werror) ) {
2658 printf("failed (%s)\n", dos_errstr(werror));
2659 goto done;
2661 printf("ok\n");
2663 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2664 printf("Opening %s...", printername_path);
2665 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2666 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2667 if ( !W_ERROR_IS_OK(werror) ) {
2668 printf("failed (%s)\n", dos_errstr(werror));
2669 goto done;
2671 printf("ok\n");
2674 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2675 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2676 #if 0
2677 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2678 #endif
2681 done:
2682 /* cleanup */
2684 printf("Closing printers...");
2685 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2686 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2687 printf("ok\n");
2689 /* close the second remote connection */
2691 cli_shutdown( cli_server2 );
2693 return WERR_OK;
2696 /* List of commands exported by this module */
2697 struct cmd_set spoolss_commands[] = {
2699 { "SPOOLSS" },
2701 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2702 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2703 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2704 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2705 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2706 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2707 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2708 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2709 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2710 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2711 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2712 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2713 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2714 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2715 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2716 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2717 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2718 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2719 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2720 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2721 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2722 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2723 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2724 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2725 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2726 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2727 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2728 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2729 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },
2731 { NULL }