r14074: Some cleanup; there is no point in declaring and mapping
[Samba/nascimento.git] / source3 / rpcclient / cmd_spoolss.c
blob137335962eabe60eb3473c3cb1b99fdcadc2f853
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 printf("\tflags:[0x%x]\n", i3->flags);
281 display_sec_desc(i3->secdesc);
283 printf("\n");
286 /****************************************************************************
287 ****************************************************************************/
289 static void display_print_info_7(PRINTER_INFO_7 *i7)
291 fstring guid = "";
292 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
293 printf("\tguid:[%s]\n", guid);
294 printf("\taction:[0x%x]\n", i7->action);
298 /****************************************************************************
299 ****************************************************************************/
301 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
302 TALLOC_CTX *mem_ctx,
303 int argc, const char **argv)
305 WERROR result;
306 uint32 info_level = 1;
307 PRINTER_INFO_CTR ctr;
308 uint32 i = 0, num_printers;
309 fstring name;
311 if (argc > 3)
313 printf("Usage: %s [level] [name]\n", argv[0]);
314 return WERR_OK;
317 if (argc >= 2)
318 info_level = atoi(argv[1]);
320 if (argc == 3)
321 fstrcpy(name, argv[2]);
322 else {
323 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
324 strupper_m(name);
327 ZERO_STRUCT(ctr);
329 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
330 info_level, &num_printers, &ctr);
332 if (W_ERROR_IS_OK(result)) {
334 if (!num_printers) {
335 printf ("No printers returned.\n");
336 goto done;
339 for (i = 0; i < num_printers; i++) {
340 switch(info_level) {
341 case 0:
342 display_print_info_0(&ctr.printers_0[i]);
343 break;
344 case 1:
345 display_print_info_1(&ctr.printers_1[i]);
346 break;
347 case 2:
348 display_print_info_2(&ctr.printers_2[i]);
349 break;
350 case 3:
351 display_print_info_3(&ctr.printers_3[i]);
352 break;
353 default:
354 printf("unknown info level %d\n", info_level);
355 goto done;
359 done:
361 return result;
364 /****************************************************************************
365 ****************************************************************************/
367 static void display_port_info_1(PORT_INFO_1 *i1)
369 fstring buffer;
371 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
372 printf("\tPort Name:\t[%s]\n", buffer);
375 /****************************************************************************
376 ****************************************************************************/
378 static void display_port_info_2(PORT_INFO_2 *i2)
380 fstring buffer;
382 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
383 printf("\tPort Name:\t[%s]\n", buffer);
384 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
386 printf("\tMonitor Name:\t[%s]\n", buffer);
387 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
389 printf("\tDescription:\t[%s]\n", buffer);
390 printf("\tPort Type:\t" );
391 if ( i2->port_type ) {
392 int comma = 0; /* hack */
393 printf( "[" );
394 if ( i2->port_type & PORT_TYPE_READ ) {
395 printf( "Read" );
396 comma = 1;
398 if ( i2->port_type & PORT_TYPE_WRITE ) {
399 printf( "%sWrite", comma ? ", " : "" );
400 comma = 1;
402 /* These two have slightly different interpretations
403 on 95/98/ME but I'm disregarding that for now */
404 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
405 printf( "%sRedirected", comma ? ", " : "" );
406 comma = 1;
408 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
409 printf( "%sNet-Attached", comma ? ", " : "" );
411 printf( "]\n" );
412 } else {
413 printf( "[Unset]\n" );
415 printf("\tReserved:\t[%d]\n", i2->reserved);
416 printf("\n");
419 /****************************************************************************
420 ****************************************************************************/
422 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
423 TALLOC_CTX *mem_ctx, int argc,
424 const char **argv)
426 WERROR result;
427 uint32 info_level = 1;
428 PORT_INFO_CTR ctr;
429 uint32 returned;
431 if (argc > 2) {
432 printf("Usage: %s [level]\n", argv[0]);
433 return WERR_OK;
436 if (argc == 2)
437 info_level = atoi(argv[1]);
439 /* Enumerate ports */
441 ZERO_STRUCT(ctr);
443 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
445 if (W_ERROR_IS_OK(result)) {
446 int i;
448 for (i = 0; i < returned; i++) {
449 switch (info_level) {
450 case 1:
451 display_port_info_1(&ctr.port.info_1[i]);
452 break;
453 case 2:
454 display_port_info_2(&ctr.port.info_2[i]);
455 break;
456 default:
457 printf("unknown info level %d\n", info_level);
458 break;
463 return result;
466 /****************************************************************************
467 ****************************************************************************/
469 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
470 TALLOC_CTX *mem_ctx,
471 int argc, const char **argv)
473 POLICY_HND pol;
474 WERROR result;
475 uint32 info_level = 2;
476 BOOL opened_hnd = False;
477 PRINTER_INFO_CTR ctr;
478 fstring printername,
479 servername,
480 user,
481 comment;
483 if (argc == 1 || argc > 3) {
484 printf("Usage: %s printername comment\n", argv[0]);
486 return WERR_OK;
489 /* Open a printer handle */
490 if (argc == 3) {
491 fstrcpy(comment, argv[2]);
494 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
495 strupper_m(servername);
496 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
497 fstrcpy(user, cli->user_name);
499 /* get a printer handle */
500 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
501 PRINTER_ALL_ACCESS, servername,
502 user, &pol);
504 if (!W_ERROR_IS_OK(result))
505 goto done;
507 opened_hnd = True;
509 /* Get printer info */
510 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
512 if (!W_ERROR_IS_OK(result))
513 goto done;
516 /* Modify the comment. */
517 init_unistr(&ctr.printers_2->comment, comment);
518 ctr.printers_2->devmode = NULL;
519 ctr.printers_2->secdesc = NULL;
521 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
522 if (W_ERROR_IS_OK(result))
523 printf("Success in setting comment.\n");
525 done:
526 if (opened_hnd)
527 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
529 return result;
532 /****************************************************************************
533 ****************************************************************************/
535 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
536 TALLOC_CTX *mem_ctx,
537 int argc, const char **argv)
539 POLICY_HND pol;
540 WERROR result;
541 uint32 info_level = 2;
542 BOOL opened_hnd = False;
543 PRINTER_INFO_CTR ctr;
544 fstring printername,
545 servername,
546 user,
547 new_printername;
549 if (argc == 1 || argc > 3) {
550 printf("Usage: %s printername new_printername\n", argv[0]);
552 return WERR_OK;
555 /* Open a printer handle */
556 if (argc == 3) {
557 fstrcpy(new_printername, argv[2]);
560 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
561 strupper_m(servername);
562 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
563 fstrcpy(user, cli->user_name);
565 /* get a printer handle */
566 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
567 PRINTER_ALL_ACCESS, servername,
568 user, &pol);
570 if (!W_ERROR_IS_OK(result))
571 goto done;
573 opened_hnd = True;
575 /* Get printer info */
576 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
578 if (!W_ERROR_IS_OK(result))
579 goto done;
581 /* Modify the printername. */
582 init_unistr(&ctr.printers_2->printername, new_printername);
583 ctr.printers_2->devmode = NULL;
584 ctr.printers_2->secdesc = NULL;
586 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
587 if (W_ERROR_IS_OK(result))
588 printf("Success in setting printername.\n");
590 done:
591 if (opened_hnd)
592 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
594 return result;
597 /****************************************************************************
598 ****************************************************************************/
600 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
601 TALLOC_CTX *mem_ctx,
602 int argc, const char **argv)
604 POLICY_HND pol;
605 WERROR result;
606 uint32 info_level = 1;
607 BOOL opened_hnd = False;
608 PRINTER_INFO_CTR ctr;
609 fstring printername,
610 servername,
611 user;
613 if (argc == 1 || argc > 3) {
614 printf("Usage: %s <printername> [level]\n", argv[0]);
615 return WERR_OK;
618 /* Open a printer handle */
619 if (argc == 3) {
620 info_level = atoi(argv[2]);
623 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
624 strupper_m(servername);
625 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
626 fstrcpy(user, cli->user_name);
628 /* get a printer handle */
630 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
631 "", MAXIMUM_ALLOWED_ACCESS,
632 servername, user, &pol);
634 if (!W_ERROR_IS_OK(result))
635 goto done;
637 opened_hnd = True;
639 /* Get printer info */
641 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
643 if (!W_ERROR_IS_OK(result))
644 goto done;
646 /* Display printer info */
648 switch (info_level) {
649 case 0:
650 display_print_info_0(ctr.printers_0);
651 break;
652 case 1:
653 display_print_info_1(ctr.printers_1);
654 break;
655 case 2:
656 display_print_info_2(ctr.printers_2);
657 break;
658 case 3:
659 display_print_info_3(ctr.printers_3);
660 break;
661 case 7:
662 display_print_info_7(ctr.printers_7);
663 break;
664 default:
665 printf("unknown info level %d\n", info_level);
666 break;
669 done:
670 if (opened_hnd)
671 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
673 return result;
676 /****************************************************************************
677 ****************************************************************************/
679 static void display_reg_value(REGISTRY_VALUE value)
681 pstring text;
683 switch(value.type) {
684 case REG_DWORD:
685 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
686 *((uint32 *) value.data_p));
687 break;
688 case REG_SZ:
689 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
690 STR_TERMINATE);
691 printf("%s: REG_SZ: %s\n", value.valuename, text);
692 break;
693 case REG_BINARY: {
694 char *hex = hex_encode(NULL, value.data_p, value.size);
695 size_t i, len;
696 printf("%s: REG_BINARY:", value.valuename);
697 len = strlen(hex);
698 for (i=0; i<len; i++) {
699 if (hex[i] == '\0') {
700 break;
702 if (i%40 == 0) {
703 putchar('\n');
705 putchar(hex[i]);
707 TALLOC_FREE(hex);
708 putchar('\n');
709 break;
711 case REG_MULTI_SZ: {
712 uint16 *curstr = (uint16 *) value.data_p;
713 uint8 *start = value.data_p;
714 printf("%s: REG_MULTI_SZ:\n", value.valuename);
715 while (((uint8 *) curstr < start + value.size)) {
716 rpcstr_pull(text, curstr, sizeof(text), -1,
717 STR_TERMINATE);
718 printf(" %s\n", *text != 0 ? text : "NULL");
719 curstr += strlen(text) + 1;
722 break;
723 default:
724 printf("%s: unknown type %d\n", value.valuename, value.type);
729 /****************************************************************************
730 ****************************************************************************/
732 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
733 TALLOC_CTX *mem_ctx,
734 int argc, const char **argv)
736 POLICY_HND pol;
737 WERROR result;
738 BOOL opened_hnd = False;
739 fstring printername,
740 servername,
741 user;
742 const char *valuename;
743 REGISTRY_VALUE value;
745 if (argc != 3) {
746 printf("Usage: %s <printername> <valuename>\n", argv[0]);
747 printf("<printername> of . queries print server\n");
748 return WERR_OK;
750 valuename = argv[2];
752 /* Open a printer handle */
754 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
755 strupper_m(servername);
756 if (strncmp(argv[1], ".", sizeof(".")) == 0)
757 fstrcpy(printername, servername);
758 else
759 slprintf(printername, sizeof(servername)-1, "%s\\%s",
760 servername, argv[1]);
761 fstrcpy(user, cli->user_name);
763 /* get a printer handle */
765 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
766 "", MAXIMUM_ALLOWED_ACCESS,
767 servername, user, &pol);
769 if (!W_ERROR_IS_OK(result))
770 goto done;
772 opened_hnd = True;
774 /* Get printer info */
776 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
778 if (!W_ERROR_IS_OK(result))
779 goto done;
781 /* Display printer data */
783 fstrcpy(value.valuename, valuename);
784 display_reg_value(value);
787 done:
788 if (opened_hnd)
789 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
791 return result;
794 /****************************************************************************
795 ****************************************************************************/
797 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
798 TALLOC_CTX *mem_ctx,
799 int argc, const char **argv)
801 POLICY_HND pol;
802 WERROR result;
803 BOOL opened_hnd = False;
804 fstring printername,
805 servername,
806 user;
807 const char *valuename, *keyname;
808 REGISTRY_VALUE value;
810 if (argc != 4) {
811 printf("Usage: %s <printername> <keyname> <valuename>\n",
812 argv[0]);
813 printf("<printername> of . queries print server\n");
814 return WERR_OK;
816 valuename = argv[3];
817 keyname = argv[2];
819 /* Open a printer handle */
821 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
822 strupper_m(servername);
823 if (strncmp(argv[1], ".", sizeof(".")) == 0)
824 fstrcpy(printername, servername);
825 else
826 slprintf(printername, sizeof(printername)-1, "%s\\%s",
827 servername, argv[1]);
828 fstrcpy(user, cli->user_name);
830 /* get a printer handle */
832 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
833 "", MAXIMUM_ALLOWED_ACCESS,
834 servername, user, &pol);
836 if (!W_ERROR_IS_OK(result))
837 goto done;
839 opened_hnd = True;
841 /* Get printer info */
843 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
844 valuename, &value);
846 if (!W_ERROR_IS_OK(result))
847 goto done;
849 /* Display printer data */
851 fstrcpy(value.valuename, valuename);
852 display_reg_value(value);
855 done:
856 if (opened_hnd)
857 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
859 return result;
862 /****************************************************************************
863 ****************************************************************************/
865 static void display_print_driver_1(DRIVER_INFO_1 *i1)
867 fstring name;
868 if (i1 == NULL)
869 return;
871 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
873 printf ("Printer Driver Info 1:\n");
874 printf ("\tDriver Name: [%s]\n\n", name);
876 return;
879 /****************************************************************************
880 ****************************************************************************/
882 static void display_print_driver_2(DRIVER_INFO_2 *i1)
884 fstring name;
885 fstring architecture;
886 fstring driverpath;
887 fstring datafile;
888 fstring configfile;
889 if (i1 == NULL)
890 return;
892 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
893 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
894 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
895 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
896 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
898 printf ("Printer Driver Info 2:\n");
899 printf ("\tVersion: [%x]\n", i1->version);
900 printf ("\tDriver Name: [%s]\n", name);
901 printf ("\tArchitecture: [%s]\n", architecture);
902 printf ("\tDriver Path: [%s]\n", driverpath);
903 printf ("\tDatafile: [%s]\n", datafile);
904 printf ("\tConfigfile: [%s]\n\n", configfile);
906 return;
909 /****************************************************************************
910 ****************************************************************************/
912 static void display_print_driver_3(DRIVER_INFO_3 *i1)
914 fstring name = "";
915 fstring architecture = "";
916 fstring driverpath = "";
917 fstring datafile = "";
918 fstring configfile = "";
919 fstring helpfile = "";
920 fstring dependentfiles = "";
921 fstring monitorname = "";
922 fstring defaultdatatype = "";
924 int length=0;
925 BOOL valid = True;
927 if (i1 == NULL)
928 return;
930 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
931 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
932 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
933 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
934 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
935 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
936 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
937 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
939 printf ("Printer Driver Info 3:\n");
940 printf ("\tVersion: [%x]\n", i1->version);
941 printf ("\tDriver Name: [%s]\n",name);
942 printf ("\tArchitecture: [%s]\n", architecture);
943 printf ("\tDriver Path: [%s]\n", driverpath);
944 printf ("\tDatafile: [%s]\n", datafile);
945 printf ("\tConfigfile: [%s]\n", configfile);
946 printf ("\tHelpfile: [%s]\n\n", helpfile);
948 while (valid)
950 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
952 length+=strlen(dependentfiles)+1;
954 if (strlen(dependentfiles) > 0)
956 printf ("\tDependentfiles: [%s]\n", dependentfiles);
958 else
960 valid = False;
964 printf ("\n");
966 printf ("\tMonitorname: [%s]\n", monitorname);
967 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
969 return;
972 /****************************************************************************
973 ****************************************************************************/
975 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
976 TALLOC_CTX *mem_ctx,
977 int argc, const char **argv)
979 POLICY_HND pol;
980 WERROR werror;
981 uint32 info_level = 3;
982 BOOL opened_hnd = False;
983 PRINTER_DRIVER_CTR ctr;
984 fstring printername,
985 servername,
986 user;
987 uint32 i;
988 BOOL success = False;
990 if ((argc == 1) || (argc > 3))
992 printf("Usage: %s <printername> [level]\n", argv[0]);
993 return WERR_OK;
996 /* get the arguments need to open the printer handle */
997 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
998 strupper_m(servername);
999 fstrcpy(user, cli->user_name);
1000 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1001 if (argc == 3)
1002 info_level = atoi(argv[2]);
1004 /* Open a printer handle */
1006 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1007 PRINTER_ACCESS_USE,
1008 servername, user, &pol);
1010 if (!W_ERROR_IS_OK(werror)) {
1011 printf("Error opening printer handle for %s!\n", printername);
1012 return werror;
1015 opened_hnd = True;
1017 /* loop through and print driver info level for each architecture */
1019 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1021 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1022 archi_table[i].long_archi, archi_table[i].version,
1023 &ctr);
1025 if (!W_ERROR_IS_OK(werror))
1026 continue;
1028 /* need at least one success */
1030 success = True;
1032 printf ("\n[%s]\n", archi_table[i].long_archi);
1034 switch (info_level) {
1035 case 1:
1036 display_print_driver_1 (ctr.info1);
1037 break;
1038 case 2:
1039 display_print_driver_2 (ctr.info2);
1040 break;
1041 case 3:
1042 display_print_driver_3 (ctr.info3);
1043 break;
1044 default:
1045 printf("unknown info level %d\n", info_level);
1046 break;
1050 /* Cleanup */
1052 if (opened_hnd)
1053 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1055 if ( success )
1056 werror = WERR_OK;
1058 return werror;
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1065 TALLOC_CTX *mem_ctx,
1066 int argc, const char **argv)
1068 WERROR werror = WERR_OK;
1069 uint32 info_level = 1;
1070 PRINTER_DRIVER_CTR ctr;
1071 uint32 i, j,
1072 returned;
1074 if (argc > 2) {
1075 printf("Usage: enumdrivers [level]\n");
1076 return WERR_OK;
1079 if (argc == 2)
1080 info_level = atoi(argv[1]);
1083 /* loop through and print driver info level for each architecture */
1084 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1085 /* check to see if we already asked for this architecture string */
1087 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1088 continue;
1090 werror = rpccli_spoolss_enumprinterdrivers(
1091 cli, mem_ctx, info_level,
1092 archi_table[i].long_archi, &returned, &ctr);
1094 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1095 printf ("Server does not support environment [%s]\n",
1096 archi_table[i].long_archi);
1097 werror = WERR_OK;
1098 continue;
1101 if (returned == 0)
1102 continue;
1104 if (!W_ERROR_IS_OK(werror)) {
1105 printf ("Error getting driver for environment [%s] - %d\n",
1106 archi_table[i].long_archi, W_ERROR_V(werror));
1107 continue;
1110 printf ("\n[%s]\n", archi_table[i].long_archi);
1111 switch (info_level)
1114 case 1:
1115 for (j=0; j < returned; j++) {
1116 display_print_driver_1 (&ctr.info1[j]);
1118 break;
1119 case 2:
1120 for (j=0; j < returned; j++) {
1121 display_print_driver_2 (&ctr.info2[j]);
1123 break;
1124 case 3:
1125 for (j=0; j < returned; j++) {
1126 display_print_driver_3 (&ctr.info3[j]);
1128 break;
1129 default:
1130 printf("unknown info level %d\n", info_level);
1131 return WERR_UNKNOWN_LEVEL;
1135 return werror;
1138 /****************************************************************************
1139 ****************************************************************************/
1141 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1143 fstring name;
1144 if (i1 == NULL)
1145 return;
1147 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1149 printf ("\tDirectory Name:[%s]\n", name);
1152 /****************************************************************************
1153 ****************************************************************************/
1155 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1156 TALLOC_CTX *mem_ctx,
1157 int argc, const char **argv)
1159 WERROR result;
1160 fstring env;
1161 DRIVER_DIRECTORY_CTR ctr;
1163 if (argc > 2) {
1164 printf("Usage: %s [environment]\n", argv[0]);
1165 return WERR_OK;
1168 /* Get the arguments need to open the printer handle */
1170 if (argc == 2)
1171 fstrcpy (env, argv[1]);
1172 else
1173 fstrcpy (env, "Windows NT x86");
1175 /* Get the directory. Only use Info level 1 */
1177 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1179 if (W_ERROR_IS_OK(result))
1180 display_printdriverdir_1(ctr.info1);
1182 return result;
1185 /****************************************************************************
1186 ****************************************************************************/
1188 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1191 int i;
1193 for (i=0; archi_table[i].long_archi != NULL; i++)
1195 if (strcmp(arch, archi_table[i].short_archi) == 0)
1197 info->version = archi_table[i].version;
1198 init_unistr (&info->architecture, archi_table[i].long_archi);
1199 break;
1203 if (archi_table[i].long_archi == NULL)
1205 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1208 return;
1212 /**************************************************************************
1213 wrapper for strtok to get the next parameter from a delimited list.
1214 Needed to handle the empty parameter string denoted by "NULL"
1215 *************************************************************************/
1217 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1219 char *ptr;
1221 /* get the next token */
1222 ptr = strtok(str, delim);
1224 /* a string of 'NULL' is used to represent an empty
1225 parameter because two consecutive delimiters
1226 will not return an empty string. See man strtok(3)
1227 for details */
1228 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1229 ptr = NULL;
1231 if (dest != NULL)
1232 init_unistr(dest, ptr);
1234 return ptr;
1237 /********************************************************************************
1238 fill in the members of a DRIVER_INFO_3 struct using a character
1239 string in the form of
1240 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1241 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1242 <Default Data Type>:<Comma Separated list of Files>
1243 *******************************************************************************/
1244 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1245 char *args )
1247 char *str, *str2;
1248 uint32 len, i;
1250 /* fill in the UNISTR fields */
1251 str = get_driver_3_param (args, ":", &info->name);
1252 str = get_driver_3_param (NULL, ":", &info->driverpath);
1253 str = get_driver_3_param (NULL, ":", &info->datafile);
1254 str = get_driver_3_param (NULL, ":", &info->configfile);
1255 str = get_driver_3_param (NULL, ":", &info->helpfile);
1256 str = get_driver_3_param (NULL, ":", &info->monitorname);
1257 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1259 /* <Comma Separated List of Dependent Files> */
1260 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1261 str = str2;
1263 /* begin to strip out each filename */
1264 str = strtok(str, ",");
1265 len = 0;
1266 while (str != NULL)
1268 /* keep a cumlative count of the str lengths */
1269 len += strlen(str)+1;
1270 str = strtok(NULL, ",");
1273 /* allocate the space; add one extra slot for a terminating NULL.
1274 Each filename is NULL terminated and the end contains a double
1275 NULL */
1276 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1278 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1279 return False;
1281 for (i=0; i<len; i++)
1283 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1285 info->dependentfiles[len] = '\0';
1287 return True;
1291 /****************************************************************************
1292 ****************************************************************************/
1294 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1295 TALLOC_CTX *mem_ctx,
1296 int argc, const char **argv)
1298 WERROR result;
1299 uint32 level = 3;
1300 PRINTER_DRIVER_CTR ctr;
1301 DRIVER_INFO_3 info3;
1302 const char *arch;
1303 fstring driver_name;
1304 char *driver_args;
1306 /* parse the command arguements */
1307 if (argc != 3 && argc != 4)
1309 printf ("Usage: %s <Environment> \\\n", argv[0]);
1310 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1311 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1312 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1313 printf ("\t[version]\n");
1315 return WERR_OK;
1318 /* Fill in the DRIVER_INFO_3 struct */
1319 ZERO_STRUCT(info3);
1320 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1322 printf ("Error Unknown architechture [%s]\n", argv[1]);
1323 return WERR_INVALID_PARAM;
1325 else
1326 set_drv_info_3_env(&info3, arch);
1328 driver_args = talloc_strdup( mem_ctx, argv[2] );
1329 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1331 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1332 return WERR_INVALID_PARAM;
1335 /* if printer driver version specified, override the default version
1336 * used by the architecture. This allows installation of Windows
1337 * 2000 (version 3) printer drivers. */
1338 if (argc == 4)
1340 info3.version = atoi(argv[3]);
1344 ctr.info3 = &info3;
1345 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1347 if (W_ERROR_IS_OK(result)) {
1348 rpcstr_pull(driver_name, info3.name.buffer,
1349 sizeof(driver_name), -1, STR_TERMINATE);
1350 printf ("Printer Driver %s successfully installed.\n",
1351 driver_name);
1354 return result;
1358 /****************************************************************************
1359 ****************************************************************************/
1361 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1362 TALLOC_CTX *mem_ctx,
1363 int argc, const char **argv)
1365 WERROR result;
1366 uint32 level = 2;
1367 PRINTER_INFO_CTR ctr;
1368 PRINTER_INFO_2 info2;
1369 fstring servername;
1371 /* parse the command arguements */
1372 if (argc != 5)
1374 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1375 return WERR_OK;
1378 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1379 strupper_m(servername);
1381 /* Fill in the DRIVER_INFO_2 struct */
1382 ZERO_STRUCT(info2);
1384 init_unistr( &info2.printername, argv[1]);
1385 init_unistr( &info2.sharename, argv[2]);
1386 init_unistr( &info2.drivername, argv[3]);
1387 init_unistr( &info2.portname, argv[4]);
1388 init_unistr( &info2.comment, "Created by rpcclient");
1389 init_unistr( &info2.printprocessor, "winprint");
1390 init_unistr( &info2.datatype, "RAW");
1391 info2.devmode = NULL;
1392 info2.secdesc = NULL;
1393 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1394 info2.priority = 0;
1395 info2.defaultpriority = 0;
1396 info2.starttime = 0;
1397 info2.untiltime = 0;
1399 /* These three fields must not be used by AddPrinter()
1400 as defined in the MS Platform SDK documentation..
1401 --jerry
1402 info2.status = 0;
1403 info2.cjobs = 0;
1404 info2.averageppm = 0;
1407 ctr.printers_2 = &info2;
1408 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1410 if (W_ERROR_IS_OK(result))
1411 printf ("Printer %s successfully installed.\n", argv[1]);
1413 return result;
1416 /****************************************************************************
1417 ****************************************************************************/
1419 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1420 TALLOC_CTX *mem_ctx,
1421 int argc, const char **argv)
1423 POLICY_HND pol;
1424 WERROR result;
1425 uint32 level = 2;
1426 BOOL opened_hnd = False;
1427 PRINTER_INFO_CTR ctr;
1428 PRINTER_INFO_2 info2;
1429 fstring servername,
1430 printername,
1431 user;
1433 /* parse the command arguements */
1434 if (argc != 3)
1436 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1437 return WERR_OK;
1440 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1441 strupper_m(servername);
1442 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1443 fstrcpy(user, cli->user_name);
1445 /* Get a printer handle */
1447 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1448 PRINTER_ALL_ACCESS,
1449 servername, user, &pol);
1451 if (!W_ERROR_IS_OK(result))
1452 goto done;
1454 opened_hnd = True;
1456 /* Get printer info */
1458 ZERO_STRUCT (info2);
1459 ctr.printers_2 = &info2;
1461 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1463 if (!W_ERROR_IS_OK(result)) {
1464 printf ("Unable to retrieve printer information!\n");
1465 goto done;
1468 /* Set the printer driver */
1470 init_unistr(&ctr.printers_2->drivername, argv[2]);
1472 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1474 if (!W_ERROR_IS_OK(result)) {
1475 printf("SetPrinter call failed!\n");
1476 goto done;;
1479 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1481 done:
1482 /* Cleanup */
1484 if (opened_hnd)
1485 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1487 return result;
1491 /****************************************************************************
1492 ****************************************************************************/
1494 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1495 TALLOC_CTX *mem_ctx,
1496 int argc, const char **argv)
1498 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1500 int i;
1501 int vers = -1;
1503 const char *arch = NULL;
1505 /* parse the command arguements */
1506 if (argc < 2 || argc > 4) {
1507 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1508 return WERR_OK;
1511 if (argc >= 3)
1512 arch = argv[2];
1513 if (argc == 4)
1514 vers = atoi (argv[3]);
1517 /* delete the driver for all architectures */
1518 for (i=0; archi_table[i].long_archi; i++) {
1520 if (arch && !strequal( archi_table[i].long_archi, arch))
1521 continue;
1523 if (vers >= 0 && archi_table[i].version != vers)
1524 continue;
1526 /* make the call to remove the driver */
1527 result = rpccli_spoolss_deleteprinterdriverex(
1528 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1530 if ( !W_ERROR_IS_OK(result) )
1532 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1533 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1534 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1537 else
1539 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1540 archi_table[i].long_archi, archi_table[i].version);
1541 ret = WERR_OK;
1545 return ret;
1549 /****************************************************************************
1550 ****************************************************************************/
1552 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1553 TALLOC_CTX *mem_ctx,
1554 int argc, const char **argv)
1556 WERROR result = WERR_OK;
1557 fstring servername;
1558 int i;
1560 /* parse the command arguements */
1561 if (argc != 2) {
1562 printf ("Usage: %s <driver>\n", argv[0]);
1563 return WERR_OK;
1566 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1567 strupper_m(servername);
1569 /* delete the driver for all architectures */
1570 for (i=0; archi_table[i].long_archi; i++) {
1571 /* make the call to remove the driver */
1572 result = rpccli_spoolss_deleteprinterdriver(
1573 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1575 if ( !W_ERROR_IS_OK(result) ) {
1576 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1577 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1578 argv[1], archi_table[i].long_archi,
1579 W_ERROR_V(result));
1581 } else {
1582 printf ("Driver %s removed for arch [%s].\n", argv[1],
1583 archi_table[i].long_archi);
1587 return result;
1590 /****************************************************************************
1591 ****************************************************************************/
1593 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1594 TALLOC_CTX *mem_ctx,
1595 int argc, const char **argv)
1597 WERROR result;
1598 char *servername = NULL, *environment = NULL;
1599 fstring procdir;
1601 /* parse the command arguements */
1602 if (argc > 2) {
1603 printf ("Usage: %s [environment]\n", argv[0]);
1604 return WERR_OK;
1607 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1608 return WERR_NOMEM;
1609 strupper_m(servername);
1611 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1612 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1613 SAFE_FREE(servername);
1614 return WERR_NOMEM;
1617 result = rpccli_spoolss_getprintprocessordirectory(
1618 cli, mem_ctx, servername, environment, procdir);
1620 if (W_ERROR_IS_OK(result))
1621 printf("%s\n", procdir);
1623 SAFE_FREE(servername);
1624 SAFE_FREE(environment);
1626 return result;
1629 /****************************************************************************
1630 ****************************************************************************/
1632 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1633 int argc, const char **argv)
1635 POLICY_HND handle;
1636 WERROR werror;
1637 char *servername = NULL, *printername = NULL;
1638 FORM form;
1639 BOOL got_handle = False;
1641 /* Parse the command arguements */
1643 if (argc != 3) {
1644 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1645 return WERR_OK;
1648 /* Get a printer handle */
1650 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1651 strupper_m(servername);
1652 asprintf(&printername, "%s\\%s", servername, argv[1]);
1654 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1655 PRINTER_ALL_ACCESS,
1656 servername, cli->user_name, &handle);
1658 if (!W_ERROR_IS_OK(werror))
1659 goto done;
1661 got_handle = True;
1663 /* Dummy up some values for the form data */
1665 form.flags = FORM_USER;
1666 form.size_x = form.size_y = 100;
1667 form.left = 0;
1668 form.top = 10;
1669 form.right = 20;
1670 form.bottom = 30;
1672 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1674 /* Add the form */
1677 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1679 done:
1680 if (got_handle)
1681 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1683 SAFE_FREE(servername);
1684 SAFE_FREE(printername);
1686 return werror;
1689 /****************************************************************************
1690 ****************************************************************************/
1692 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1693 int argc, const char **argv)
1695 POLICY_HND handle;
1696 WERROR werror;
1697 char *servername = NULL, *printername = NULL;
1698 FORM form;
1699 BOOL got_handle = False;
1701 /* Parse the command arguements */
1703 if (argc != 3) {
1704 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1705 return WERR_OK;
1708 /* Get a printer handle */
1710 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1711 strupper_m(servername);
1712 asprintf(&printername, "%s\\%s", servername, argv[1]);
1714 werror = rpccli_spoolss_open_printer_ex(
1715 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1716 servername, cli->user_name, &handle);
1718 if (!W_ERROR_IS_OK(werror))
1719 goto done;
1721 got_handle = True;
1723 /* Dummy up some values for the form data */
1725 form.flags = FORM_PRINTER;
1726 form.size_x = form.size_y = 100;
1727 form.left = 0;
1728 form.top = 1000;
1729 form.right = 2000;
1730 form.bottom = 3000;
1732 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1734 /* Set the form */
1736 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1738 done:
1739 if (got_handle)
1740 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1742 SAFE_FREE(servername);
1743 SAFE_FREE(printername);
1745 return werror;
1748 /****************************************************************************
1749 ****************************************************************************/
1751 static const char *get_form_flag(int form_flag)
1753 switch (form_flag) {
1754 case FORM_USER:
1755 return "FORM_USER";
1756 case FORM_BUILTIN:
1757 return "FORM_BUILTIN";
1758 case FORM_PRINTER:
1759 return "FORM_PRINTER";
1760 default:
1761 return "unknown";
1765 /****************************************************************************
1766 ****************************************************************************/
1768 static void display_form(FORM_1 *form)
1770 fstring form_name = "";
1772 if (form->name.buffer)
1773 rpcstr_pull(form_name, form->name.buffer,
1774 sizeof(form_name), -1, STR_TERMINATE);
1776 printf("%s\n" \
1777 "\tflag: %s (%d)\n" \
1778 "\twidth: %d, length: %d\n" \
1779 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1780 form_name, get_form_flag(form->flag), form->flag,
1781 form->width, form->length,
1782 form->left, form->right,
1783 form->top, form->bottom);
1786 /****************************************************************************
1787 ****************************************************************************/
1789 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1790 int argc, const char **argv)
1792 POLICY_HND handle;
1793 WERROR werror;
1794 char *servername = NULL, *printername = NULL;
1795 FORM_1 form;
1796 BOOL got_handle = False;
1798 /* Parse the command arguements */
1800 if (argc != 3) {
1801 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1802 return WERR_OK;
1805 /* Get a printer handle */
1807 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1808 strupper_m(servername);
1809 asprintf(&printername, "%s\\%s", servername, argv[1]);
1811 werror = rpccli_spoolss_open_printer_ex(
1812 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1813 servername, cli->user_name, &handle);
1815 if (!W_ERROR_IS_OK(werror))
1816 goto done;
1818 got_handle = True;
1820 /* Get the form */
1822 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1824 if (!W_ERROR_IS_OK(werror))
1825 goto done;
1827 display_form(&form);
1829 done:
1830 if (got_handle)
1831 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1833 SAFE_FREE(servername);
1834 SAFE_FREE(printername);
1836 return werror;
1839 /****************************************************************************
1840 ****************************************************************************/
1842 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1843 TALLOC_CTX *mem_ctx, int argc,
1844 const char **argv)
1846 POLICY_HND handle;
1847 WERROR werror;
1848 char *servername = NULL, *printername = NULL;
1849 BOOL got_handle = False;
1851 /* Parse the command arguements */
1853 if (argc != 3) {
1854 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1855 return WERR_OK;
1858 /* Get a printer handle */
1860 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1861 strupper_m(servername);
1862 asprintf(&printername, "%s\\%s", servername, argv[1]);
1864 werror = rpccli_spoolss_open_printer_ex(
1865 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1866 servername, cli->user_name, &handle);
1868 if (!W_ERROR_IS_OK(werror))
1869 goto done;
1871 got_handle = True;
1873 /* Delete the form */
1875 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1877 done:
1878 if (got_handle)
1879 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1881 SAFE_FREE(servername);
1882 SAFE_FREE(printername);
1884 return werror;
1887 /****************************************************************************
1888 ****************************************************************************/
1890 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1891 TALLOC_CTX *mem_ctx, int argc,
1892 const char **argv)
1894 POLICY_HND handle;
1895 WERROR werror;
1896 char *servername = NULL, *printername = NULL;
1897 BOOL got_handle = False;
1898 uint32 needed, offered, num_forms, level = 1, i;
1899 FORM_1 *forms;
1901 /* Parse the command arguements */
1903 if (argc != 2) {
1904 printf ("Usage: %s <printer>\n", argv[0]);
1905 return WERR_OK;
1908 /* Get a printer handle */
1910 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1911 strupper_m(servername);
1912 asprintf(&printername, "%s\\%s", servername, argv[1]);
1914 werror = rpccli_spoolss_open_printer_ex(
1915 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1916 servername, cli->user_name, &handle);
1918 if (!W_ERROR_IS_OK(werror))
1919 goto done;
1921 got_handle = True;
1923 /* Enumerate forms */
1925 offered = needed = 0;
1926 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1928 if (!W_ERROR_IS_OK(werror))
1929 goto done;
1931 /* Display output */
1933 for (i = 0; i < num_forms; i++) {
1935 display_form(&forms[i]);
1939 done:
1940 if (got_handle)
1941 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1943 SAFE_FREE(servername);
1944 SAFE_FREE(printername);
1946 return werror;
1949 /****************************************************************************
1950 ****************************************************************************/
1952 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1953 TALLOC_CTX *mem_ctx,
1954 int argc, const char **argv)
1956 WERROR result;
1957 fstring servername, printername, user;
1958 POLICY_HND pol;
1959 BOOL opened_hnd = False;
1960 PRINTER_INFO_CTR ctr;
1961 PRINTER_INFO_0 info;
1962 REGISTRY_VALUE value;
1964 /* parse the command arguements */
1965 if (argc < 5) {
1966 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1967 " <value> <data>\n",
1968 argv[0]);
1969 return WERR_INVALID_PARAM;
1972 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1973 strupper_m(servername);
1974 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1975 fstrcpy(user, cli->user_name);
1977 value.type = REG_NONE;
1979 if (strequal(argv[2], "string")) {
1980 value.type = REG_SZ;
1983 if (strequal(argv[2], "binary")) {
1984 value.type = REG_BINARY;
1987 if (strequal(argv[2], "dword")) {
1988 value.type = REG_DWORD;
1991 if (strequal(argv[2], "multistring")) {
1992 value.type = REG_MULTI_SZ;
1995 if (value.type == REG_NONE) {
1996 printf("Unknown data type: %s\n", argv[2]);
1997 return WERR_INVALID_PARAM;
2000 /* get a printer handle */
2001 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2002 MAXIMUM_ALLOWED_ACCESS, servername,
2003 user, &pol);
2004 if (!W_ERROR_IS_OK(result))
2005 goto done;
2007 opened_hnd = True;
2009 ctr.printers_0 = &info;
2011 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2013 if (!W_ERROR_IS_OK(result))
2014 goto done;
2016 printf("%s\n", timestring(True));
2017 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2019 /* Set the printer data */
2021 fstrcpy(value.valuename, argv[3]);
2023 switch (value.type) {
2024 case REG_SZ: {
2025 UNISTR2 data;
2026 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2027 value.size = data.uni_str_len * 2;
2028 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2029 break;
2031 case REG_DWORD: {
2032 uint32 data = strtoul(argv[4], NULL, 10);
2033 value.size = sizeof(data);
2034 value.data_p = TALLOC_MEMDUP(mem_ctx, &data, sizeof(data));
2035 break;
2037 case REG_BINARY: {
2038 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2039 value.data_p = data.data;
2040 value.size = data.length;
2041 break;
2043 case REG_MULTI_SZ: {
2044 int i;
2045 size_t len = 0;
2046 char *p;
2048 for (i=4; i<argc; i++) {
2049 if (strcmp(argv[i], "NULL") == 0) {
2050 argv[i] = "";
2052 len += strlen(argv[i])+1;
2055 value.size = len*2;
2056 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2057 if (value.data_p == NULL) {
2058 result = WERR_NOMEM;
2059 goto done;
2062 p = (char *)value.data_p;
2063 len = value.size;
2064 for (i=4; i<argc; i++) {
2065 size_t l = (strlen(argv[i])+1)*2;
2066 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2067 p += l;
2068 len -= l;
2070 SMB_ASSERT(len == 0);
2071 break;
2073 default:
2074 printf("Unknown data type: %s\n", argv[2]);
2075 result = WERR_INVALID_PARAM;
2076 goto done;
2079 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2081 if (!W_ERROR_IS_OK(result)) {
2082 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2083 goto done;
2085 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2087 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2089 if (!W_ERROR_IS_OK(result))
2090 goto done;
2092 printf("%s\n", timestring(True));
2093 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2095 done:
2096 /* cleanup */
2097 if (opened_hnd)
2098 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2100 return result;
2103 /****************************************************************************
2104 ****************************************************************************/
2106 static void display_job_info_1(JOB_INFO_1 *job)
2108 fstring username = "", document = "", text_status = "";
2110 rpcstr_pull(username, job->username.buffer,
2111 sizeof(username), -1, STR_TERMINATE);
2113 rpcstr_pull(document, job->document.buffer,
2114 sizeof(document), -1, STR_TERMINATE);
2116 rpcstr_pull(text_status, job->text_status.buffer,
2117 sizeof(text_status), -1, STR_TERMINATE);
2119 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2120 username, document, text_status, job->pagesprinted,
2121 job->totalpages);
2124 /****************************************************************************
2125 ****************************************************************************/
2127 static void display_job_info_2(JOB_INFO_2 *job)
2129 fstring username = "", document = "", text_status = "";
2131 rpcstr_pull(username, job->username.buffer,
2132 sizeof(username), -1, STR_TERMINATE);
2134 rpcstr_pull(document, job->document.buffer,
2135 sizeof(document), -1, STR_TERMINATE);
2137 rpcstr_pull(text_status, job->text_status.buffer,
2138 sizeof(text_status), -1, STR_TERMINATE);
2140 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2141 username, document, text_status, job->pagesprinted,
2142 job->totalpages, job->size);
2145 /****************************************************************************
2146 ****************************************************************************/
2148 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2149 TALLOC_CTX *mem_ctx, int argc,
2150 const char **argv)
2152 WERROR result;
2153 uint32 needed, offered, level = 1, num_jobs, i;
2154 BOOL got_hnd = False;
2155 pstring printername;
2156 fstring servername, user;
2157 POLICY_HND hnd;
2158 JOB_INFO_CTR ctr;
2160 if (argc < 2 || argc > 3) {
2161 printf("Usage: %s printername [level]\n", argv[0]);
2162 return WERR_OK;
2165 if (argc == 3)
2166 level = atoi(argv[2]);
2168 /* Open printer handle */
2170 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2171 strupper_m(servername);
2172 fstrcpy(user, cli->user_name);
2173 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2174 strupper_m(printername);
2175 pstrcat(printername, argv[1]);
2177 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2178 "", MAXIMUM_ALLOWED_ACCESS,
2179 servername, user, &hnd);
2181 if (!W_ERROR_IS_OK(result))
2182 goto done;
2184 got_hnd = True;
2186 /* Enumerate ports */
2188 offered = needed = 0;
2189 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2190 &num_jobs, &ctr);
2192 if (!W_ERROR_IS_OK(result))
2193 goto done;
2195 for (i = 0; i < num_jobs; i++) {
2196 switch(level) {
2197 case 1:
2198 display_job_info_1(&ctr.job.job_info_1[i]);
2199 break;
2200 case 2:
2201 display_job_info_2(&ctr.job.job_info_2[i]);
2202 break;
2203 default:
2204 d_printf("unknown info level %d\n", level);
2205 break;
2209 done:
2210 if (got_hnd)
2211 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2213 return result;
2216 /****************************************************************************
2217 ****************************************************************************/
2219 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2220 TALLOC_CTX *mem_ctx, int argc,
2221 const char **argv)
2223 WERROR result;
2224 uint32 i=0, val_needed, data_needed;
2225 BOOL got_hnd = False;
2226 pstring printername;
2227 fstring servername, user;
2228 POLICY_HND hnd;
2230 if (argc != 2) {
2231 printf("Usage: %s printername\n", argv[0]);
2232 return WERR_OK;
2235 /* Open printer handle */
2237 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2238 strupper_m(servername);
2239 fstrcpy(user, cli->user_name);
2240 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2241 strupper_m(printername);
2242 pstrcat(printername, argv[1]);
2244 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2245 "", MAXIMUM_ALLOWED_ACCESS,
2246 servername, user, &hnd);
2248 if (!W_ERROR_IS_OK(result))
2249 goto done;
2251 got_hnd = True;
2253 /* Enumerate data */
2255 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2256 &val_needed, &data_needed,
2257 NULL);
2258 while (W_ERROR_IS_OK(result)) {
2259 REGISTRY_VALUE value;
2260 result = rpccli_spoolss_enumprinterdata(
2261 cli, mem_ctx, &hnd, i++, val_needed,
2262 data_needed, 0, 0, &value);
2263 if (W_ERROR_IS_OK(result))
2264 display_reg_value(value);
2266 if (W_ERROR_V(result) == ERRnomoreitems)
2267 result = W_ERROR(ERRsuccess);
2269 done:
2270 if (got_hnd)
2271 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2273 return result;
2276 /****************************************************************************
2277 ****************************************************************************/
2279 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2280 TALLOC_CTX *mem_ctx, int argc,
2281 const char **argv)
2283 WERROR result;
2284 uint32 i;
2285 BOOL got_hnd = False;
2286 pstring printername;
2287 fstring servername, user;
2288 const char *keyname = NULL;
2289 POLICY_HND hnd;
2290 REGVAL_CTR *ctr = NULL;
2292 if (argc != 3) {
2293 printf("Usage: %s printername <keyname>\n", argv[0]);
2294 return WERR_OK;
2297 keyname = argv[2];
2299 /* Open printer handle */
2301 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2302 strupper_m(servername);
2303 fstrcpy(user, cli->user_name);
2304 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2305 strupper_m(printername);
2306 pstrcat(printername, argv[1]);
2308 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2309 "", MAXIMUM_ALLOWED_ACCESS,
2310 servername, user, &hnd);
2312 if (!W_ERROR_IS_OK(result))
2313 goto done;
2315 got_hnd = True;
2317 /* Enumerate subkeys */
2319 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2320 return WERR_NOMEM;
2322 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2324 if (!W_ERROR_IS_OK(result))
2325 goto done;
2327 for (i=0; i < ctr->num_values; i++) {
2328 display_reg_value(*(ctr->values[i]));
2331 TALLOC_FREE( ctr );
2333 done:
2334 if (got_hnd)
2335 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2337 return result;
2340 /****************************************************************************
2341 ****************************************************************************/
2343 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2344 TALLOC_CTX *mem_ctx, int argc,
2345 const char **argv)
2347 WERROR result;
2348 BOOL got_hnd = False;
2349 pstring printername;
2350 fstring servername, user;
2351 const char *keyname = NULL;
2352 POLICY_HND hnd;
2353 uint16 *keylist = NULL, *curkey;
2355 if (argc < 2 || argc > 3) {
2356 printf("Usage: %s printername [keyname]\n", argv[0]);
2357 return WERR_OK;
2360 if (argc == 3)
2361 keyname = argv[2];
2362 else
2363 keyname = "";
2365 /* Open printer handle */
2367 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2368 strupper_m(servername);
2369 fstrcpy(user, cli->user_name);
2370 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2371 strupper_m(printername);
2372 pstrcat(printername, argv[1]);
2374 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2375 "", MAXIMUM_ALLOWED_ACCESS,
2376 servername, user, &hnd);
2378 if (!W_ERROR_IS_OK(result))
2379 goto done;
2381 got_hnd = True;
2383 /* Enumerate subkeys */
2385 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2387 if (!W_ERROR_IS_OK(result))
2388 goto done;
2390 curkey = keylist;
2391 while (*curkey != 0) {
2392 pstring subkey;
2393 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2394 STR_TERMINATE);
2395 printf("%s\n", subkey);
2396 curkey += strlen(subkey) + 1;
2399 safe_free(keylist);
2401 done:
2402 if (got_hnd)
2403 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2405 return result;
2408 /****************************************************************************
2409 ****************************************************************************/
2411 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2412 TALLOC_CTX *mem_ctx, int argc,
2413 const char **argv)
2415 fstring servername, printername;
2416 POLICY_HND hnd;
2417 BOOL got_hnd = False;
2418 WERROR result;
2419 SPOOL_NOTIFY_OPTION option;
2421 if (argc != 2) {
2422 printf("Usage: %s printername\n", argv[0]);
2423 result = WERR_OK;
2424 goto done;
2427 /* Open printer */
2429 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2430 strupper_m(servername);
2432 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2433 argv[1]);
2434 strupper_m(printername);
2436 result = rpccli_spoolss_open_printer_ex(
2437 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2438 servername, cli->user_name, &hnd);
2440 if (!W_ERROR_IS_OK(result)) {
2441 printf("Error opening %s\n", argv[1]);
2442 goto done;
2445 got_hnd = True;
2447 /* Create spool options */
2449 ZERO_STRUCT(option);
2451 option.version = 2;
2452 option.option_type_ptr = 1;
2453 option.count = option.ctr.count = 2;
2455 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2457 ZERO_STRUCT(option.ctr.type[0]);
2458 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2459 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2460 option.ctr.type[0].fields_ptr = 1;
2461 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2463 ZERO_STRUCT(option.ctr.type[1]);
2464 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2465 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2466 option.ctr.type[1].fields_ptr = 1;
2467 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2469 /* Send rffpcnex */
2471 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2472 strupper_m(servername);
2474 result = rpccli_spoolss_rffpcnex(
2475 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2477 if (!W_ERROR_IS_OK(result)) {
2478 printf("Error rffpcnex %s\n", argv[1]);
2479 goto done;
2482 done:
2483 if (got_hnd)
2484 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2486 return result;
2489 /****************************************************************************
2490 ****************************************************************************/
2492 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2493 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2495 PRINTER_INFO_CTR ctr1, ctr2;
2496 WERROR werror;
2497 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2499 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2500 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2501 if ( !W_ERROR_IS_OK(werror) ) {
2502 printf("failed (%s)\n", dos_errstr(werror));
2503 talloc_destroy(mem_ctx);
2504 return False;
2506 printf("ok\n");
2508 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2509 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2510 if ( !W_ERROR_IS_OK(werror) ) {
2511 printf("failed (%s)\n", dos_errstr(werror));
2512 talloc_destroy(mem_ctx);
2513 return False;
2515 printf("ok\n");
2517 talloc_destroy(mem_ctx);
2519 return True;
2522 /****************************************************************************
2523 ****************************************************************************/
2525 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2526 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2528 PRINTER_INFO_CTR ctr1, ctr2;
2529 WERROR werror;
2530 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2531 SEC_DESC *sd1, *sd2;
2532 BOOL result = True;
2535 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2536 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2537 if ( !W_ERROR_IS_OK(werror) ) {
2538 printf("failed (%s)\n", dos_errstr(werror));
2539 result = False;
2540 goto done;
2542 printf("ok\n");
2544 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2545 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2546 if ( !W_ERROR_IS_OK(werror) ) {
2547 printf("failed (%s)\n", dos_errstr(werror));
2548 result = False;
2549 goto done;
2551 printf("ok\n");
2554 printf("++ ");
2556 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2557 printf("NULL PRINTER_INFO_3!\n");
2558 result = False;
2559 goto done;
2562 sd1 = ctr1.printers_3->secdesc;
2563 sd2 = ctr2.printers_3->secdesc;
2565 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2566 printf("NULL secdesc!\n");
2567 result = False;
2568 goto done;
2571 if ( (ctr1.printers_3->flags != ctr1.printers_3->flags ) || !sec_desc_equal( sd1, sd2 ) ) {
2572 printf("Security Descriptors *not* equal!\n");
2573 result = False;
2574 goto done;
2577 printf("Security descriptors match\n");
2579 done:
2580 talloc_destroy(mem_ctx);
2581 return result;
2585 /****************************************************************************
2586 ****************************************************************************/
2588 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2589 TALLOC_CTX *mem_ctx, int argc,
2590 const char **argv)
2592 fstring printername, servername1, servername2;
2593 pstring printername_path;
2594 struct cli_state *cli_server1 = cli->cli;
2595 struct cli_state *cli_server2 = NULL;
2596 struct rpc_pipe_client *cli2 = NULL;
2597 POLICY_HND hPrinter1, hPrinter2;
2598 NTSTATUS nt_status;
2599 WERROR werror;
2601 if ( argc != 3 ) {
2602 printf("Usage: %s <printer> <server>\n", argv[0]);
2603 return WERR_OK;
2606 fstrcpy( printername, argv[1] );
2608 fstr_sprintf( servername1, cli->cli->desthost );
2609 fstrcpy( servername2, argv[2] );
2610 strupper_m( servername1 );
2611 strupper_m( servername2 );
2614 /* first get the connection to the remote server */
2616 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2617 NULL, 0,
2618 "IPC$", "IPC",
2619 cmdline_auth_info.username,
2620 lp_workgroup(),
2621 cmdline_auth_info.password,
2622 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2623 cmdline_auth_info.signing_state, NULL);
2625 if ( !NT_STATUS_IS_OK(nt_status) )
2626 return WERR_GENERAL_FAILURE;
2628 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2629 if (!cli2) {
2630 printf("failed to open spoolss pipe on server %s (%s)\n",
2631 servername2, nt_errstr(nt_status));
2632 return WERR_GENERAL_FAILURE;
2635 /* now open up both printers */
2637 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2638 printf("Opening %s...", printername_path);
2639 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2640 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2641 if ( !W_ERROR_IS_OK(werror) ) {
2642 printf("failed (%s)\n", dos_errstr(werror));
2643 goto done;
2645 printf("ok\n");
2647 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2648 printf("Opening %s...", printername_path);
2649 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2650 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2651 if ( !W_ERROR_IS_OK(werror) ) {
2652 printf("failed (%s)\n", dos_errstr(werror));
2653 goto done;
2655 printf("ok\n");
2658 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2659 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2660 #if 0
2661 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2662 #endif
2665 done:
2666 /* cleanup */
2668 printf("Closing printers...");
2669 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2670 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2671 printf("ok\n");
2673 /* close the second remote connection */
2675 cli_shutdown( cli_server2 );
2677 return WERR_OK;
2680 /* List of commands exported by this module */
2681 struct cmd_set spoolss_commands[] = {
2683 { "SPOOLSS" },
2685 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2686 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2687 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2688 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2689 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2690 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2691 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2692 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2693 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2694 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2695 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2696 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2697 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2698 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2699 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2700 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2701 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2702 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2703 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2704 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2705 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2706 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2707 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2708 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2709 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2710 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2711 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2712 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2713 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },
2715 { NULL }