r21550: make disp_info_list static to get_samr_dispinfo_by_sid(), add a comment :-)
[Samba/bb.git] / source / rpcclient / cmd_spoolss.c
blobfe165732486ab0412d319c03f8fa61e01a0542eb
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 uint32 i, num_values;
713 char **values;
715 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
716 value.size, &num_values,
717 &values))) {
718 d_printf("reg_pull_multi_sz failed\n");
719 break;
722 for (i=0; i<num_values; i++) {
723 d_printf("%s\n", values[i]);
725 TALLOC_FREE(values);
726 break;
728 default:
729 printf("%s: unknown type %d\n", value.valuename, value.type);
734 /****************************************************************************
735 ****************************************************************************/
737 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
738 TALLOC_CTX *mem_ctx,
739 int argc, const char **argv)
741 POLICY_HND pol;
742 WERROR result;
743 BOOL opened_hnd = False;
744 fstring printername,
745 servername,
746 user;
747 const char *valuename;
748 REGISTRY_VALUE value;
750 if (argc != 3) {
751 printf("Usage: %s <printername> <valuename>\n", argv[0]);
752 printf("<printername> of . queries print server\n");
753 return WERR_OK;
755 valuename = argv[2];
757 /* Open a printer handle */
759 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
760 strupper_m(servername);
761 if (strncmp(argv[1], ".", sizeof(".")) == 0)
762 fstrcpy(printername, servername);
763 else
764 slprintf(printername, sizeof(servername)-1, "%s\\%s",
765 servername, argv[1]);
766 fstrcpy(user, cli->user_name);
768 /* get a printer handle */
770 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
771 "", MAXIMUM_ALLOWED_ACCESS,
772 servername, user, &pol);
774 if (!W_ERROR_IS_OK(result))
775 goto done;
777 opened_hnd = True;
779 /* Get printer info */
781 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
783 if (!W_ERROR_IS_OK(result))
784 goto done;
786 /* Display printer data */
788 fstrcpy(value.valuename, valuename);
789 display_reg_value(value);
792 done:
793 if (opened_hnd)
794 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
796 return result;
799 /****************************************************************************
800 ****************************************************************************/
802 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
803 TALLOC_CTX *mem_ctx,
804 int argc, const char **argv)
806 POLICY_HND pol;
807 WERROR result;
808 BOOL opened_hnd = False;
809 fstring printername,
810 servername,
811 user;
812 const char *valuename, *keyname;
813 REGISTRY_VALUE value;
815 if (argc != 4) {
816 printf("Usage: %s <printername> <keyname> <valuename>\n",
817 argv[0]);
818 printf("<printername> of . queries print server\n");
819 return WERR_OK;
821 valuename = argv[3];
822 keyname = argv[2];
824 /* Open a printer handle */
826 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
827 strupper_m(servername);
828 if (strncmp(argv[1], ".", sizeof(".")) == 0)
829 fstrcpy(printername, servername);
830 else
831 slprintf(printername, sizeof(printername)-1, "%s\\%s",
832 servername, argv[1]);
833 fstrcpy(user, cli->user_name);
835 /* get a printer handle */
837 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
838 "", MAXIMUM_ALLOWED_ACCESS,
839 servername, user, &pol);
841 if (!W_ERROR_IS_OK(result))
842 goto done;
844 opened_hnd = True;
846 /* Get printer info */
848 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
849 valuename, &value);
851 if (!W_ERROR_IS_OK(result))
852 goto done;
854 /* Display printer data */
856 fstrcpy(value.valuename, valuename);
857 display_reg_value(value);
860 done:
861 if (opened_hnd)
862 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
864 return result;
867 /****************************************************************************
868 ****************************************************************************/
870 static void display_print_driver_1(DRIVER_INFO_1 *i1)
872 fstring name;
873 if (i1 == NULL)
874 return;
876 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
878 printf ("Printer Driver Info 1:\n");
879 printf ("\tDriver Name: [%s]\n\n", name);
881 return;
884 /****************************************************************************
885 ****************************************************************************/
887 static void display_print_driver_2(DRIVER_INFO_2 *i1)
889 fstring name;
890 fstring architecture;
891 fstring driverpath;
892 fstring datafile;
893 fstring configfile;
894 if (i1 == NULL)
895 return;
897 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
898 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
899 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
900 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
901 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
903 printf ("Printer Driver Info 2:\n");
904 printf ("\tVersion: [%x]\n", i1->version);
905 printf ("\tDriver Name: [%s]\n", name);
906 printf ("\tArchitecture: [%s]\n", architecture);
907 printf ("\tDriver Path: [%s]\n", driverpath);
908 printf ("\tDatafile: [%s]\n", datafile);
909 printf ("\tConfigfile: [%s]\n\n", configfile);
911 return;
914 /****************************************************************************
915 ****************************************************************************/
917 static void display_print_driver_3(DRIVER_INFO_3 *i1)
919 fstring name = "";
920 fstring architecture = "";
921 fstring driverpath = "";
922 fstring datafile = "";
923 fstring configfile = "";
924 fstring helpfile = "";
925 fstring dependentfiles = "";
926 fstring monitorname = "";
927 fstring defaultdatatype = "";
929 int length=0;
930 BOOL valid = True;
932 if (i1 == NULL)
933 return;
935 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
936 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
937 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
938 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
939 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
940 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
941 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
942 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
944 printf ("Printer Driver Info 3:\n");
945 printf ("\tVersion: [%x]\n", i1->version);
946 printf ("\tDriver Name: [%s]\n",name);
947 printf ("\tArchitecture: [%s]\n", architecture);
948 printf ("\tDriver Path: [%s]\n", driverpath);
949 printf ("\tDatafile: [%s]\n", datafile);
950 printf ("\tConfigfile: [%s]\n", configfile);
951 printf ("\tHelpfile: [%s]\n\n", helpfile);
953 while (valid)
955 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
957 length+=strlen(dependentfiles)+1;
959 if (strlen(dependentfiles) > 0)
961 printf ("\tDependentfiles: [%s]\n", dependentfiles);
963 else
965 valid = False;
969 printf ("\n");
971 printf ("\tMonitorname: [%s]\n", monitorname);
972 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
974 return;
977 /****************************************************************************
978 ****************************************************************************/
980 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
981 TALLOC_CTX *mem_ctx,
982 int argc, const char **argv)
984 POLICY_HND pol;
985 WERROR werror;
986 uint32 info_level = 3;
987 BOOL opened_hnd = False;
988 PRINTER_DRIVER_CTR ctr;
989 fstring printername,
990 servername,
991 user;
992 uint32 i;
993 BOOL success = False;
995 if ((argc == 1) || (argc > 3))
997 printf("Usage: %s <printername> [level]\n", argv[0]);
998 return WERR_OK;
1001 /* get the arguments need to open the printer handle */
1002 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1003 strupper_m(servername);
1004 fstrcpy(user, cli->user_name);
1005 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1006 if (argc == 3)
1007 info_level = atoi(argv[2]);
1009 /* Open a printer handle */
1011 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1012 PRINTER_ACCESS_USE,
1013 servername, user, &pol);
1015 if (!W_ERROR_IS_OK(werror)) {
1016 printf("Error opening printer handle for %s!\n", printername);
1017 return werror;
1020 opened_hnd = True;
1022 /* loop through and print driver info level for each architecture */
1024 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1026 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1027 archi_table[i].long_archi, archi_table[i].version,
1028 &ctr);
1030 if (!W_ERROR_IS_OK(werror))
1031 continue;
1033 /* need at least one success */
1035 success = True;
1037 printf ("\n[%s]\n", archi_table[i].long_archi);
1039 switch (info_level) {
1040 case 1:
1041 display_print_driver_1 (ctr.info1);
1042 break;
1043 case 2:
1044 display_print_driver_2 (ctr.info2);
1045 break;
1046 case 3:
1047 display_print_driver_3 (ctr.info3);
1048 break;
1049 default:
1050 printf("unknown info level %d\n", info_level);
1051 break;
1055 /* Cleanup */
1057 if (opened_hnd)
1058 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1060 if ( success )
1061 werror = WERR_OK;
1063 return werror;
1066 /****************************************************************************
1067 ****************************************************************************/
1069 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1070 TALLOC_CTX *mem_ctx,
1071 int argc, const char **argv)
1073 WERROR werror = WERR_OK;
1074 uint32 info_level = 1;
1075 PRINTER_DRIVER_CTR ctr;
1076 uint32 i, j,
1077 returned;
1079 if (argc > 2) {
1080 printf("Usage: enumdrivers [level]\n");
1081 return WERR_OK;
1084 if (argc == 2)
1085 info_level = atoi(argv[1]);
1088 /* loop through and print driver info level for each architecture */
1089 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1090 /* check to see if we already asked for this architecture string */
1092 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1093 continue;
1095 werror = rpccli_spoolss_enumprinterdrivers(
1096 cli, mem_ctx, info_level,
1097 archi_table[i].long_archi, &returned, &ctr);
1099 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1100 printf ("Server does not support environment [%s]\n",
1101 archi_table[i].long_archi);
1102 werror = WERR_OK;
1103 continue;
1106 if (returned == 0)
1107 continue;
1109 if (!W_ERROR_IS_OK(werror)) {
1110 printf ("Error getting driver for environment [%s] - %d\n",
1111 archi_table[i].long_archi, W_ERROR_V(werror));
1112 continue;
1115 printf ("\n[%s]\n", archi_table[i].long_archi);
1116 switch (info_level)
1119 case 1:
1120 for (j=0; j < returned; j++) {
1121 display_print_driver_1 (&ctr.info1[j]);
1123 break;
1124 case 2:
1125 for (j=0; j < returned; j++) {
1126 display_print_driver_2 (&ctr.info2[j]);
1128 break;
1129 case 3:
1130 for (j=0; j < returned; j++) {
1131 display_print_driver_3 (&ctr.info3[j]);
1133 break;
1134 default:
1135 printf("unknown info level %d\n", info_level);
1136 return WERR_UNKNOWN_LEVEL;
1140 return werror;
1143 /****************************************************************************
1144 ****************************************************************************/
1146 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1148 fstring name;
1149 if (i1 == NULL)
1150 return;
1152 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1154 printf ("\tDirectory Name:[%s]\n", name);
1157 /****************************************************************************
1158 ****************************************************************************/
1160 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1161 TALLOC_CTX *mem_ctx,
1162 int argc, const char **argv)
1164 WERROR result;
1165 fstring env;
1166 DRIVER_DIRECTORY_CTR ctr;
1168 if (argc > 2) {
1169 printf("Usage: %s [environment]\n", argv[0]);
1170 return WERR_OK;
1173 /* Get the arguments need to open the printer handle */
1175 if (argc == 2)
1176 fstrcpy (env, argv[1]);
1177 else
1178 fstrcpy (env, "Windows NT x86");
1180 /* Get the directory. Only use Info level 1 */
1182 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1184 if (W_ERROR_IS_OK(result))
1185 display_printdriverdir_1(ctr.info1);
1187 return result;
1190 /****************************************************************************
1191 ****************************************************************************/
1193 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1196 int i;
1198 for (i=0; archi_table[i].long_archi != NULL; i++)
1200 if (strcmp(arch, archi_table[i].short_archi) == 0)
1202 info->version = archi_table[i].version;
1203 init_unistr (&info->architecture, archi_table[i].long_archi);
1204 break;
1208 if (archi_table[i].long_archi == NULL)
1210 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1213 return;
1217 /**************************************************************************
1218 wrapper for strtok to get the next parameter from a delimited list.
1219 Needed to handle the empty parameter string denoted by "NULL"
1220 *************************************************************************/
1222 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1224 char *ptr;
1226 /* get the next token */
1227 ptr = strtok(str, delim);
1229 /* a string of 'NULL' is used to represent an empty
1230 parameter because two consecutive delimiters
1231 will not return an empty string. See man strtok(3)
1232 for details */
1233 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1234 ptr = NULL;
1236 if (dest != NULL)
1237 init_unistr(dest, ptr);
1239 return ptr;
1242 /********************************************************************************
1243 fill in the members of a DRIVER_INFO_3 struct using a character
1244 string in the form of
1245 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1246 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1247 <Default Data Type>:<Comma Separated list of Files>
1248 *******************************************************************************/
1249 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1250 char *args )
1252 char *str, *str2;
1253 uint32 len, i;
1255 /* fill in the UNISTR fields */
1256 str = get_driver_3_param (args, ":", &info->name);
1257 str = get_driver_3_param (NULL, ":", &info->driverpath);
1258 str = get_driver_3_param (NULL, ":", &info->datafile);
1259 str = get_driver_3_param (NULL, ":", &info->configfile);
1260 str = get_driver_3_param (NULL, ":", &info->helpfile);
1261 str = get_driver_3_param (NULL, ":", &info->monitorname);
1262 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1264 /* <Comma Separated List of Dependent Files> */
1265 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1266 str = str2;
1268 /* begin to strip out each filename */
1269 str = strtok(str, ",");
1270 len = 0;
1271 while (str != NULL)
1273 /* keep a cumlative count of the str lengths */
1274 len += strlen(str)+1;
1275 str = strtok(NULL, ",");
1278 /* allocate the space; add one extra slot for a terminating NULL.
1279 Each filename is NULL terminated and the end contains a double
1280 NULL */
1281 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1283 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1284 return False;
1286 for (i=0; i<len; i++)
1288 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1290 info->dependentfiles[len] = '\0';
1292 return True;
1296 /****************************************************************************
1297 ****************************************************************************/
1299 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1300 TALLOC_CTX *mem_ctx,
1301 int argc, const char **argv)
1303 WERROR result;
1304 uint32 level = 3;
1305 PRINTER_DRIVER_CTR ctr;
1306 DRIVER_INFO_3 info3;
1307 const char *arch;
1308 fstring driver_name;
1309 char *driver_args;
1311 /* parse the command arguements */
1312 if (argc != 3 && argc != 4)
1314 printf ("Usage: %s <Environment> \\\n", argv[0]);
1315 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1316 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1317 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1318 printf ("\t[version]\n");
1320 return WERR_OK;
1323 /* Fill in the DRIVER_INFO_3 struct */
1324 ZERO_STRUCT(info3);
1325 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1327 printf ("Error Unknown architechture [%s]\n", argv[1]);
1328 return WERR_INVALID_PARAM;
1330 else
1331 set_drv_info_3_env(&info3, arch);
1333 driver_args = talloc_strdup( mem_ctx, argv[2] );
1334 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1336 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1337 return WERR_INVALID_PARAM;
1340 /* if printer driver version specified, override the default version
1341 * used by the architecture. This allows installation of Windows
1342 * 2000 (version 3) printer drivers. */
1343 if (argc == 4)
1345 info3.version = atoi(argv[3]);
1349 ctr.info3 = &info3;
1350 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1352 if (W_ERROR_IS_OK(result)) {
1353 rpcstr_pull(driver_name, info3.name.buffer,
1354 sizeof(driver_name), -1, STR_TERMINATE);
1355 printf ("Printer Driver %s successfully installed.\n",
1356 driver_name);
1359 return result;
1363 /****************************************************************************
1364 ****************************************************************************/
1366 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1367 TALLOC_CTX *mem_ctx,
1368 int argc, const char **argv)
1370 WERROR result;
1371 uint32 level = 2;
1372 PRINTER_INFO_CTR ctr;
1373 PRINTER_INFO_2 info2;
1374 fstring servername;
1376 /* parse the command arguements */
1377 if (argc != 5)
1379 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1380 return WERR_OK;
1383 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1384 strupper_m(servername);
1386 /* Fill in the DRIVER_INFO_2 struct */
1387 ZERO_STRUCT(info2);
1389 init_unistr( &info2.printername, argv[1]);
1390 init_unistr( &info2.sharename, argv[2]);
1391 init_unistr( &info2.drivername, argv[3]);
1392 init_unistr( &info2.portname, argv[4]);
1393 init_unistr( &info2.comment, "Created by rpcclient");
1394 init_unistr( &info2.printprocessor, "winprint");
1395 init_unistr( &info2.datatype, "RAW");
1396 info2.devmode = NULL;
1397 info2.secdesc = NULL;
1398 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1399 info2.priority = 0;
1400 info2.defaultpriority = 0;
1401 info2.starttime = 0;
1402 info2.untiltime = 0;
1404 /* These three fields must not be used by AddPrinter()
1405 as defined in the MS Platform SDK documentation..
1406 --jerry
1407 info2.status = 0;
1408 info2.cjobs = 0;
1409 info2.averageppm = 0;
1412 ctr.printers_2 = &info2;
1413 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1415 if (W_ERROR_IS_OK(result))
1416 printf ("Printer %s successfully installed.\n", argv[1]);
1418 return result;
1421 /****************************************************************************
1422 ****************************************************************************/
1424 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1425 TALLOC_CTX *mem_ctx,
1426 int argc, const char **argv)
1428 POLICY_HND pol;
1429 WERROR result;
1430 uint32 level = 2;
1431 BOOL opened_hnd = False;
1432 PRINTER_INFO_CTR ctr;
1433 PRINTER_INFO_2 info2;
1434 fstring servername,
1435 printername,
1436 user;
1438 /* parse the command arguements */
1439 if (argc != 3)
1441 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1442 return WERR_OK;
1445 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1446 strupper_m(servername);
1447 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1448 fstrcpy(user, cli->user_name);
1450 /* Get a printer handle */
1452 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1453 PRINTER_ALL_ACCESS,
1454 servername, user, &pol);
1456 if (!W_ERROR_IS_OK(result))
1457 goto done;
1459 opened_hnd = True;
1461 /* Get printer info */
1463 ZERO_STRUCT (info2);
1464 ctr.printers_2 = &info2;
1466 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1468 if (!W_ERROR_IS_OK(result)) {
1469 printf ("Unable to retrieve printer information!\n");
1470 goto done;
1473 /* Set the printer driver */
1475 init_unistr(&ctr.printers_2->drivername, argv[2]);
1477 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1479 if (!W_ERROR_IS_OK(result)) {
1480 printf("SetPrinter call failed!\n");
1481 goto done;;
1484 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1486 done:
1487 /* Cleanup */
1489 if (opened_hnd)
1490 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1492 return result;
1496 /****************************************************************************
1497 ****************************************************************************/
1499 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1500 TALLOC_CTX *mem_ctx,
1501 int argc, const char **argv)
1503 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1505 int i;
1506 int vers = -1;
1508 const char *arch = NULL;
1510 /* parse the command arguements */
1511 if (argc < 2 || argc > 4) {
1512 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1513 return WERR_OK;
1516 if (argc >= 3)
1517 arch = argv[2];
1518 if (argc == 4)
1519 vers = atoi (argv[3]);
1522 /* delete the driver for all architectures */
1523 for (i=0; archi_table[i].long_archi; i++) {
1525 if (arch && !strequal( archi_table[i].long_archi, arch))
1526 continue;
1528 if (vers >= 0 && archi_table[i].version != vers)
1529 continue;
1531 /* make the call to remove the driver */
1532 result = rpccli_spoolss_deleteprinterdriverex(
1533 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1535 if ( !W_ERROR_IS_OK(result) )
1537 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1538 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1539 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1542 else
1544 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1545 archi_table[i].long_archi, archi_table[i].version);
1546 ret = WERR_OK;
1550 return ret;
1554 /****************************************************************************
1555 ****************************************************************************/
1557 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1558 TALLOC_CTX *mem_ctx,
1559 int argc, const char **argv)
1561 WERROR result = WERR_OK;
1562 fstring servername;
1563 int i;
1565 /* parse the command arguements */
1566 if (argc != 2) {
1567 printf ("Usage: %s <driver>\n", argv[0]);
1568 return WERR_OK;
1571 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1572 strupper_m(servername);
1574 /* delete the driver for all architectures */
1575 for (i=0; archi_table[i].long_archi; i++) {
1576 /* make the call to remove the driver */
1577 result = rpccli_spoolss_deleteprinterdriver(
1578 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1580 if ( !W_ERROR_IS_OK(result) ) {
1581 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1582 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1583 argv[1], archi_table[i].long_archi,
1584 W_ERROR_V(result));
1586 } else {
1587 printf ("Driver %s removed for arch [%s].\n", argv[1],
1588 archi_table[i].long_archi);
1592 return result;
1595 /****************************************************************************
1596 ****************************************************************************/
1598 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1599 TALLOC_CTX *mem_ctx,
1600 int argc, const char **argv)
1602 WERROR result;
1603 char *servername = NULL, *environment = NULL;
1604 fstring procdir;
1606 /* parse the command arguements */
1607 if (argc > 2) {
1608 printf ("Usage: %s [environment]\n", argv[0]);
1609 return WERR_OK;
1612 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1613 return WERR_NOMEM;
1614 strupper_m(servername);
1616 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1617 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1618 SAFE_FREE(servername);
1619 return WERR_NOMEM;
1622 result = rpccli_spoolss_getprintprocessordirectory(
1623 cli, mem_ctx, servername, environment, procdir);
1625 if (W_ERROR_IS_OK(result))
1626 printf("%s\n", procdir);
1628 SAFE_FREE(servername);
1629 SAFE_FREE(environment);
1631 return result;
1634 /****************************************************************************
1635 ****************************************************************************/
1637 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1638 int argc, const char **argv)
1640 POLICY_HND handle;
1641 WERROR werror;
1642 char *servername = NULL, *printername = NULL;
1643 FORM form;
1644 BOOL got_handle = False;
1646 /* Parse the command arguements */
1648 if (argc != 3) {
1649 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1650 return WERR_OK;
1653 /* Get a printer handle */
1655 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1656 strupper_m(servername);
1657 asprintf(&printername, "%s\\%s", servername, argv[1]);
1659 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1660 PRINTER_ALL_ACCESS,
1661 servername, cli->user_name, &handle);
1663 if (!W_ERROR_IS_OK(werror))
1664 goto done;
1666 got_handle = True;
1668 /* Dummy up some values for the form data */
1670 form.flags = FORM_USER;
1671 form.size_x = form.size_y = 100;
1672 form.left = 0;
1673 form.top = 10;
1674 form.right = 20;
1675 form.bottom = 30;
1677 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1679 /* Add the form */
1682 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1684 done:
1685 if (got_handle)
1686 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1688 SAFE_FREE(servername);
1689 SAFE_FREE(printername);
1691 return werror;
1694 /****************************************************************************
1695 ****************************************************************************/
1697 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1698 int argc, const char **argv)
1700 POLICY_HND handle;
1701 WERROR werror;
1702 char *servername = NULL, *printername = NULL;
1703 FORM form;
1704 BOOL got_handle = False;
1706 /* Parse the command arguements */
1708 if (argc != 3) {
1709 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1710 return WERR_OK;
1713 /* Get a printer handle */
1715 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1716 strupper_m(servername);
1717 asprintf(&printername, "%s\\%s", servername, argv[1]);
1719 werror = rpccli_spoolss_open_printer_ex(
1720 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1721 servername, cli->user_name, &handle);
1723 if (!W_ERROR_IS_OK(werror))
1724 goto done;
1726 got_handle = True;
1728 /* Dummy up some values for the form data */
1730 form.flags = FORM_PRINTER;
1731 form.size_x = form.size_y = 100;
1732 form.left = 0;
1733 form.top = 1000;
1734 form.right = 2000;
1735 form.bottom = 3000;
1737 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1739 /* Set the form */
1741 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1743 done:
1744 if (got_handle)
1745 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1747 SAFE_FREE(servername);
1748 SAFE_FREE(printername);
1750 return werror;
1753 /****************************************************************************
1754 ****************************************************************************/
1756 static const char *get_form_flag(int form_flag)
1758 switch (form_flag) {
1759 case FORM_USER:
1760 return "FORM_USER";
1761 case FORM_BUILTIN:
1762 return "FORM_BUILTIN";
1763 case FORM_PRINTER:
1764 return "FORM_PRINTER";
1765 default:
1766 return "unknown";
1770 /****************************************************************************
1771 ****************************************************************************/
1773 static void display_form(FORM_1 *form)
1775 fstring form_name = "";
1777 if (form->name.buffer)
1778 rpcstr_pull(form_name, form->name.buffer,
1779 sizeof(form_name), -1, STR_TERMINATE);
1781 printf("%s\n" \
1782 "\tflag: %s (%d)\n" \
1783 "\twidth: %d, length: %d\n" \
1784 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1785 form_name, get_form_flag(form->flag), form->flag,
1786 form->width, form->length,
1787 form->left, form->right,
1788 form->top, form->bottom);
1791 /****************************************************************************
1792 ****************************************************************************/
1794 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1795 int argc, const char **argv)
1797 POLICY_HND handle;
1798 WERROR werror;
1799 char *servername = NULL, *printername = NULL;
1800 FORM_1 form;
1801 BOOL got_handle = False;
1803 /* Parse the command arguements */
1805 if (argc != 3) {
1806 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1807 return WERR_OK;
1810 /* Get a printer handle */
1812 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1813 strupper_m(servername);
1814 asprintf(&printername, "%s\\%s", servername, argv[1]);
1816 werror = rpccli_spoolss_open_printer_ex(
1817 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1818 servername, cli->user_name, &handle);
1820 if (!W_ERROR_IS_OK(werror))
1821 goto done;
1823 got_handle = True;
1825 /* Get the form */
1827 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1829 if (!W_ERROR_IS_OK(werror))
1830 goto done;
1832 display_form(&form);
1834 done:
1835 if (got_handle)
1836 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1838 SAFE_FREE(servername);
1839 SAFE_FREE(printername);
1841 return werror;
1844 /****************************************************************************
1845 ****************************************************************************/
1847 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1848 TALLOC_CTX *mem_ctx, int argc,
1849 const char **argv)
1851 POLICY_HND handle;
1852 WERROR werror;
1853 char *servername = NULL, *printername = NULL;
1854 BOOL got_handle = False;
1856 /* Parse the command arguements */
1858 if (argc != 3) {
1859 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1860 return WERR_OK;
1863 /* Get a printer handle */
1865 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1866 strupper_m(servername);
1867 asprintf(&printername, "%s\\%s", servername, argv[1]);
1869 werror = rpccli_spoolss_open_printer_ex(
1870 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1871 servername, cli->user_name, &handle);
1873 if (!W_ERROR_IS_OK(werror))
1874 goto done;
1876 got_handle = True;
1878 /* Delete the form */
1880 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1882 done:
1883 if (got_handle)
1884 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1886 SAFE_FREE(servername);
1887 SAFE_FREE(printername);
1889 return werror;
1892 /****************************************************************************
1893 ****************************************************************************/
1895 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1896 TALLOC_CTX *mem_ctx, int argc,
1897 const char **argv)
1899 POLICY_HND handle;
1900 WERROR werror;
1901 char *servername = NULL, *printername = NULL;
1902 BOOL got_handle = False;
1903 uint32 num_forms, level = 1, i;
1904 FORM_1 *forms;
1906 /* Parse the command arguements */
1908 if (argc != 2) {
1909 printf ("Usage: %s <printer>\n", argv[0]);
1910 return WERR_OK;
1913 /* Get a printer handle */
1915 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1916 strupper_m(servername);
1917 asprintf(&printername, "%s\\%s", servername, argv[1]);
1919 werror = rpccli_spoolss_open_printer_ex(
1920 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1921 servername, cli->user_name, &handle);
1923 if (!W_ERROR_IS_OK(werror))
1924 goto done;
1926 got_handle = True;
1928 /* Enumerate forms */
1930 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1932 if (!W_ERROR_IS_OK(werror))
1933 goto done;
1935 /* Display output */
1937 for (i = 0; i < num_forms; i++) {
1939 display_form(&forms[i]);
1943 done:
1944 if (got_handle)
1945 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1947 SAFE_FREE(servername);
1948 SAFE_FREE(printername);
1950 return werror;
1953 /****************************************************************************
1954 ****************************************************************************/
1956 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1957 TALLOC_CTX *mem_ctx,
1958 int argc, const char **argv)
1960 WERROR result;
1961 fstring servername, printername, user;
1962 POLICY_HND pol;
1963 BOOL opened_hnd = False;
1964 PRINTER_INFO_CTR ctr;
1965 PRINTER_INFO_0 info;
1966 REGISTRY_VALUE value;
1968 /* parse the command arguements */
1969 if (argc < 5) {
1970 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1971 " <value> <data>\n",
1972 argv[0]);
1973 return WERR_INVALID_PARAM;
1976 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1977 strupper_m(servername);
1978 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1979 fstrcpy(user, cli->user_name);
1981 value.type = REG_NONE;
1983 if (strequal(argv[2], "string")) {
1984 value.type = REG_SZ;
1987 if (strequal(argv[2], "binary")) {
1988 value.type = REG_BINARY;
1991 if (strequal(argv[2], "dword")) {
1992 value.type = REG_DWORD;
1995 if (strequal(argv[2], "multistring")) {
1996 value.type = REG_MULTI_SZ;
1999 if (value.type == REG_NONE) {
2000 printf("Unknown data type: %s\n", argv[2]);
2001 return WERR_INVALID_PARAM;
2004 /* get a printer handle */
2005 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2006 MAXIMUM_ALLOWED_ACCESS, servername,
2007 user, &pol);
2008 if (!W_ERROR_IS_OK(result))
2009 goto done;
2011 opened_hnd = True;
2013 ctr.printers_0 = &info;
2015 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2017 if (!W_ERROR_IS_OK(result))
2018 goto done;
2020 printf("%s\n", current_timestring(True));
2021 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2023 /* Set the printer data */
2025 fstrcpy(value.valuename, argv[3]);
2027 switch (value.type) {
2028 case REG_SZ: {
2029 UNISTR2 data;
2030 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2031 value.size = data.uni_str_len * 2;
2032 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2033 value.size);
2034 break;
2036 case REG_DWORD: {
2037 uint32 data = strtoul(argv[4], NULL, 10);
2038 value.size = sizeof(data);
2039 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2040 sizeof(data));
2041 break;
2043 case REG_BINARY: {
2044 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2045 value.data_p = data.data;
2046 value.size = data.length;
2047 break;
2049 case REG_MULTI_SZ: {
2050 int i;
2051 size_t len = 0;
2052 char *p;
2054 for (i=4; i<argc; i++) {
2055 if (strcmp(argv[i], "NULL") == 0) {
2056 argv[i] = "";
2058 len += strlen(argv[i])+1;
2061 value.size = len*2;
2062 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2063 if (value.data_p == NULL) {
2064 result = WERR_NOMEM;
2065 goto done;
2068 p = (char *)value.data_p;
2069 len = value.size;
2070 for (i=4; i<argc; i++) {
2071 size_t l = (strlen(argv[i])+1)*2;
2072 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2073 p += l;
2074 len -= l;
2076 SMB_ASSERT(len == 0);
2077 break;
2079 default:
2080 printf("Unknown data type: %s\n", argv[2]);
2081 result = WERR_INVALID_PARAM;
2082 goto done;
2085 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2087 if (!W_ERROR_IS_OK(result)) {
2088 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2089 goto done;
2091 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2093 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2095 if (!W_ERROR_IS_OK(result))
2096 goto done;
2098 printf("%s\n", current_timestring(True));
2099 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2101 done:
2102 /* cleanup */
2103 if (opened_hnd)
2104 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2106 return result;
2109 /****************************************************************************
2110 ****************************************************************************/
2112 static void display_job_info_1(JOB_INFO_1 *job)
2114 fstring username = "", document = "", text_status = "";
2116 rpcstr_pull(username, job->username.buffer,
2117 sizeof(username), -1, STR_TERMINATE);
2119 rpcstr_pull(document, job->document.buffer,
2120 sizeof(document), -1, STR_TERMINATE);
2122 rpcstr_pull(text_status, job->text_status.buffer,
2123 sizeof(text_status), -1, STR_TERMINATE);
2125 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2126 username, document, text_status, job->pagesprinted,
2127 job->totalpages);
2130 /****************************************************************************
2131 ****************************************************************************/
2133 static void display_job_info_2(JOB_INFO_2 *job)
2135 fstring username = "", document = "", text_status = "";
2137 rpcstr_pull(username, job->username.buffer,
2138 sizeof(username), -1, STR_TERMINATE);
2140 rpcstr_pull(document, job->document.buffer,
2141 sizeof(document), -1, STR_TERMINATE);
2143 rpcstr_pull(text_status, job->text_status.buffer,
2144 sizeof(text_status), -1, STR_TERMINATE);
2146 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2147 username, document, text_status, job->pagesprinted,
2148 job->totalpages, job->size);
2151 /****************************************************************************
2152 ****************************************************************************/
2154 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2155 TALLOC_CTX *mem_ctx, int argc,
2156 const char **argv)
2158 WERROR result;
2159 uint32 level = 1, num_jobs, i;
2160 BOOL got_hnd = False;
2161 pstring printername;
2162 fstring servername, user;
2163 POLICY_HND hnd;
2164 JOB_INFO_CTR ctr;
2166 if (argc < 2 || argc > 3) {
2167 printf("Usage: %s printername [level]\n", argv[0]);
2168 return WERR_OK;
2171 if (argc == 3)
2172 level = atoi(argv[2]);
2174 /* Open printer handle */
2176 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2177 strupper_m(servername);
2178 fstrcpy(user, cli->user_name);
2179 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2180 strupper_m(printername);
2181 pstrcat(printername, argv[1]);
2183 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2184 "", MAXIMUM_ALLOWED_ACCESS,
2185 servername, user, &hnd);
2187 if (!W_ERROR_IS_OK(result))
2188 goto done;
2190 got_hnd = True;
2192 /* Enumerate ports */
2194 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2195 &num_jobs, &ctr);
2197 if (!W_ERROR_IS_OK(result))
2198 goto done;
2200 for (i = 0; i < num_jobs; i++) {
2201 switch(level) {
2202 case 1:
2203 display_job_info_1(&ctr.job.job_info_1[i]);
2204 break;
2205 case 2:
2206 display_job_info_2(&ctr.job.job_info_2[i]);
2207 break;
2208 default:
2209 d_printf("unknown info level %d\n", level);
2210 break;
2214 done:
2215 if (got_hnd)
2216 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2218 return result;
2221 /****************************************************************************
2222 ****************************************************************************/
2224 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2225 TALLOC_CTX *mem_ctx, int argc,
2226 const char **argv)
2228 WERROR result;
2229 uint32 i=0, val_needed, data_needed;
2230 BOOL got_hnd = False;
2231 pstring printername;
2232 fstring servername, user;
2233 POLICY_HND hnd;
2235 if (argc != 2) {
2236 printf("Usage: %s printername\n", argv[0]);
2237 return WERR_OK;
2240 /* Open printer handle */
2242 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2243 strupper_m(servername);
2244 fstrcpy(user, cli->user_name);
2245 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2246 strupper_m(printername);
2247 pstrcat(printername, argv[1]);
2249 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2250 "", MAXIMUM_ALLOWED_ACCESS,
2251 servername, user, &hnd);
2253 if (!W_ERROR_IS_OK(result))
2254 goto done;
2256 got_hnd = True;
2258 /* Enumerate data */
2260 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2261 &val_needed, &data_needed,
2262 NULL);
2263 while (W_ERROR_IS_OK(result)) {
2264 REGISTRY_VALUE value;
2265 result = rpccli_spoolss_enumprinterdata(
2266 cli, mem_ctx, &hnd, i++, val_needed,
2267 data_needed, 0, 0, &value);
2268 if (W_ERROR_IS_OK(result))
2269 display_reg_value(value);
2271 if (W_ERROR_V(result) == ERRnomoreitems)
2272 result = W_ERROR(ERRsuccess);
2274 done:
2275 if (got_hnd)
2276 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2278 return result;
2281 /****************************************************************************
2282 ****************************************************************************/
2284 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2285 TALLOC_CTX *mem_ctx, int argc,
2286 const char **argv)
2288 WERROR result;
2289 uint32 i;
2290 BOOL got_hnd = False;
2291 pstring printername;
2292 fstring servername, user;
2293 const char *keyname = NULL;
2294 POLICY_HND hnd;
2295 REGVAL_CTR *ctr = NULL;
2297 if (argc != 3) {
2298 printf("Usage: %s printername <keyname>\n", argv[0]);
2299 return WERR_OK;
2302 keyname = argv[2];
2304 /* Open printer handle */
2306 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2307 strupper_m(servername);
2308 fstrcpy(user, cli->user_name);
2309 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2310 strupper_m(printername);
2311 pstrcat(printername, argv[1]);
2313 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2314 "", MAXIMUM_ALLOWED_ACCESS,
2315 servername, user, &hnd);
2317 if (!W_ERROR_IS_OK(result))
2318 goto done;
2320 got_hnd = True;
2322 /* Enumerate subkeys */
2324 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2325 return WERR_NOMEM;
2327 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2329 if (!W_ERROR_IS_OK(result))
2330 goto done;
2332 for (i=0; i < ctr->num_values; i++) {
2333 display_reg_value(*(ctr->values[i]));
2336 TALLOC_FREE( ctr );
2338 done:
2339 if (got_hnd)
2340 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2342 return result;
2345 /****************************************************************************
2346 ****************************************************************************/
2348 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2349 TALLOC_CTX *mem_ctx, int argc,
2350 const char **argv)
2352 WERROR result;
2353 BOOL got_hnd = False;
2354 pstring printername;
2355 fstring servername, user;
2356 const char *keyname = NULL;
2357 POLICY_HND hnd;
2358 uint16 *keylist = NULL, *curkey;
2360 if (argc < 2 || argc > 3) {
2361 printf("Usage: %s printername [keyname]\n", argv[0]);
2362 return WERR_OK;
2365 if (argc == 3)
2366 keyname = argv[2];
2367 else
2368 keyname = "";
2370 /* Open printer handle */
2372 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2373 strupper_m(servername);
2374 fstrcpy(user, cli->user_name);
2375 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2376 strupper_m(printername);
2377 pstrcat(printername, argv[1]);
2379 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2380 "", MAXIMUM_ALLOWED_ACCESS,
2381 servername, user, &hnd);
2383 if (!W_ERROR_IS_OK(result))
2384 goto done;
2386 got_hnd = True;
2388 /* Enumerate subkeys */
2390 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2392 if (!W_ERROR_IS_OK(result))
2393 goto done;
2395 curkey = keylist;
2396 while (*curkey != 0) {
2397 pstring subkey;
2398 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2399 STR_TERMINATE);
2400 printf("%s\n", subkey);
2401 curkey += strlen(subkey) + 1;
2404 done:
2406 SAFE_FREE(keylist);
2408 if (got_hnd)
2409 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2411 return result;
2414 /****************************************************************************
2415 ****************************************************************************/
2417 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2418 TALLOC_CTX *mem_ctx, int argc,
2419 const char **argv)
2421 fstring servername, printername;
2422 POLICY_HND hnd;
2423 BOOL got_hnd = False;
2424 WERROR result;
2425 SPOOL_NOTIFY_OPTION option;
2427 if (argc != 2) {
2428 printf("Usage: %s printername\n", argv[0]);
2429 result = WERR_OK;
2430 goto done;
2433 /* Open printer */
2435 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2436 strupper_m(servername);
2438 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2439 argv[1]);
2440 strupper_m(printername);
2442 result = rpccli_spoolss_open_printer_ex(
2443 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2444 servername, cli->user_name, &hnd);
2446 if (!W_ERROR_IS_OK(result)) {
2447 printf("Error opening %s\n", argv[1]);
2448 goto done;
2451 got_hnd = True;
2453 /* Create spool options */
2455 ZERO_STRUCT(option);
2457 option.version = 2;
2458 option.option_type_ptr = 1;
2459 option.count = option.ctr.count = 2;
2461 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2462 if (option.ctr.type == NULL) {
2463 result = WERR_NOMEM;
2464 goto done;
2467 ZERO_STRUCT(option.ctr.type[0]);
2468 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2469 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2470 option.ctr.type[0].fields_ptr = 1;
2471 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2473 ZERO_STRUCT(option.ctr.type[1]);
2474 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2475 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2476 option.ctr.type[1].fields_ptr = 1;
2477 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2479 /* Send rffpcnex */
2481 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2482 strupper_m(servername);
2484 result = rpccli_spoolss_rffpcnex(
2485 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2487 if (!W_ERROR_IS_OK(result)) {
2488 printf("Error rffpcnex %s\n", argv[1]);
2489 goto done;
2492 done:
2493 if (got_hnd)
2494 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2496 return result;
2499 /****************************************************************************
2500 ****************************************************************************/
2502 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2503 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2505 PRINTER_INFO_CTR ctr1, ctr2;
2506 WERROR werror;
2507 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2509 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2510 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2511 if ( !W_ERROR_IS_OK(werror) ) {
2512 printf("failed (%s)\n", dos_errstr(werror));
2513 talloc_destroy(mem_ctx);
2514 return False;
2516 printf("ok\n");
2518 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2519 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2520 if ( !W_ERROR_IS_OK(werror) ) {
2521 printf("failed (%s)\n", dos_errstr(werror));
2522 talloc_destroy(mem_ctx);
2523 return False;
2525 printf("ok\n");
2527 talloc_destroy(mem_ctx);
2529 return True;
2532 /****************************************************************************
2533 ****************************************************************************/
2535 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2536 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2538 PRINTER_INFO_CTR ctr1, ctr2;
2539 WERROR werror;
2540 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2541 SEC_DESC *sd1, *sd2;
2542 BOOL result = True;
2545 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2546 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2547 if ( !W_ERROR_IS_OK(werror) ) {
2548 printf("failed (%s)\n", dos_errstr(werror));
2549 result = False;
2550 goto done;
2552 printf("ok\n");
2554 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2555 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2556 if ( !W_ERROR_IS_OK(werror) ) {
2557 printf("failed (%s)\n", dos_errstr(werror));
2558 result = False;
2559 goto done;
2561 printf("ok\n");
2564 printf("++ ");
2566 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2567 printf("NULL PRINTER_INFO_3!\n");
2568 result = False;
2569 goto done;
2572 sd1 = ctr1.printers_3->secdesc;
2573 sd2 = ctr2.printers_3->secdesc;
2575 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2576 printf("NULL secdesc!\n");
2577 result = False;
2578 goto done;
2581 if ( (ctr1.printers_3->flags != ctr1.printers_3->flags ) || !sec_desc_equal( sd1, sd2 ) ) {
2582 printf("Security Descriptors *not* equal!\n");
2583 result = False;
2584 goto done;
2587 printf("Security descriptors match\n");
2589 done:
2590 talloc_destroy(mem_ctx);
2591 return result;
2595 /****************************************************************************
2596 ****************************************************************************/
2598 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2599 TALLOC_CTX *mem_ctx, int argc,
2600 const char **argv)
2602 fstring printername, servername1, servername2;
2603 pstring printername_path;
2604 struct cli_state *cli_server1 = cli->cli;
2605 struct cli_state *cli_server2 = NULL;
2606 struct rpc_pipe_client *cli2 = NULL;
2607 POLICY_HND hPrinter1, hPrinter2;
2608 NTSTATUS nt_status;
2609 WERROR werror;
2611 if ( argc != 3 ) {
2612 printf("Usage: %s <printer> <server>\n", argv[0]);
2613 return WERR_OK;
2616 fstrcpy( printername, argv[1] );
2618 fstr_sprintf( servername1, cli->cli->desthost );
2619 fstrcpy( servername2, argv[2] );
2620 strupper_m( servername1 );
2621 strupper_m( servername2 );
2624 /* first get the connection to the remote server */
2626 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2627 NULL, 0,
2628 "IPC$", "IPC",
2629 cmdline_auth_info.username,
2630 lp_workgroup(),
2631 cmdline_auth_info.password,
2632 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2633 cmdline_auth_info.signing_state, NULL);
2635 if ( !NT_STATUS_IS_OK(nt_status) )
2636 return WERR_GENERAL_FAILURE;
2638 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2639 if (!cli2) {
2640 printf("failed to open spoolss pipe on server %s (%s)\n",
2641 servername2, nt_errstr(nt_status));
2642 return WERR_GENERAL_FAILURE;
2645 /* now open up both printers */
2647 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2648 printf("Opening %s...", printername_path);
2649 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2650 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2651 if ( !W_ERROR_IS_OK(werror) ) {
2652 printf("failed (%s)\n", dos_errstr(werror));
2653 goto done;
2655 printf("ok\n");
2657 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2658 printf("Opening %s...", printername_path);
2659 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2660 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2661 if ( !W_ERROR_IS_OK(werror) ) {
2662 printf("failed (%s)\n", dos_errstr(werror));
2663 goto done;
2665 printf("ok\n");
2668 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2669 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2670 #if 0
2671 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2672 #endif
2675 done:
2676 /* cleanup */
2678 printf("Closing printers...");
2679 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2680 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2681 printf("ok\n");
2683 /* close the second remote connection */
2685 cli_shutdown( cli_server2 );
2687 return WERR_OK;
2690 /* List of commands exported by this module */
2691 struct cmd_set spoolss_commands[] = {
2693 { "SPOOLSS" },
2695 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2696 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2697 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2698 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2699 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2700 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2701 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2702 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2703 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2704 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2705 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2706 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2707 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2708 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2709 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2710 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2711 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2712 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2713 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2714 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2715 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2716 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2717 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2718 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2719 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2720 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2721 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2722 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2723 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },
2725 { NULL }