[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / rpcclient / cmd_spoolss.c
blob41e27c16822ec0393802dd4a270dfce883e2d5db
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "rpcclient.h"
28 struct table_node {
29 const char *long_archi;
30 const char *short_archi;
31 int version;
34 /* The version int is used by getdrivers. Note that
35 all architecture strings that support mutliple
36 versions must be grouped together since enumdrivers
37 uses this property to prevent issuing multiple
38 enumdriver calls for the same arch */
41 static const struct table_node archi_table[]= {
43 {"Windows 4.0", "WIN40", 0 },
44 {"Windows NT x86", "W32X86", 2 },
45 {"Windows NT x86", "W32X86", 3 },
46 {"Windows NT R4000", "W32MIPS", 2 },
47 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
48 {"Windows NT PowerPC", "W32PPC", 2 },
49 {"Windows IA64", "IA64", 3 },
50 {"Windows x64", "x64", 3 },
51 {NULL, "", -1 }
54 /**
55 * @file
57 * rpcclient module for SPOOLSS rpc pipe.
59 * This generally just parses and checks command lines, and then calls
60 * a cli_spoolss function.
61 **/
63 /****************************************************************************
64 function to do the mapping between the long architecture name and
65 the short one.
66 ****************************************************************************/
68 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
70 int i=-1;
72 DEBUG(107,("Getting architecture dependant directory\n"));
73 do {
74 i++;
75 } while ( (archi_table[i].long_archi!=NULL ) &&
76 StrCaseCmp(long_archi, archi_table[i].long_archi) );
78 if (archi_table[i].long_archi==NULL) {
79 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
80 return NULL;
83 /* this might be client code - but shouldn't this be an fstrcpy etc? */
86 DEBUGADD(108,("index: [%d]\n", i));
87 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
88 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
90 return archi_table[i].short_archi;
93 /****************************************************************************
94 ****************************************************************************/
96 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
97 TALLOC_CTX *mem_ctx,
98 int argc, const char **argv)
100 WERROR werror;
101 fstring printername;
102 fstring servername, user;
103 POLICY_HND hnd;
105 if (argc != 2) {
106 printf("Usage: %s <printername>\n", argv[0]);
107 return WERR_OK;
110 if (!cli)
111 return WERR_GENERAL_FAILURE;
113 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
114 strupper_m(servername);
115 fstrcpy(user, cli->user_name);
116 fstrcpy(printername, argv[1]);
118 /* Open the printer handle */
120 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
121 "", PRINTER_ALL_ACCESS,
122 servername, user, &hnd);
124 if (W_ERROR_IS_OK(werror)) {
125 printf("Printer %s opened successfully\n", printername);
126 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
128 if (!W_ERROR_IS_OK(werror)) {
129 printf("Error closing printer handle! (%s)\n",
130 get_dos_error_msg(werror));
134 return werror;
138 /****************************************************************************
139 ****************************************************************************/
141 static void display_print_info_0(PRINTER_INFO_0 *i0)
143 fstring name = "";
144 fstring servername = "";
146 if (!i0)
147 return;
149 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
151 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
153 printf("\tprintername:[%s]\n", name);
154 printf("\tservername:[%s]\n", servername);
155 printf("\tcjobs:[0x%x]\n", i0->cjobs);
156 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
158 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
159 i0->day, i0->dayofweek);
160 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
161 i0->second, i0->milliseconds);
163 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
164 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
166 printf("\tmajorversion:[0x%x]\n", i0->major_version);
167 printf("\tbuildversion:[0x%x]\n", i0->build_version);
169 printf("\tunknown7:[0x%x]\n", i0->unknown7);
170 printf("\tunknown8:[0x%x]\n", i0->unknown8);
171 printf("\tunknown9:[0x%x]\n", i0->unknown9);
172 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
173 printf("\tunknown11:[0x%x]\n", i0->unknown11);
174 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
175 printf("\tunknown13:[0x%x]\n", i0->unknown13);
176 printf("\tunknown14:[0x%x]\n", i0->unknown14);
177 printf("\tunknown15:[0x%x]\n", i0->unknown15);
178 printf("\tunknown16:[0x%x]\n", i0->unknown16);
179 printf("\tchange_id:[0x%x]\n", i0->change_id);
180 printf("\tunknown18:[0x%x]\n", i0->unknown18);
181 printf("\tstatus:[0x%x]\n", i0->status);
182 printf("\tunknown20:[0x%x]\n", i0->unknown20);
183 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
184 printf("\tunknown22:[0x%x]\n", i0->unknown22);
185 printf("\tunknown23:[0x%x]\n", i0->unknown23);
186 printf("\tunknown24:[0x%x]\n", i0->unknown24);
187 printf("\tunknown25:[0x%x]\n", i0->unknown25);
188 printf("\tunknown26:[0x%x]\n", i0->unknown26);
189 printf("\tunknown27:[0x%x]\n", i0->unknown27);
190 printf("\tunknown28:[0x%x]\n", i0->unknown28);
191 printf("\tunknown29:[0x%x]\n", i0->unknown29);
193 printf("\n");
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info_1(PRINTER_INFO_1 *i1)
201 fstring desc = "";
202 fstring name = "";
203 fstring comm = "";
205 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
206 STR_TERMINATE);
208 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
209 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
211 printf("\tflags:[0x%x]\n", i1->flags);
212 printf("\tname:[%s]\n", name);
213 printf("\tdescription:[%s]\n", desc);
214 printf("\tcomment:[%s]\n", comm);
216 printf("\n");
219 /****************************************************************************
220 ****************************************************************************/
222 static void display_print_info_2(PRINTER_INFO_2 *i2)
224 fstring servername = "";
225 fstring printername = "";
226 fstring sharename = "";
227 fstring portname = "";
228 fstring drivername = "";
229 fstring comment = "";
230 fstring location = "";
231 fstring sepfile = "";
232 fstring printprocessor = "";
233 fstring datatype = "";
234 fstring parameters = "";
236 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
237 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
238 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
239 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
240 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
241 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
242 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
243 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
244 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
245 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
246 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
248 printf("\tservername:[%s]\n", servername);
249 printf("\tprintername:[%s]\n", printername);
250 printf("\tsharename:[%s]\n", sharename);
251 printf("\tportname:[%s]\n", portname);
252 printf("\tdrivername:[%s]\n", drivername);
253 printf("\tcomment:[%s]\n", comment);
254 printf("\tlocation:[%s]\n", location);
255 printf("\tsepfile:[%s]\n", sepfile);
256 printf("\tprintprocessor:[%s]\n", printprocessor);
257 printf("\tdatatype:[%s]\n", datatype);
258 printf("\tparameters:[%s]\n", parameters);
259 printf("\tattributes:[0x%x]\n", i2->attributes);
260 printf("\tpriority:[0x%x]\n", i2->priority);
261 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
262 printf("\tstarttime:[0x%x]\n", i2->starttime);
263 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
264 printf("\tstatus:[0x%x]\n", i2->status);
265 printf("\tcjobs:[0x%x]\n", i2->cjobs);
266 printf("\taverageppm:[0x%x]\n", i2->averageppm);
268 if (i2->secdesc)
269 display_sec_desc(i2->secdesc);
271 printf("\n");
274 /****************************************************************************
275 ****************************************************************************/
277 static void display_print_info_3(PRINTER_INFO_3 *i3)
279 display_sec_desc(i3->secdesc);
281 printf("\n");
284 /****************************************************************************
285 ****************************************************************************/
287 static void display_print_info_7(PRINTER_INFO_7 *i7)
289 fstring guid = "";
290 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
291 printf("\tguid:[%s]\n", guid);
292 printf("\taction:[0x%x]\n", i7->action);
296 /****************************************************************************
297 ****************************************************************************/
299 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
300 TALLOC_CTX *mem_ctx,
301 int argc, const char **argv)
303 WERROR result;
304 uint32 info_level = 1;
305 PRINTER_INFO_CTR ctr;
306 uint32 i = 0, num_printers;
307 fstring name;
309 if (argc > 3)
311 printf("Usage: %s [level] [name]\n", argv[0]);
312 return WERR_OK;
315 if (argc >= 2)
316 info_level = atoi(argv[1]);
318 if (argc == 3)
319 fstrcpy(name, argv[2]);
320 else {
321 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
322 strupper_m(name);
325 ZERO_STRUCT(ctr);
327 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
328 info_level, &num_printers, &ctr);
330 if (W_ERROR_IS_OK(result)) {
332 if (!num_printers) {
333 printf ("No printers returned.\n");
334 goto done;
337 for (i = 0; i < num_printers; i++) {
338 switch(info_level) {
339 case 0:
340 display_print_info_0(&ctr.printers_0[i]);
341 break;
342 case 1:
343 display_print_info_1(&ctr.printers_1[i]);
344 break;
345 case 2:
346 display_print_info_2(&ctr.printers_2[i]);
347 break;
348 case 3:
349 display_print_info_3(&ctr.printers_3[i]);
350 break;
351 default:
352 printf("unknown info level %d\n", info_level);
353 goto done;
357 done:
359 return result;
362 /****************************************************************************
363 ****************************************************************************/
365 static void display_port_info_1(PORT_INFO_1 *i1)
367 fstring buffer;
369 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
370 printf("\tPort Name:\t[%s]\n", buffer);
373 /****************************************************************************
374 ****************************************************************************/
376 static void display_port_info_2(PORT_INFO_2 *i2)
378 fstring buffer;
380 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
381 printf("\tPort Name:\t[%s]\n", buffer);
382 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
384 printf("\tMonitor Name:\t[%s]\n", buffer);
385 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
387 printf("\tDescription:\t[%s]\n", buffer);
388 printf("\tPort Type:\t" );
389 if ( i2->port_type ) {
390 int comma = 0; /* hack */
391 printf( "[" );
392 if ( i2->port_type & PORT_TYPE_READ ) {
393 printf( "Read" );
394 comma = 1;
396 if ( i2->port_type & PORT_TYPE_WRITE ) {
397 printf( "%sWrite", comma ? ", " : "" );
398 comma = 1;
400 /* These two have slightly different interpretations
401 on 95/98/ME but I'm disregarding that for now */
402 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
403 printf( "%sRedirected", comma ? ", " : "" );
404 comma = 1;
406 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
407 printf( "%sNet-Attached", comma ? ", " : "" );
409 printf( "]\n" );
410 } else {
411 printf( "[Unset]\n" );
413 printf("\tReserved:\t[%d]\n", i2->reserved);
414 printf("\n");
417 /****************************************************************************
418 ****************************************************************************/
420 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
421 TALLOC_CTX *mem_ctx, int argc,
422 const char **argv)
424 WERROR result;
425 uint32 info_level = 1;
426 PORT_INFO_CTR ctr;
427 uint32 returned;
429 if (argc > 2) {
430 printf("Usage: %s [level]\n", argv[0]);
431 return WERR_OK;
434 if (argc == 2)
435 info_level = atoi(argv[1]);
437 /* Enumerate ports */
439 ZERO_STRUCT(ctr);
441 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
443 if (W_ERROR_IS_OK(result)) {
444 int i;
446 for (i = 0; i < returned; i++) {
447 switch (info_level) {
448 case 1:
449 display_port_info_1(&ctr.port.info_1[i]);
450 break;
451 case 2:
452 display_port_info_2(&ctr.port.info_2[i]);
453 break;
454 default:
455 printf("unknown info level %d\n", info_level);
456 break;
461 return result;
464 /****************************************************************************
465 ****************************************************************************/
467 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
468 TALLOC_CTX *mem_ctx,
469 int argc, const char **argv)
471 POLICY_HND pol;
472 WERROR result;
473 uint32 info_level = 2;
474 BOOL opened_hnd = False;
475 PRINTER_INFO_CTR ctr;
476 fstring printername,
477 servername,
478 user,
479 comment;
481 if (argc == 1 || argc > 3) {
482 printf("Usage: %s printername comment\n", argv[0]);
484 return WERR_OK;
487 /* Open a printer handle */
488 if (argc == 3) {
489 fstrcpy(comment, argv[2]);
492 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
493 strupper_m(servername);
494 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
495 fstrcpy(user, cli->user_name);
497 /* get a printer handle */
498 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
499 PRINTER_ALL_ACCESS, servername,
500 user, &pol);
502 if (!W_ERROR_IS_OK(result))
503 goto done;
505 opened_hnd = True;
507 /* Get printer info */
508 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
510 if (!W_ERROR_IS_OK(result))
511 goto done;
514 /* Modify the comment. */
515 init_unistr(&ctr.printers_2->comment, comment);
516 ctr.printers_2->devmode = NULL;
517 ctr.printers_2->secdesc = NULL;
519 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
520 if (W_ERROR_IS_OK(result))
521 printf("Success in setting comment.\n");
523 done:
524 if (opened_hnd)
525 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
527 return result;
530 /****************************************************************************
531 ****************************************************************************/
533 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
534 TALLOC_CTX *mem_ctx,
535 int argc, const char **argv)
537 POLICY_HND pol;
538 WERROR result;
539 uint32 info_level = 2;
540 BOOL opened_hnd = False;
541 PRINTER_INFO_CTR ctr;
542 fstring printername,
543 servername,
544 user,
545 new_printername;
547 if (argc == 1 || argc > 3) {
548 printf("Usage: %s printername new_printername\n", argv[0]);
550 return WERR_OK;
553 /* Open a printer handle */
554 if (argc == 3) {
555 fstrcpy(new_printername, argv[2]);
558 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
559 strupper_m(servername);
560 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
561 fstrcpy(user, cli->user_name);
563 /* get a printer handle */
564 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
565 PRINTER_ALL_ACCESS, servername,
566 user, &pol);
568 if (!W_ERROR_IS_OK(result))
569 goto done;
571 opened_hnd = True;
573 /* Get printer info */
574 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
576 if (!W_ERROR_IS_OK(result))
577 goto done;
579 /* Modify the printername. */
580 init_unistr(&ctr.printers_2->printername, new_printername);
581 ctr.printers_2->devmode = NULL;
582 ctr.printers_2->secdesc = NULL;
584 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
585 if (W_ERROR_IS_OK(result))
586 printf("Success in setting printername.\n");
588 done:
589 if (opened_hnd)
590 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
592 return result;
595 /****************************************************************************
596 ****************************************************************************/
598 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
599 TALLOC_CTX *mem_ctx,
600 int argc, const char **argv)
602 POLICY_HND pol;
603 WERROR result;
604 uint32 info_level = 1;
605 BOOL opened_hnd = False;
606 PRINTER_INFO_CTR ctr;
607 fstring printername,
608 servername,
609 user;
611 if (argc == 1 || argc > 3) {
612 printf("Usage: %s <printername> [level]\n", argv[0]);
613 return WERR_OK;
616 /* Open a printer handle */
617 if (argc == 3) {
618 info_level = atoi(argv[2]);
621 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
622 strupper_m(servername);
623 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
624 fstrcpy(user, cli->user_name);
626 /* get a printer handle */
628 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
629 "", MAXIMUM_ALLOWED_ACCESS,
630 servername, user, &pol);
632 if (!W_ERROR_IS_OK(result))
633 goto done;
635 opened_hnd = True;
637 /* Get printer info */
639 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
641 if (!W_ERROR_IS_OK(result))
642 goto done;
644 /* Display printer info */
646 switch (info_level) {
647 case 0:
648 display_print_info_0(ctr.printers_0);
649 break;
650 case 1:
651 display_print_info_1(ctr.printers_1);
652 break;
653 case 2:
654 display_print_info_2(ctr.printers_2);
655 break;
656 case 3:
657 display_print_info_3(ctr.printers_3);
658 break;
659 case 7:
660 display_print_info_7(ctr.printers_7);
661 break;
662 default:
663 printf("unknown info level %d\n", info_level);
664 break;
667 done:
668 if (opened_hnd)
669 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
671 return result;
674 /****************************************************************************
675 ****************************************************************************/
677 static void display_reg_value(REGISTRY_VALUE value)
679 pstring text;
681 switch(value.type) {
682 case REG_DWORD:
683 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
684 *((uint32 *) value.data_p));
685 break;
686 case REG_SZ:
687 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
688 STR_TERMINATE);
689 printf("%s: REG_SZ: %s\n", value.valuename, text);
690 break;
691 case REG_BINARY: {
692 char *hex = hex_encode(NULL, value.data_p, value.size);
693 size_t i, len;
694 printf("%s: REG_BINARY:", value.valuename);
695 len = strlen(hex);
696 for (i=0; i<len; i++) {
697 if (hex[i] == '\0') {
698 break;
700 if (i%40 == 0) {
701 putchar('\n');
703 putchar(hex[i]);
705 TALLOC_FREE(hex);
706 putchar('\n');
707 break;
709 case REG_MULTI_SZ: {
710 uint16 *curstr = (uint16 *) value.data_p;
711 uint8 *start = value.data_p;
712 printf("%s: REG_MULTI_SZ:\n", value.valuename);
713 while (((uint8 *) curstr < start + value.size)) {
714 rpcstr_pull(text, curstr, sizeof(text), -1,
715 STR_TERMINATE);
716 printf(" %s\n", *text != 0 ? text : "NULL");
717 curstr += strlen(text) + 1;
720 break;
721 default:
722 printf("%s: unknown type %d\n", value.valuename, value.type);
727 /****************************************************************************
728 ****************************************************************************/
730 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
731 TALLOC_CTX *mem_ctx,
732 int argc, const char **argv)
734 POLICY_HND pol;
735 WERROR result;
736 BOOL opened_hnd = False;
737 fstring printername,
738 servername,
739 user;
740 const char *valuename;
741 REGISTRY_VALUE value;
743 if (argc != 3) {
744 printf("Usage: %s <printername> <valuename>\n", argv[0]);
745 printf("<printername> of . queries print server\n");
746 return WERR_OK;
748 valuename = argv[2];
750 /* Open a printer handle */
752 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
753 strupper_m(servername);
754 if (strncmp(argv[1], ".", sizeof(".")) == 0)
755 fstrcpy(printername, servername);
756 else
757 slprintf(printername, sizeof(servername)-1, "%s\\%s",
758 servername, argv[1]);
759 fstrcpy(user, cli->user_name);
761 /* get a printer handle */
763 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
764 "", MAXIMUM_ALLOWED_ACCESS,
765 servername, user, &pol);
767 if (!W_ERROR_IS_OK(result))
768 goto done;
770 opened_hnd = True;
772 /* Get printer info */
774 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
776 if (!W_ERROR_IS_OK(result))
777 goto done;
779 /* Display printer data */
781 fstrcpy(value.valuename, valuename);
782 display_reg_value(value);
785 done:
786 if (opened_hnd)
787 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
789 return result;
792 /****************************************************************************
793 ****************************************************************************/
795 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
796 TALLOC_CTX *mem_ctx,
797 int argc, const char **argv)
799 POLICY_HND pol;
800 WERROR result;
801 BOOL opened_hnd = False;
802 fstring printername,
803 servername,
804 user;
805 const char *valuename, *keyname;
806 REGISTRY_VALUE value;
808 if (argc != 4) {
809 printf("Usage: %s <printername> <keyname> <valuename>\n",
810 argv[0]);
811 printf("<printername> of . queries print server\n");
812 return WERR_OK;
814 valuename = argv[3];
815 keyname = argv[2];
817 /* Open a printer handle */
819 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
820 strupper_m(servername);
821 if (strncmp(argv[1], ".", sizeof(".")) == 0)
822 fstrcpy(printername, servername);
823 else
824 slprintf(printername, sizeof(printername)-1, "%s\\%s",
825 servername, argv[1]);
826 fstrcpy(user, cli->user_name);
828 /* get a printer handle */
830 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
831 "", MAXIMUM_ALLOWED_ACCESS,
832 servername, user, &pol);
834 if (!W_ERROR_IS_OK(result))
835 goto done;
837 opened_hnd = True;
839 /* Get printer info */
841 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
842 valuename, &value);
844 if (!W_ERROR_IS_OK(result))
845 goto done;
847 /* Display printer data */
849 fstrcpy(value.valuename, valuename);
850 display_reg_value(value);
853 done:
854 if (opened_hnd)
855 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
857 return result;
860 /****************************************************************************
861 ****************************************************************************/
863 static void display_print_driver_1(DRIVER_INFO_1 *i1)
865 fstring name;
866 if (i1 == NULL)
867 return;
869 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
871 printf ("Printer Driver Info 1:\n");
872 printf ("\tDriver Name: [%s]\n\n", name);
874 return;
877 /****************************************************************************
878 ****************************************************************************/
880 static void display_print_driver_2(DRIVER_INFO_2 *i1)
882 fstring name;
883 fstring architecture;
884 fstring driverpath;
885 fstring datafile;
886 fstring configfile;
887 if (i1 == NULL)
888 return;
890 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
891 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
892 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
893 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
894 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
896 printf ("Printer Driver Info 2:\n");
897 printf ("\tVersion: [%x]\n", i1->version);
898 printf ("\tDriver Name: [%s]\n", name);
899 printf ("\tArchitecture: [%s]\n", architecture);
900 printf ("\tDriver Path: [%s]\n", driverpath);
901 printf ("\tDatafile: [%s]\n", datafile);
902 printf ("\tConfigfile: [%s]\n\n", configfile);
904 return;
907 /****************************************************************************
908 ****************************************************************************/
910 static void display_print_driver_3(DRIVER_INFO_3 *i1)
912 fstring name = "";
913 fstring architecture = "";
914 fstring driverpath = "";
915 fstring datafile = "";
916 fstring configfile = "";
917 fstring helpfile = "";
918 fstring dependentfiles = "";
919 fstring monitorname = "";
920 fstring defaultdatatype = "";
922 int length=0;
923 BOOL valid = True;
925 if (i1 == NULL)
926 return;
928 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
929 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
930 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
931 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
932 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
933 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
934 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
935 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
937 printf ("Printer Driver Info 3:\n");
938 printf ("\tVersion: [%x]\n", i1->version);
939 printf ("\tDriver Name: [%s]\n",name);
940 printf ("\tArchitecture: [%s]\n", architecture);
941 printf ("\tDriver Path: [%s]\n", driverpath);
942 printf ("\tDatafile: [%s]\n", datafile);
943 printf ("\tConfigfile: [%s]\n", configfile);
944 printf ("\tHelpfile: [%s]\n\n", helpfile);
946 while (valid)
948 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
950 length+=strlen(dependentfiles)+1;
952 if (strlen(dependentfiles) > 0)
954 printf ("\tDependentfiles: [%s]\n", dependentfiles);
956 else
958 valid = False;
962 printf ("\n");
964 printf ("\tMonitorname: [%s]\n", monitorname);
965 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
967 return;
970 /****************************************************************************
971 ****************************************************************************/
973 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
974 TALLOC_CTX *mem_ctx,
975 int argc, const char **argv)
977 POLICY_HND pol;
978 WERROR werror;
979 uint32 info_level = 3;
980 BOOL opened_hnd = False;
981 PRINTER_DRIVER_CTR ctr;
982 fstring printername,
983 servername,
984 user;
985 uint32 i;
986 BOOL success = False;
988 if ((argc == 1) || (argc > 3))
990 printf("Usage: %s <printername> [level]\n", argv[0]);
991 return WERR_OK;
994 /* get the arguments need to open the printer handle */
995 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
996 strupper_m(servername);
997 fstrcpy(user, cli->user_name);
998 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
999 if (argc == 3)
1000 info_level = atoi(argv[2]);
1002 /* Open a printer handle */
1004 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1005 PRINTER_ACCESS_USE,
1006 servername, user, &pol);
1008 if (!W_ERROR_IS_OK(werror)) {
1009 printf("Error opening printer handle for %s!\n", printername);
1010 return werror;
1013 opened_hnd = True;
1015 /* loop through and print driver info level for each architecture */
1017 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1019 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1020 archi_table[i].long_archi, archi_table[i].version,
1021 &ctr);
1023 if (!W_ERROR_IS_OK(werror))
1024 continue;
1026 /* need at least one success */
1028 success = True;
1030 printf ("\n[%s]\n", archi_table[i].long_archi);
1032 switch (info_level) {
1033 case 1:
1034 display_print_driver_1 (ctr.info1);
1035 break;
1036 case 2:
1037 display_print_driver_2 (ctr.info2);
1038 break;
1039 case 3:
1040 display_print_driver_3 (ctr.info3);
1041 break;
1042 default:
1043 printf("unknown info level %d\n", info_level);
1044 break;
1048 /* Cleanup */
1050 if (opened_hnd)
1051 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1053 if ( success )
1054 werror = WERR_OK;
1056 return werror;
1059 /****************************************************************************
1060 ****************************************************************************/
1062 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1063 TALLOC_CTX *mem_ctx,
1064 int argc, const char **argv)
1066 WERROR werror = WERR_OK;
1067 uint32 info_level = 1;
1068 PRINTER_DRIVER_CTR ctr;
1069 uint32 i, j,
1070 returned;
1072 if (argc > 2) {
1073 printf("Usage: enumdrivers [level]\n");
1074 return WERR_OK;
1077 if (argc == 2)
1078 info_level = atoi(argv[1]);
1081 /* loop through and print driver info level for each architecture */
1082 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1083 /* check to see if we already asked for this architecture string */
1085 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1086 continue;
1088 werror = rpccli_spoolss_enumprinterdrivers(
1089 cli, mem_ctx, info_level,
1090 archi_table[i].long_archi, &returned, &ctr);
1092 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1093 printf ("Server does not support environment [%s]\n",
1094 archi_table[i].long_archi);
1095 werror = WERR_OK;
1096 continue;
1099 if (returned == 0)
1100 continue;
1102 if (!W_ERROR_IS_OK(werror)) {
1103 printf ("Error getting driver for environment [%s] - %d\n",
1104 archi_table[i].long_archi, W_ERROR_V(werror));
1105 continue;
1108 printf ("\n[%s]\n", archi_table[i].long_archi);
1109 switch (info_level)
1112 case 1:
1113 for (j=0; j < returned; j++) {
1114 display_print_driver_1 (&ctr.info1[j]);
1116 break;
1117 case 2:
1118 for (j=0; j < returned; j++) {
1119 display_print_driver_2 (&ctr.info2[j]);
1121 break;
1122 case 3:
1123 for (j=0; j < returned; j++) {
1124 display_print_driver_3 (&ctr.info3[j]);
1126 break;
1127 default:
1128 printf("unknown info level %d\n", info_level);
1129 return WERR_UNKNOWN_LEVEL;
1133 return werror;
1136 /****************************************************************************
1137 ****************************************************************************/
1139 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1141 fstring name;
1142 if (i1 == NULL)
1143 return;
1145 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1147 printf ("\tDirectory Name:[%s]\n", name);
1150 /****************************************************************************
1151 ****************************************************************************/
1153 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1154 TALLOC_CTX *mem_ctx,
1155 int argc, const char **argv)
1157 WERROR result;
1158 fstring env;
1159 DRIVER_DIRECTORY_CTR ctr;
1161 if (argc > 2) {
1162 printf("Usage: %s [environment]\n", argv[0]);
1163 return WERR_OK;
1166 /* Get the arguments need to open the printer handle */
1168 if (argc == 2)
1169 fstrcpy (env, argv[1]);
1170 else
1171 fstrcpy (env, "Windows NT x86");
1173 /* Get the directory. Only use Info level 1 */
1175 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1177 if (W_ERROR_IS_OK(result))
1178 display_printdriverdir_1(ctr.info1);
1180 return result;
1183 /****************************************************************************
1184 ****************************************************************************/
1186 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1189 int i;
1191 for (i=0; archi_table[i].long_archi != NULL; i++)
1193 if (strcmp(arch, archi_table[i].short_archi) == 0)
1195 info->version = archi_table[i].version;
1196 init_unistr (&info->architecture, archi_table[i].long_archi);
1197 break;
1201 if (archi_table[i].long_archi == NULL)
1203 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1206 return;
1210 /**************************************************************************
1211 wrapper for strtok to get the next parameter from a delimited list.
1212 Needed to handle the empty parameter string denoted by "NULL"
1213 *************************************************************************/
1215 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1217 char *ptr;
1219 /* get the next token */
1220 ptr = strtok(str, delim);
1222 /* a string of 'NULL' is used to represent an empty
1223 parameter because two consecutive delimiters
1224 will not return an empty string. See man strtok(3)
1225 for details */
1226 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1227 ptr = NULL;
1229 if (dest != NULL)
1230 init_unistr(dest, ptr);
1232 return ptr;
1235 /********************************************************************************
1236 fill in the members of a DRIVER_INFO_3 struct using a character
1237 string in the form of
1238 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1239 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1240 <Default Data Type>:<Comma Separated list of Files>
1241 *******************************************************************************/
1242 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1243 char *args )
1245 char *str, *str2;
1246 uint32 len, i;
1248 /* fill in the UNISTR fields */
1249 str = get_driver_3_param (args, ":", &info->name);
1250 str = get_driver_3_param (NULL, ":", &info->driverpath);
1251 str = get_driver_3_param (NULL, ":", &info->datafile);
1252 str = get_driver_3_param (NULL, ":", &info->configfile);
1253 str = get_driver_3_param (NULL, ":", &info->helpfile);
1254 str = get_driver_3_param (NULL, ":", &info->monitorname);
1255 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1257 /* <Comma Separated List of Dependent Files> */
1258 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1259 str = str2;
1261 /* begin to strip out each filename */
1262 str = strtok(str, ",");
1263 len = 0;
1264 while (str != NULL)
1266 /* keep a cumlative count of the str lengths */
1267 len += strlen(str)+1;
1268 str = strtok(NULL, ",");
1271 /* allocate the space; add one extra slot for a terminating NULL.
1272 Each filename is NULL terminated and the end contains a double
1273 NULL */
1274 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1276 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1277 return False;
1279 for (i=0; i<len; i++)
1281 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1283 info->dependentfiles[len] = '\0';
1285 return True;
1289 /****************************************************************************
1290 ****************************************************************************/
1292 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1293 TALLOC_CTX *mem_ctx,
1294 int argc, const char **argv)
1296 WERROR result;
1297 uint32 level = 3;
1298 PRINTER_DRIVER_CTR ctr;
1299 DRIVER_INFO_3 info3;
1300 const char *arch;
1301 fstring driver_name;
1302 char *driver_args;
1304 /* parse the command arguements */
1305 if (argc != 3 && argc != 4)
1307 printf ("Usage: %s <Environment> \\\n", argv[0]);
1308 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1309 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1310 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1311 printf ("\t[version]\n");
1313 return WERR_OK;
1316 /* Fill in the DRIVER_INFO_3 struct */
1317 ZERO_STRUCT(info3);
1318 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1320 printf ("Error Unknown architechture [%s]\n", argv[1]);
1321 return WERR_INVALID_PARAM;
1323 else
1324 set_drv_info_3_env(&info3, arch);
1326 driver_args = talloc_strdup( mem_ctx, argv[2] );
1327 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1329 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1330 return WERR_INVALID_PARAM;
1333 /* if printer driver version specified, override the default version
1334 * used by the architecture. This allows installation of Windows
1335 * 2000 (version 3) printer drivers. */
1336 if (argc == 4)
1338 info3.version = atoi(argv[3]);
1342 ctr.info3 = &info3;
1343 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1345 if (W_ERROR_IS_OK(result)) {
1346 rpcstr_pull(driver_name, info3.name.buffer,
1347 sizeof(driver_name), -1, STR_TERMINATE);
1348 printf ("Printer Driver %s successfully installed.\n",
1349 driver_name);
1352 return result;
1356 /****************************************************************************
1357 ****************************************************************************/
1359 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1360 TALLOC_CTX *mem_ctx,
1361 int argc, const char **argv)
1363 WERROR result;
1364 uint32 level = 2;
1365 PRINTER_INFO_CTR ctr;
1366 PRINTER_INFO_2 info2;
1367 fstring servername;
1369 /* parse the command arguements */
1370 if (argc != 5)
1372 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1373 return WERR_OK;
1376 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1377 strupper_m(servername);
1379 /* Fill in the DRIVER_INFO_2 struct */
1380 ZERO_STRUCT(info2);
1382 init_unistr( &info2.printername, argv[1]);
1383 init_unistr( &info2.sharename, argv[2]);
1384 init_unistr( &info2.drivername, argv[3]);
1385 init_unistr( &info2.portname, argv[4]);
1386 init_unistr( &info2.comment, "Created by rpcclient");
1387 init_unistr( &info2.printprocessor, "winprint");
1388 init_unistr( &info2.datatype, "RAW");
1389 info2.devmode = NULL;
1390 info2.secdesc = NULL;
1391 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1392 info2.priority = 0;
1393 info2.defaultpriority = 0;
1394 info2.starttime = 0;
1395 info2.untiltime = 0;
1397 /* These three fields must not be used by AddPrinter()
1398 as defined in the MS Platform SDK documentation..
1399 --jerry
1400 info2.status = 0;
1401 info2.cjobs = 0;
1402 info2.averageppm = 0;
1405 ctr.printers_2 = &info2;
1406 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1408 if (W_ERROR_IS_OK(result))
1409 printf ("Printer %s successfully installed.\n", argv[1]);
1411 return result;
1414 /****************************************************************************
1415 ****************************************************************************/
1417 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1418 TALLOC_CTX *mem_ctx,
1419 int argc, const char **argv)
1421 POLICY_HND pol;
1422 WERROR result;
1423 uint32 level = 2;
1424 BOOL opened_hnd = False;
1425 PRINTER_INFO_CTR ctr;
1426 PRINTER_INFO_2 info2;
1427 fstring servername,
1428 printername,
1429 user;
1431 /* parse the command arguements */
1432 if (argc != 3)
1434 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1435 return WERR_OK;
1438 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1439 strupper_m(servername);
1440 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1441 fstrcpy(user, cli->user_name);
1443 /* Get a printer handle */
1445 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1446 PRINTER_ALL_ACCESS,
1447 servername, user, &pol);
1449 if (!W_ERROR_IS_OK(result))
1450 goto done;
1452 opened_hnd = True;
1454 /* Get printer info */
1456 ZERO_STRUCT (info2);
1457 ctr.printers_2 = &info2;
1459 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1461 if (!W_ERROR_IS_OK(result)) {
1462 printf ("Unable to retrieve printer information!\n");
1463 goto done;
1466 /* Set the printer driver */
1468 init_unistr(&ctr.printers_2->drivername, argv[2]);
1470 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1472 if (!W_ERROR_IS_OK(result)) {
1473 printf("SetPrinter call failed!\n");
1474 goto done;;
1477 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1479 done:
1480 /* Cleanup */
1482 if (opened_hnd)
1483 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1485 return result;
1489 /****************************************************************************
1490 ****************************************************************************/
1492 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1493 TALLOC_CTX *mem_ctx,
1494 int argc, const char **argv)
1496 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1498 int i;
1499 int vers = -1;
1501 const char *arch = NULL;
1503 /* parse the command arguements */
1504 if (argc < 2 || argc > 4) {
1505 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1506 return WERR_OK;
1509 if (argc >= 3)
1510 arch = argv[2];
1511 if (argc == 4)
1512 vers = atoi (argv[3]);
1515 /* delete the driver for all architectures */
1516 for (i=0; archi_table[i].long_archi; i++) {
1518 if (arch && !strequal( archi_table[i].long_archi, arch))
1519 continue;
1521 if (vers >= 0 && archi_table[i].version != vers)
1522 continue;
1524 /* make the call to remove the driver */
1525 result = rpccli_spoolss_deleteprinterdriverex(
1526 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1528 if ( !W_ERROR_IS_OK(result) )
1530 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1531 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1532 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1535 else
1537 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1538 archi_table[i].long_archi, archi_table[i].version);
1539 ret = WERR_OK;
1543 return ret;
1547 /****************************************************************************
1548 ****************************************************************************/
1550 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1551 TALLOC_CTX *mem_ctx,
1552 int argc, const char **argv)
1554 WERROR result = WERR_OK;
1555 fstring servername;
1556 int i;
1558 /* parse the command arguements */
1559 if (argc != 2) {
1560 printf ("Usage: %s <driver>\n", argv[0]);
1561 return WERR_OK;
1564 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1565 strupper_m(servername);
1567 /* delete the driver for all architectures */
1568 for (i=0; archi_table[i].long_archi; i++) {
1569 /* make the call to remove the driver */
1570 result = rpccli_spoolss_deleteprinterdriver(
1571 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1573 if ( !W_ERROR_IS_OK(result) ) {
1574 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1575 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1576 argv[1], archi_table[i].long_archi,
1577 W_ERROR_V(result));
1579 } else {
1580 printf ("Driver %s removed for arch [%s].\n", argv[1],
1581 archi_table[i].long_archi);
1585 return result;
1588 /****************************************************************************
1589 ****************************************************************************/
1591 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1592 TALLOC_CTX *mem_ctx,
1593 int argc, const char **argv)
1595 WERROR result;
1596 char *servername = NULL, *environment = NULL;
1597 fstring procdir;
1599 /* parse the command arguements */
1600 if (argc > 2) {
1601 printf ("Usage: %s [environment]\n", argv[0]);
1602 return WERR_OK;
1605 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1606 return WERR_NOMEM;
1607 strupper_m(servername);
1609 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1610 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1611 SAFE_FREE(servername);
1612 return WERR_NOMEM;
1615 result = rpccli_spoolss_getprintprocessordirectory(
1616 cli, mem_ctx, servername, environment, procdir);
1618 if (W_ERROR_IS_OK(result))
1619 printf("%s\n", procdir);
1621 SAFE_FREE(servername);
1622 SAFE_FREE(environment);
1624 return result;
1627 /****************************************************************************
1628 ****************************************************************************/
1630 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1631 int argc, const char **argv)
1633 POLICY_HND handle;
1634 WERROR werror;
1635 char *servername = NULL, *printername = NULL;
1636 FORM form;
1637 BOOL got_handle = False;
1639 /* Parse the command arguements */
1641 if (argc != 3) {
1642 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1643 return WERR_OK;
1646 /* Get a printer handle */
1648 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1649 strupper_m(servername);
1650 asprintf(&printername, "%s\\%s", servername, argv[1]);
1652 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1653 PRINTER_ALL_ACCESS,
1654 servername, cli->user_name, &handle);
1656 if (!W_ERROR_IS_OK(werror))
1657 goto done;
1659 got_handle = True;
1661 /* Dummy up some values for the form data */
1663 form.flags = FORM_USER;
1664 form.size_x = form.size_y = 100;
1665 form.left = 0;
1666 form.top = 10;
1667 form.right = 20;
1668 form.bottom = 30;
1670 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1672 /* Add the form */
1675 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1677 done:
1678 if (got_handle)
1679 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1681 SAFE_FREE(servername);
1682 SAFE_FREE(printername);
1684 return werror;
1687 /****************************************************************************
1688 ****************************************************************************/
1690 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1691 int argc, const char **argv)
1693 POLICY_HND handle;
1694 WERROR werror;
1695 char *servername = NULL, *printername = NULL;
1696 FORM form;
1697 BOOL got_handle = False;
1699 /* Parse the command arguements */
1701 if (argc != 3) {
1702 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1703 return WERR_OK;
1706 /* Get a printer handle */
1708 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1709 strupper_m(servername);
1710 asprintf(&printername, "%s\\%s", servername, argv[1]);
1712 werror = rpccli_spoolss_open_printer_ex(
1713 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1714 servername, cli->user_name, &handle);
1716 if (!W_ERROR_IS_OK(werror))
1717 goto done;
1719 got_handle = True;
1721 /* Dummy up some values for the form data */
1723 form.flags = FORM_PRINTER;
1724 form.size_x = form.size_y = 100;
1725 form.left = 0;
1726 form.top = 1000;
1727 form.right = 2000;
1728 form.bottom = 3000;
1730 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1732 /* Set the form */
1734 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1736 done:
1737 if (got_handle)
1738 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1740 SAFE_FREE(servername);
1741 SAFE_FREE(printername);
1743 return werror;
1746 /****************************************************************************
1747 ****************************************************************************/
1749 static const char *get_form_flag(int form_flag)
1751 switch (form_flag) {
1752 case FORM_USER:
1753 return "FORM_USER";
1754 case FORM_BUILTIN:
1755 return "FORM_BUILTIN";
1756 case FORM_PRINTER:
1757 return "FORM_PRINTER";
1758 default:
1759 return "unknown";
1763 /****************************************************************************
1764 ****************************************************************************/
1766 static void display_form(FORM_1 *form)
1768 fstring form_name = "";
1770 if (form->name.buffer)
1771 rpcstr_pull(form_name, form->name.buffer,
1772 sizeof(form_name), -1, STR_TERMINATE);
1774 printf("%s\n" \
1775 "\tflag: %s (%d)\n" \
1776 "\twidth: %d, length: %d\n" \
1777 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1778 form_name, get_form_flag(form->flag), form->flag,
1779 form->width, form->length,
1780 form->left, form->right,
1781 form->top, form->bottom);
1784 /****************************************************************************
1785 ****************************************************************************/
1787 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1788 int argc, const char **argv)
1790 POLICY_HND handle;
1791 WERROR werror;
1792 char *servername = NULL, *printername = NULL;
1793 FORM_1 form;
1794 BOOL got_handle = False;
1796 /* Parse the command arguements */
1798 if (argc != 3) {
1799 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1800 return WERR_OK;
1803 /* Get a printer handle */
1805 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1806 strupper_m(servername);
1807 asprintf(&printername, "%s\\%s", servername, argv[1]);
1809 werror = rpccli_spoolss_open_printer_ex(
1810 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1811 servername, cli->user_name, &handle);
1813 if (!W_ERROR_IS_OK(werror))
1814 goto done;
1816 got_handle = True;
1818 /* Get the form */
1820 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1822 if (!W_ERROR_IS_OK(werror))
1823 goto done;
1825 display_form(&form);
1827 done:
1828 if (got_handle)
1829 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1831 SAFE_FREE(servername);
1832 SAFE_FREE(printername);
1834 return werror;
1837 /****************************************************************************
1838 ****************************************************************************/
1840 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1841 TALLOC_CTX *mem_ctx, int argc,
1842 const char **argv)
1844 POLICY_HND handle;
1845 WERROR werror;
1846 char *servername = NULL, *printername = NULL;
1847 BOOL got_handle = False;
1849 /* Parse the command arguements */
1851 if (argc != 3) {
1852 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1853 return WERR_OK;
1856 /* Get a printer handle */
1858 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1859 strupper_m(servername);
1860 asprintf(&printername, "%s\\%s", servername, argv[1]);
1862 werror = rpccli_spoolss_open_printer_ex(
1863 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1864 servername, cli->user_name, &handle);
1866 if (!W_ERROR_IS_OK(werror))
1867 goto done;
1869 got_handle = True;
1871 /* Delete the form */
1873 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1875 done:
1876 if (got_handle)
1877 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1879 SAFE_FREE(servername);
1880 SAFE_FREE(printername);
1882 return werror;
1885 /****************************************************************************
1886 ****************************************************************************/
1888 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1889 TALLOC_CTX *mem_ctx, int argc,
1890 const char **argv)
1892 POLICY_HND handle;
1893 WERROR werror;
1894 char *servername = NULL, *printername = NULL;
1895 BOOL got_handle = False;
1896 uint32 num_forms, level = 1, i;
1897 FORM_1 *forms;
1899 /* Parse the command arguements */
1901 if (argc != 2) {
1902 printf ("Usage: %s <printer>\n", argv[0]);
1903 return WERR_OK;
1906 /* Get a printer handle */
1908 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1909 strupper_m(servername);
1910 asprintf(&printername, "%s\\%s", servername, argv[1]);
1912 werror = rpccli_spoolss_open_printer_ex(
1913 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1914 servername, cli->user_name, &handle);
1916 if (!W_ERROR_IS_OK(werror))
1917 goto done;
1919 got_handle = True;
1921 /* Enumerate forms */
1923 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1925 if (!W_ERROR_IS_OK(werror))
1926 goto done;
1928 /* Display output */
1930 for (i = 0; i < num_forms; i++) {
1932 display_form(&forms[i]);
1936 done:
1937 if (got_handle)
1938 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1940 SAFE_FREE(servername);
1941 SAFE_FREE(printername);
1943 return werror;
1946 /****************************************************************************
1947 ****************************************************************************/
1949 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1950 TALLOC_CTX *mem_ctx,
1951 int argc, const char **argv)
1953 WERROR result;
1954 fstring servername, printername, user;
1955 POLICY_HND pol;
1956 BOOL opened_hnd = False;
1957 PRINTER_INFO_CTR ctr;
1958 PRINTER_INFO_0 info;
1959 REGISTRY_VALUE value;
1961 /* parse the command arguements */
1962 if (argc < 5) {
1963 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1964 " <value> <data>\n",
1965 argv[0]);
1966 return WERR_INVALID_PARAM;
1969 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1970 strupper_m(servername);
1971 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1972 fstrcpy(user, cli->user_name);
1974 value.type = REG_NONE;
1976 if (strequal(argv[2], "string")) {
1977 value.type = REG_SZ;
1980 if (strequal(argv[2], "binary")) {
1981 value.type = REG_BINARY;
1984 if (strequal(argv[2], "dword")) {
1985 value.type = REG_DWORD;
1988 if (strequal(argv[2], "multistring")) {
1989 value.type = REG_MULTI_SZ;
1992 if (value.type == REG_NONE) {
1993 printf("Unknown data type: %s\n", argv[2]);
1994 return WERR_INVALID_PARAM;
1997 /* get a printer handle */
1998 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1999 MAXIMUM_ALLOWED_ACCESS, servername,
2000 user, &pol);
2001 if (!W_ERROR_IS_OK(result))
2002 goto done;
2004 opened_hnd = True;
2006 ctr.printers_0 = &info;
2008 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2010 if (!W_ERROR_IS_OK(result))
2011 goto done;
2013 printf("%s\n", current_timestring(True));
2014 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2016 /* Set the printer data */
2018 fstrcpy(value.valuename, argv[3]);
2020 switch (value.type) {
2021 case REG_SZ: {
2022 UNISTR2 data;
2023 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2024 value.size = data.uni_str_len * 2;
2025 if (value.size) {
2026 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2027 value.size);
2028 } else {
2029 value.data_p = NULL;
2031 break;
2033 case REG_DWORD: {
2034 uint32 data = strtoul(argv[4], NULL, 10);
2035 value.size = sizeof(data);
2036 if (sizeof(data)) {
2037 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2038 sizeof(data));
2039 } else {
2040 value.data_p = NULL;
2042 break;
2044 case REG_BINARY: {
2045 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2046 value.data_p = data.data;
2047 value.size = data.length;
2048 break;
2050 case REG_MULTI_SZ: {
2051 int i;
2052 size_t len = 0;
2053 char *p;
2055 for (i=4; i<argc; i++) {
2056 if (strcmp(argv[i], "NULL") == 0) {
2057 argv[i] = "";
2059 len += strlen(argv[i])+1;
2062 value.size = len*2;
2063 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2064 if (value.data_p == NULL) {
2065 result = WERR_NOMEM;
2066 goto done;
2069 p = (char *)value.data_p;
2070 len = value.size;
2071 for (i=4; i<argc; i++) {
2072 size_t l = (strlen(argv[i])+1)*2;
2073 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2074 p += l;
2075 len -= l;
2077 SMB_ASSERT(len == 0);
2078 break;
2080 default:
2081 printf("Unknown data type: %s\n", argv[2]);
2082 result = WERR_INVALID_PARAM;
2083 goto done;
2086 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2088 if (!W_ERROR_IS_OK(result)) {
2089 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2090 goto done;
2092 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2094 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2096 if (!W_ERROR_IS_OK(result))
2097 goto done;
2099 printf("%s\n", current_timestring(True));
2100 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2102 done:
2103 /* cleanup */
2104 if (opened_hnd)
2105 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2107 return result;
2110 /****************************************************************************
2111 ****************************************************************************/
2113 static void display_job_info_1(JOB_INFO_1 *job)
2115 fstring username = "", document = "", text_status = "";
2117 rpcstr_pull(username, job->username.buffer,
2118 sizeof(username), -1, STR_TERMINATE);
2120 rpcstr_pull(document, job->document.buffer,
2121 sizeof(document), -1, STR_TERMINATE);
2123 rpcstr_pull(text_status, job->text_status.buffer,
2124 sizeof(text_status), -1, STR_TERMINATE);
2126 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2127 username, document, text_status, job->pagesprinted,
2128 job->totalpages);
2131 /****************************************************************************
2132 ****************************************************************************/
2134 static void display_job_info_2(JOB_INFO_2 *job)
2136 fstring username = "", document = "", text_status = "";
2138 rpcstr_pull(username, job->username.buffer,
2139 sizeof(username), -1, STR_TERMINATE);
2141 rpcstr_pull(document, job->document.buffer,
2142 sizeof(document), -1, STR_TERMINATE);
2144 rpcstr_pull(text_status, job->text_status.buffer,
2145 sizeof(text_status), -1, STR_TERMINATE);
2147 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2148 username, document, text_status, job->pagesprinted,
2149 job->totalpages, job->size);
2152 /****************************************************************************
2153 ****************************************************************************/
2155 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2156 TALLOC_CTX *mem_ctx, int argc,
2157 const char **argv)
2159 WERROR result;
2160 uint32 level = 1, num_jobs, i;
2161 BOOL got_hnd = False;
2162 pstring printername;
2163 fstring servername, user;
2164 POLICY_HND hnd;
2165 JOB_INFO_CTR ctr;
2167 if (argc < 2 || argc > 3) {
2168 printf("Usage: %s printername [level]\n", argv[0]);
2169 return WERR_OK;
2172 if (argc == 3)
2173 level = atoi(argv[2]);
2175 /* Open printer handle */
2177 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2178 strupper_m(servername);
2179 fstrcpy(user, cli->user_name);
2180 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2181 strupper_m(printername);
2182 pstrcat(printername, argv[1]);
2184 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2185 "", MAXIMUM_ALLOWED_ACCESS,
2186 servername, user, &hnd);
2188 if (!W_ERROR_IS_OK(result))
2189 goto done;
2191 got_hnd = True;
2193 /* Enumerate ports */
2195 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2196 &num_jobs, &ctr);
2198 if (!W_ERROR_IS_OK(result))
2199 goto done;
2201 for (i = 0; i < num_jobs; i++) {
2202 switch(level) {
2203 case 1:
2204 display_job_info_1(&ctr.job.job_info_1[i]);
2205 break;
2206 case 2:
2207 display_job_info_2(&ctr.job.job_info_2[i]);
2208 break;
2209 default:
2210 d_printf("unknown info level %d\n", level);
2211 break;
2215 done:
2216 if (got_hnd)
2217 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2219 return result;
2222 /****************************************************************************
2223 ****************************************************************************/
2225 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2226 TALLOC_CTX *mem_ctx, int argc,
2227 const char **argv)
2229 WERROR result;
2230 uint32 i=0, val_needed, data_needed;
2231 BOOL got_hnd = False;
2232 pstring printername;
2233 fstring servername, user;
2234 POLICY_HND hnd;
2236 if (argc != 2) {
2237 printf("Usage: %s printername\n", argv[0]);
2238 return WERR_OK;
2241 /* Open printer handle */
2243 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2244 strupper_m(servername);
2245 fstrcpy(user, cli->user_name);
2246 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2247 strupper_m(printername);
2248 pstrcat(printername, argv[1]);
2250 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2251 "", MAXIMUM_ALLOWED_ACCESS,
2252 servername, user, &hnd);
2254 if (!W_ERROR_IS_OK(result))
2255 goto done;
2257 got_hnd = True;
2259 /* Enumerate data */
2261 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2262 &val_needed, &data_needed,
2263 NULL);
2264 while (W_ERROR_IS_OK(result)) {
2265 REGISTRY_VALUE value;
2266 result = rpccli_spoolss_enumprinterdata(
2267 cli, mem_ctx, &hnd, i++, val_needed,
2268 data_needed, 0, 0, &value);
2269 if (W_ERROR_IS_OK(result))
2270 display_reg_value(value);
2272 if (W_ERROR_V(result) == ERRnomoreitems)
2273 result = W_ERROR(ERRsuccess);
2275 done:
2276 if (got_hnd)
2277 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2279 return result;
2282 /****************************************************************************
2283 ****************************************************************************/
2285 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2286 TALLOC_CTX *mem_ctx, int argc,
2287 const char **argv)
2289 WERROR result;
2290 uint32 i;
2291 BOOL got_hnd = False;
2292 pstring printername;
2293 fstring servername, user;
2294 const char *keyname = NULL;
2295 POLICY_HND hnd;
2296 REGVAL_CTR *ctr = NULL;
2298 if (argc != 3) {
2299 printf("Usage: %s printername <keyname>\n", argv[0]);
2300 return WERR_OK;
2303 keyname = argv[2];
2305 /* Open printer handle */
2307 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2308 strupper_m(servername);
2309 fstrcpy(user, cli->user_name);
2310 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2311 strupper_m(printername);
2312 pstrcat(printername, argv[1]);
2314 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2315 "", MAXIMUM_ALLOWED_ACCESS,
2316 servername, user, &hnd);
2318 if (!W_ERROR_IS_OK(result))
2319 goto done;
2321 got_hnd = True;
2323 /* Enumerate subkeys */
2325 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2326 return WERR_NOMEM;
2328 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2330 if (!W_ERROR_IS_OK(result))
2331 goto done;
2333 for (i=0; i < ctr->num_values; i++) {
2334 display_reg_value(*(ctr->values[i]));
2337 TALLOC_FREE( ctr );
2339 done:
2340 if (got_hnd)
2341 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2343 return result;
2346 /****************************************************************************
2347 ****************************************************************************/
2349 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2350 TALLOC_CTX *mem_ctx, int argc,
2351 const char **argv)
2353 WERROR result;
2354 BOOL got_hnd = False;
2355 pstring printername;
2356 fstring servername, user;
2357 const char *keyname = NULL;
2358 POLICY_HND hnd;
2359 uint16 *keylist = NULL, *curkey;
2361 if (argc < 2 || argc > 3) {
2362 printf("Usage: %s printername [keyname]\n", argv[0]);
2363 return WERR_OK;
2366 if (argc == 3)
2367 keyname = argv[2];
2368 else
2369 keyname = "";
2371 /* Open printer handle */
2373 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2374 strupper_m(servername);
2375 fstrcpy(user, cli->user_name);
2376 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2377 strupper_m(printername);
2378 pstrcat(printername, argv[1]);
2380 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2381 "", MAXIMUM_ALLOWED_ACCESS,
2382 servername, user, &hnd);
2384 if (!W_ERROR_IS_OK(result))
2385 goto done;
2387 got_hnd = True;
2389 /* Enumerate subkeys */
2391 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2393 if (!W_ERROR_IS_OK(result))
2394 goto done;
2396 curkey = keylist;
2397 while (*curkey != 0) {
2398 pstring subkey;
2399 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2400 STR_TERMINATE);
2401 printf("%s\n", subkey);
2402 curkey += strlen(subkey) + 1;
2405 done:
2407 SAFE_FREE(keylist);
2409 if (got_hnd)
2410 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2412 return result;
2415 /****************************************************************************
2416 ****************************************************************************/
2418 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2419 TALLOC_CTX *mem_ctx, int argc,
2420 const char **argv)
2422 fstring servername, printername;
2423 POLICY_HND hnd;
2424 BOOL got_hnd = False;
2425 WERROR result;
2426 SPOOL_NOTIFY_OPTION option;
2428 if (argc != 2) {
2429 printf("Usage: %s printername\n", argv[0]);
2430 result = WERR_OK;
2431 goto done;
2434 /* Open printer */
2436 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2437 strupper_m(servername);
2439 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2440 argv[1]);
2441 strupper_m(printername);
2443 result = rpccli_spoolss_open_printer_ex(
2444 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2445 servername, cli->user_name, &hnd);
2447 if (!W_ERROR_IS_OK(result)) {
2448 printf("Error opening %s\n", argv[1]);
2449 goto done;
2452 got_hnd = True;
2454 /* Create spool options */
2456 ZERO_STRUCT(option);
2458 option.version = 2;
2459 option.option_type_ptr = 1;
2460 option.count = option.ctr.count = 2;
2462 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2463 if (option.ctr.type == NULL) {
2464 result = WERR_NOMEM;
2465 goto done;
2468 ZERO_STRUCT(option.ctr.type[0]);
2469 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2470 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2471 option.ctr.type[0].fields_ptr = 1;
2472 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2474 ZERO_STRUCT(option.ctr.type[1]);
2475 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2476 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2477 option.ctr.type[1].fields_ptr = 1;
2478 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2480 /* Send rffpcnex */
2482 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2483 strupper_m(servername);
2485 result = rpccli_spoolss_rffpcnex(
2486 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2488 if (!W_ERROR_IS_OK(result)) {
2489 printf("Error rffpcnex %s\n", argv[1]);
2490 goto done;
2493 done:
2494 if (got_hnd)
2495 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2497 return result;
2500 /****************************************************************************
2501 ****************************************************************************/
2503 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2504 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2506 PRINTER_INFO_CTR ctr1, ctr2;
2507 WERROR werror;
2508 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2510 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2511 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2512 if ( !W_ERROR_IS_OK(werror) ) {
2513 printf("failed (%s)\n", dos_errstr(werror));
2514 talloc_destroy(mem_ctx);
2515 return False;
2517 printf("ok\n");
2519 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2520 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2521 if ( !W_ERROR_IS_OK(werror) ) {
2522 printf("failed (%s)\n", dos_errstr(werror));
2523 talloc_destroy(mem_ctx);
2524 return False;
2526 printf("ok\n");
2528 talloc_destroy(mem_ctx);
2530 return True;
2533 /****************************************************************************
2534 ****************************************************************************/
2536 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2537 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2539 PRINTER_INFO_CTR ctr1, ctr2;
2540 WERROR werror;
2541 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2542 SEC_DESC *sd1, *sd2;
2543 BOOL result = True;
2546 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2547 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2548 if ( !W_ERROR_IS_OK(werror) ) {
2549 printf("failed (%s)\n", dos_errstr(werror));
2550 result = False;
2551 goto done;
2553 printf("ok\n");
2555 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2556 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2557 if ( !W_ERROR_IS_OK(werror) ) {
2558 printf("failed (%s)\n", dos_errstr(werror));
2559 result = False;
2560 goto done;
2562 printf("ok\n");
2565 printf("++ ");
2567 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2568 printf("NULL PRINTER_INFO_3!\n");
2569 result = False;
2570 goto done;
2573 sd1 = ctr1.printers_3->secdesc;
2574 sd2 = ctr2.printers_3->secdesc;
2576 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2577 printf("NULL secdesc!\n");
2578 result = False;
2579 goto done;
2582 if (!sec_desc_equal( sd1, sd2 ) ) {
2583 printf("Security Descriptors *not* equal!\n");
2584 result = False;
2585 goto done;
2588 printf("Security descriptors match\n");
2590 done:
2591 talloc_destroy(mem_ctx);
2592 return result;
2596 /****************************************************************************
2597 ****************************************************************************/
2599 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2600 TALLOC_CTX *mem_ctx, int argc,
2601 const char **argv)
2603 fstring printername, servername1, servername2;
2604 pstring printername_path;
2605 struct cli_state *cli_server1 = cli->cli;
2606 struct cli_state *cli_server2 = NULL;
2607 struct rpc_pipe_client *cli2 = NULL;
2608 POLICY_HND hPrinter1, hPrinter2;
2609 NTSTATUS nt_status;
2610 WERROR werror;
2612 if ( argc != 3 ) {
2613 printf("Usage: %s <printer> <server>\n", argv[0]);
2614 return WERR_OK;
2617 fstrcpy( printername, argv[1] );
2619 fstr_sprintf( servername1, cli->cli->desthost );
2620 fstrcpy( servername2, argv[2] );
2621 strupper_m( servername1 );
2622 strupper_m( servername2 );
2625 /* first get the connection to the remote server */
2627 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2628 NULL, 0,
2629 "IPC$", "IPC",
2630 cmdline_auth_info.username,
2631 lp_workgroup(),
2632 cmdline_auth_info.password,
2633 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2634 cmdline_auth_info.signing_state, NULL);
2636 if ( !NT_STATUS_IS_OK(nt_status) )
2637 return WERR_GENERAL_FAILURE;
2639 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2640 if (!cli2) {
2641 printf("failed to open spoolss pipe on server %s (%s)\n",
2642 servername2, nt_errstr(nt_status));
2643 return WERR_GENERAL_FAILURE;
2646 /* now open up both printers */
2648 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2649 printf("Opening %s...", printername_path);
2650 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2651 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2652 if ( !W_ERROR_IS_OK(werror) ) {
2653 printf("failed (%s)\n", dos_errstr(werror));
2654 goto done;
2656 printf("ok\n");
2658 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2659 printf("Opening %s...", printername_path);
2660 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2661 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2662 if ( !W_ERROR_IS_OK(werror) ) {
2663 printf("failed (%s)\n", dos_errstr(werror));
2664 goto done;
2666 printf("ok\n");
2669 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2670 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2671 #if 0
2672 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2673 #endif
2676 done:
2677 /* cleanup */
2679 printf("Closing printers...");
2680 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2681 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2682 printf("ok\n");
2684 /* close the second remote connection */
2686 cli_shutdown( cli_server2 );
2688 return WERR_OK;
2691 /* List of commands exported by this module */
2692 struct cmd_set spoolss_commands[] = {
2694 { "SPOOLSS" },
2696 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2697 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2698 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2699 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2700 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2701 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2702 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2703 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2704 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2705 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2706 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2707 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2708 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2709 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2710 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2711 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2712 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2713 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2714 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2715 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2716 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2717 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2718 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2719 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2720 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2721 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2722 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2723 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2724 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },
2726 { NULL }