Determine case sensitivity based on file system attributes.
[Samba.git] / source / rpcclient / cmd_spoolss.c
blob47409afc51b13a87ffd6cbed7e1f119e1c5894b7
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 3 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, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpcclient.h"
27 struct table_node {
28 const char *long_archi;
29 const char *short_archi;
30 int version;
33 /* The version int is used by getdrivers. Note that
34 all architecture strings that support mutliple
35 versions must be grouped together since enumdrivers
36 uses this property to prevent issuing multiple
37 enumdriver calls for the same arch */
40 static const struct table_node archi_table[]= {
42 {"Windows 4.0", "WIN40", 0 },
43 {"Windows NT x86", "W32X86", 2 },
44 {"Windows NT x86", "W32X86", 3 },
45 {"Windows NT R4000", "W32MIPS", 2 },
46 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
47 {"Windows NT PowerPC", "W32PPC", 2 },
48 {"Windows IA64", "IA64", 3 },
49 {"Windows x64", "x64", 3 },
50 {NULL, "", -1 }
53 /**
54 * @file
56 * rpcclient module for SPOOLSS rpc pipe.
58 * This generally just parses and checks command lines, and then calls
59 * a cli_spoolss function.
60 **/
62 /****************************************************************************
63 function to do the mapping between the long architecture name and
64 the short one.
65 ****************************************************************************/
67 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
69 int i=-1;
71 DEBUG(107,("Getting architecture dependant directory\n"));
72 do {
73 i++;
74 } while ( (archi_table[i].long_archi!=NULL ) &&
75 StrCaseCmp(long_archi, archi_table[i].long_archi) );
77 if (archi_table[i].long_archi==NULL) {
78 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
79 return NULL;
82 /* this might be client code - but shouldn't this be an fstrcpy etc? */
85 DEBUGADD(108,("index: [%d]\n", i));
86 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
87 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
89 return archi_table[i].short_archi;
92 /****************************************************************************
93 ****************************************************************************/
95 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
96 TALLOC_CTX *mem_ctx,
97 int argc, const char **argv)
99 WERROR werror;
100 fstring printername;
101 fstring servername, user;
102 POLICY_HND hnd;
104 if (argc != 2) {
105 printf("Usage: %s <printername>\n", argv[0]);
106 return WERR_OK;
109 if (!cli)
110 return WERR_GENERAL_FAILURE;
112 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
113 strupper_m(servername);
114 fstrcpy(user, cli->user_name);
115 fstrcpy(printername, argv[1]);
117 /* Open the printer handle */
119 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
120 "", PRINTER_ALL_ACCESS,
121 servername, user, &hnd);
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", printername);
125 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
127 if (!W_ERROR_IS_OK(werror)) {
128 printf("Error closing printer handle! (%s)\n",
129 get_dos_error_msg(werror));
133 return werror;
137 /****************************************************************************
138 ****************************************************************************/
140 static void display_print_info_0(PRINTER_INFO_0 *i0)
142 fstring name = "";
143 fstring servername = "";
145 if (!i0)
146 return;
148 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
150 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
152 printf("\tprintername:[%s]\n", name);
153 printf("\tservername:[%s]\n", servername);
154 printf("\tcjobs:[0x%x]\n", i0->cjobs);
155 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
157 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
158 i0->day, i0->dayofweek);
159 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
160 i0->second, i0->milliseconds);
162 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
163 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
165 printf("\tmajorversion:[0x%x]\n", i0->major_version);
166 printf("\tbuildversion:[0x%x]\n", i0->build_version);
168 printf("\tunknown7:[0x%x]\n", i0->unknown7);
169 printf("\tunknown8:[0x%x]\n", i0->unknown8);
170 printf("\tunknown9:[0x%x]\n", i0->unknown9);
171 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
172 printf("\tunknown11:[0x%x]\n", i0->unknown11);
173 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
174 printf("\tunknown13:[0x%x]\n", i0->unknown13);
175 printf("\tunknown14:[0x%x]\n", i0->unknown14);
176 printf("\tunknown15:[0x%x]\n", i0->unknown15);
177 printf("\tunknown16:[0x%x]\n", i0->unknown16);
178 printf("\tchange_id:[0x%x]\n", i0->change_id);
179 printf("\tunknown18:[0x%x]\n", i0->unknown18);
180 printf("\tstatus:[0x%x]\n", i0->status);
181 printf("\tunknown20:[0x%x]\n", i0->unknown20);
182 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
183 printf("\tunknown22:[0x%x]\n", i0->unknown22);
184 printf("\tunknown23:[0x%x]\n", i0->unknown23);
185 printf("\tunknown24:[0x%x]\n", i0->unknown24);
186 printf("\tunknown25:[0x%x]\n", i0->unknown25);
187 printf("\tunknown26:[0x%x]\n", i0->unknown26);
188 printf("\tunknown27:[0x%x]\n", i0->unknown27);
189 printf("\tunknown28:[0x%x]\n", i0->unknown28);
190 printf("\tunknown29:[0x%x]\n", i0->unknown29);
192 printf("\n");
195 /****************************************************************************
196 ****************************************************************************/
198 static void display_print_info_1(PRINTER_INFO_1 *i1)
200 fstring desc = "";
201 fstring name = "";
202 fstring comm = "";
204 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
205 STR_TERMINATE);
207 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
208 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
210 printf("\tflags:[0x%x]\n", i1->flags);
211 printf("\tname:[%s]\n", name);
212 printf("\tdescription:[%s]\n", desc);
213 printf("\tcomment:[%s]\n", comm);
215 printf("\n");
218 /****************************************************************************
219 ****************************************************************************/
221 static void display_print_info_2(PRINTER_INFO_2 *i2)
223 fstring servername = "";
224 fstring printername = "";
225 fstring sharename = "";
226 fstring portname = "";
227 fstring drivername = "";
228 fstring comment = "";
229 fstring location = "";
230 fstring sepfile = "";
231 fstring printprocessor = "";
232 fstring datatype = "";
233 fstring parameters = "";
235 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
236 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
237 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
238 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
239 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
240 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
241 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
242 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
243 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
244 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
245 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
247 printf("\tservername:[%s]\n", servername);
248 printf("\tprintername:[%s]\n", printername);
249 printf("\tsharename:[%s]\n", sharename);
250 printf("\tportname:[%s]\n", portname);
251 printf("\tdrivername:[%s]\n", drivername);
252 printf("\tcomment:[%s]\n", comment);
253 printf("\tlocation:[%s]\n", location);
254 printf("\tsepfile:[%s]\n", sepfile);
255 printf("\tprintprocessor:[%s]\n", printprocessor);
256 printf("\tdatatype:[%s]\n", datatype);
257 printf("\tparameters:[%s]\n", parameters);
258 printf("\tattributes:[0x%x]\n", i2->attributes);
259 printf("\tpriority:[0x%x]\n", i2->priority);
260 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
261 printf("\tstarttime:[0x%x]\n", i2->starttime);
262 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
263 printf("\tstatus:[0x%x]\n", i2->status);
264 printf("\tcjobs:[0x%x]\n", i2->cjobs);
265 printf("\taverageppm:[0x%x]\n", i2->averageppm);
267 if (i2->secdesc)
268 display_sec_desc(i2->secdesc);
270 printf("\n");
273 /****************************************************************************
274 ****************************************************************************/
276 static void display_print_info_3(PRINTER_INFO_3 *i3)
278 display_sec_desc(i3->secdesc);
280 printf("\n");
283 /****************************************************************************
284 ****************************************************************************/
286 static void display_print_info_7(PRINTER_INFO_7 *i7)
288 fstring guid = "";
289 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
290 printf("\tguid:[%s]\n", guid);
291 printf("\taction:[0x%x]\n", i7->action);
295 /****************************************************************************
296 ****************************************************************************/
298 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
299 TALLOC_CTX *mem_ctx,
300 int argc, const char **argv)
302 WERROR result;
303 uint32 info_level = 1;
304 PRINTER_INFO_CTR ctr;
305 uint32 i = 0, num_printers;
306 fstring name;
308 if (argc > 3)
310 printf("Usage: %s [level] [name]\n", argv[0]);
311 return WERR_OK;
314 if (argc >= 2)
315 info_level = atoi(argv[1]);
317 if (argc == 3)
318 fstrcpy(name, argv[2]);
319 else {
320 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
321 strupper_m(name);
324 ZERO_STRUCT(ctr);
326 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
327 info_level, &num_printers, &ctr);
329 if (W_ERROR_IS_OK(result)) {
331 if (!num_printers) {
332 printf ("No printers returned.\n");
333 goto done;
336 for (i = 0; i < num_printers; i++) {
337 switch(info_level) {
338 case 0:
339 display_print_info_0(&ctr.printers_0[i]);
340 break;
341 case 1:
342 display_print_info_1(&ctr.printers_1[i]);
343 break;
344 case 2:
345 display_print_info_2(&ctr.printers_2[i]);
346 break;
347 case 3:
348 display_print_info_3(&ctr.printers_3[i]);
349 break;
350 default:
351 printf("unknown info level %d\n", info_level);
352 goto done;
356 done:
358 return result;
361 /****************************************************************************
362 ****************************************************************************/
364 static void display_port_info_1(PORT_INFO_1 *i1)
366 fstring buffer;
368 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
369 printf("\tPort Name:\t[%s]\n", buffer);
372 /****************************************************************************
373 ****************************************************************************/
375 static void display_port_info_2(PORT_INFO_2 *i2)
377 fstring buffer;
379 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
380 printf("\tPort Name:\t[%s]\n", buffer);
381 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
383 printf("\tMonitor Name:\t[%s]\n", buffer);
384 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
386 printf("\tDescription:\t[%s]\n", buffer);
387 printf("\tPort Type:\t" );
388 if ( i2->port_type ) {
389 int comma = 0; /* hack */
390 printf( "[" );
391 if ( i2->port_type & PORT_TYPE_READ ) {
392 printf( "Read" );
393 comma = 1;
395 if ( i2->port_type & PORT_TYPE_WRITE ) {
396 printf( "%sWrite", comma ? ", " : "" );
397 comma = 1;
399 /* These two have slightly different interpretations
400 on 95/98/ME but I'm disregarding that for now */
401 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
402 printf( "%sRedirected", comma ? ", " : "" );
403 comma = 1;
405 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
406 printf( "%sNet-Attached", comma ? ", " : "" );
408 printf( "]\n" );
409 } else {
410 printf( "[Unset]\n" );
412 printf("\tReserved:\t[%d]\n", i2->reserved);
413 printf("\n");
416 /****************************************************************************
417 ****************************************************************************/
419 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
420 TALLOC_CTX *mem_ctx, int argc,
421 const char **argv)
423 WERROR result;
424 uint32 info_level = 1;
425 PORT_INFO_CTR ctr;
426 uint32 returned;
428 if (argc > 2) {
429 printf("Usage: %s [level]\n", argv[0]);
430 return WERR_OK;
433 if (argc == 2)
434 info_level = atoi(argv[1]);
436 /* Enumerate ports */
438 ZERO_STRUCT(ctr);
440 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
442 if (W_ERROR_IS_OK(result)) {
443 int i;
445 for (i = 0; i < returned; i++) {
446 switch (info_level) {
447 case 1:
448 display_port_info_1(&ctr.port.info_1[i]);
449 break;
450 case 2:
451 display_port_info_2(&ctr.port.info_2[i]);
452 break;
453 default:
454 printf("unknown info level %d\n", info_level);
455 break;
460 return result;
463 /****************************************************************************
464 ****************************************************************************/
466 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
467 TALLOC_CTX *mem_ctx,
468 int argc, const char **argv)
470 POLICY_HND pol;
471 WERROR result;
472 uint32 info_level = 2;
473 bool opened_hnd = False;
474 PRINTER_INFO_CTR ctr;
475 fstring printername,
476 servername,
477 user,
478 comment;
480 if (argc == 1 || argc > 3) {
481 printf("Usage: %s printername comment\n", argv[0]);
483 return WERR_OK;
486 /* Open a printer handle */
487 if (argc == 3) {
488 fstrcpy(comment, argv[2]);
491 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
492 strupper_m(servername);
493 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
494 fstrcpy(user, cli->user_name);
496 /* get a printer handle */
497 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
498 PRINTER_ALL_ACCESS, servername,
499 user, &pol);
501 if (!W_ERROR_IS_OK(result))
502 goto done;
504 opened_hnd = True;
506 /* Get printer info */
507 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
509 if (!W_ERROR_IS_OK(result))
510 goto done;
513 /* Modify the comment. */
514 init_unistr(&ctr.printers_2->comment, comment);
515 ctr.printers_2->devmode = NULL;
516 ctr.printers_2->secdesc = NULL;
518 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
519 if (W_ERROR_IS_OK(result))
520 printf("Success in setting comment.\n");
522 done:
523 if (opened_hnd)
524 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
526 return result;
529 /****************************************************************************
530 ****************************************************************************/
532 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
533 TALLOC_CTX *mem_ctx,
534 int argc, const char **argv)
536 POLICY_HND pol;
537 WERROR result;
538 uint32 info_level = 2;
539 bool opened_hnd = False;
540 PRINTER_INFO_CTR ctr;
541 fstring printername,
542 servername,
543 user,
544 new_printername;
546 if (argc == 1 || argc > 3) {
547 printf("Usage: %s printername new_printername\n", argv[0]);
549 return WERR_OK;
552 /* Open a printer handle */
553 if (argc == 3) {
554 fstrcpy(new_printername, argv[2]);
557 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
558 strupper_m(servername);
559 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
560 fstrcpy(user, cli->user_name);
562 /* get a printer handle */
563 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
564 PRINTER_ALL_ACCESS, servername,
565 user, &pol);
567 if (!W_ERROR_IS_OK(result))
568 goto done;
570 opened_hnd = True;
572 /* Get printer info */
573 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
575 if (!W_ERROR_IS_OK(result))
576 goto done;
578 /* Modify the printername. */
579 init_unistr(&ctr.printers_2->printername, new_printername);
580 ctr.printers_2->devmode = NULL;
581 ctr.printers_2->secdesc = NULL;
583 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
584 if (W_ERROR_IS_OK(result))
585 printf("Success in setting printername.\n");
587 done:
588 if (opened_hnd)
589 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
591 return result;
594 /****************************************************************************
595 ****************************************************************************/
597 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
598 TALLOC_CTX *mem_ctx,
599 int argc, const char **argv)
601 POLICY_HND pol;
602 WERROR result;
603 uint32 info_level = 1;
604 bool opened_hnd = False;
605 PRINTER_INFO_CTR ctr;
606 fstring printername,
607 servername,
608 user;
610 if (argc == 1 || argc > 3) {
611 printf("Usage: %s <printername> [level]\n", argv[0]);
612 return WERR_OK;
615 /* Open a printer handle */
616 if (argc == 3) {
617 info_level = atoi(argv[2]);
620 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
621 strupper_m(servername);
622 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
623 fstrcpy(user, cli->user_name);
625 /* get a printer handle */
627 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
628 "", MAXIMUM_ALLOWED_ACCESS,
629 servername, user, &pol);
631 if (!W_ERROR_IS_OK(result))
632 goto done;
634 opened_hnd = True;
636 /* Get printer info */
638 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
640 if (!W_ERROR_IS_OK(result))
641 goto done;
643 /* Display printer info */
645 switch (info_level) {
646 case 0:
647 display_print_info_0(ctr.printers_0);
648 break;
649 case 1:
650 display_print_info_1(ctr.printers_1);
651 break;
652 case 2:
653 display_print_info_2(ctr.printers_2);
654 break;
655 case 3:
656 display_print_info_3(ctr.printers_3);
657 break;
658 case 7:
659 display_print_info_7(ctr.printers_7);
660 break;
661 default:
662 printf("unknown info level %d\n", info_level);
663 break;
666 done:
667 if (opened_hnd)
668 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
670 return result;
673 /****************************************************************************
674 ****************************************************************************/
676 static void display_reg_value(REGISTRY_VALUE value)
678 char *text = NULL;
680 switch(value.type) {
681 case REG_DWORD:
682 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
683 *((uint32 *) value.data_p));
684 break;
685 case REG_SZ:
686 rpcstr_pull_talloc(talloc_tos(),
687 &text,
688 value.data_p,
689 value.size,
690 STR_TERMINATE);
691 printf("%s: REG_SZ: %s\n", value.valuename, text ? 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,
1223 char **saveptr)
1225 char *ptr;
1227 /* get the next token */
1228 ptr = strtok_r(str, delim, saveptr);
1230 /* a string of 'NULL' is used to represent an empty
1231 parameter because two consecutive delimiters
1232 will not return an empty string. See man strtok(3)
1233 for details */
1234 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1235 ptr = NULL;
1237 if (dest != NULL)
1238 init_unistr(dest, ptr);
1240 return ptr;
1243 /********************************************************************************
1244 fill in the members of a DRIVER_INFO_3 struct using a character
1245 string in the form of
1246 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1247 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1248 <Default Data Type>:<Comma Separated list of Files>
1249 *******************************************************************************/
1250 static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1251 char *args )
1253 char *str, *str2;
1254 uint32 len, i;
1255 char *saveptr = NULL;
1257 /* fill in the UNISTR fields */
1258 str = get_driver_3_param (args, ":", &info->name, &saveptr);
1259 str = get_driver_3_param (NULL, ":", &info->driverpath, &saveptr);
1260 str = get_driver_3_param (NULL, ":", &info->datafile, &saveptr);
1261 str = get_driver_3_param (NULL, ":", &info->configfile, &saveptr);
1262 str = get_driver_3_param (NULL, ":", &info->helpfile, &saveptr);
1263 str = get_driver_3_param (NULL, ":", &info->monitorname, &saveptr);
1264 str = get_driver_3_param (NULL, ":", &info->defaultdatatype, &saveptr);
1266 /* <Comma Separated List of Dependent Files> */
1267 /* save the beginning of the string */
1268 str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
1269 str = str2;
1271 /* begin to strip out each filename */
1272 str = strtok_r(str, ",", &saveptr);
1273 len = 0;
1274 while (str != NULL)
1276 /* keep a cumlative count of the str lengths */
1277 len += strlen(str)+1;
1278 str = strtok_r(NULL, ",", &saveptr);
1281 /* allocate the space; add one extra slot for a terminating NULL.
1282 Each filename is NULL terminated and the end contains a double
1283 NULL */
1284 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1286 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1287 return False;
1289 for (i=0; i<len; i++)
1291 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1293 info->dependentfiles[len] = '\0';
1295 return True;
1299 /****************************************************************************
1300 ****************************************************************************/
1302 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1303 TALLOC_CTX *mem_ctx,
1304 int argc, const char **argv)
1306 WERROR result;
1307 uint32 level = 3;
1308 PRINTER_DRIVER_CTR ctr;
1309 DRIVER_INFO_3 info3;
1310 const char *arch;
1311 fstring driver_name;
1312 char *driver_args;
1314 /* parse the command arguements */
1315 if (argc != 3 && argc != 4)
1317 printf ("Usage: %s <Environment> \\\n", argv[0]);
1318 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1319 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1320 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1321 printf ("\t[version]\n");
1323 return WERR_OK;
1326 /* Fill in the DRIVER_INFO_3 struct */
1327 ZERO_STRUCT(info3);
1328 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1330 printf ("Error Unknown architechture [%s]\n", argv[1]);
1331 return WERR_INVALID_PARAM;
1333 else
1334 set_drv_info_3_env(&info3, arch);
1336 driver_args = talloc_strdup( mem_ctx, argv[2] );
1337 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1339 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1340 return WERR_INVALID_PARAM;
1343 /* if printer driver version specified, override the default version
1344 * used by the architecture. This allows installation of Windows
1345 * 2000 (version 3) printer drivers. */
1346 if (argc == 4)
1348 info3.version = atoi(argv[3]);
1352 ctr.info3 = &info3;
1353 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1355 if (W_ERROR_IS_OK(result)) {
1356 rpcstr_pull(driver_name, info3.name.buffer,
1357 sizeof(driver_name), -1, STR_TERMINATE);
1358 printf ("Printer Driver %s successfully installed.\n",
1359 driver_name);
1362 return result;
1366 /****************************************************************************
1367 ****************************************************************************/
1369 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1370 TALLOC_CTX *mem_ctx,
1371 int argc, const char **argv)
1373 WERROR result;
1374 uint32 level = 2;
1375 PRINTER_INFO_CTR ctr;
1376 PRINTER_INFO_2 info2;
1377 fstring servername;
1379 /* parse the command arguements */
1380 if (argc != 5)
1382 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1383 return WERR_OK;
1386 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1387 strupper_m(servername);
1389 /* Fill in the DRIVER_INFO_2 struct */
1390 ZERO_STRUCT(info2);
1392 init_unistr( &info2.printername, argv[1]);
1393 init_unistr( &info2.sharename, argv[2]);
1394 init_unistr( &info2.drivername, argv[3]);
1395 init_unistr( &info2.portname, argv[4]);
1396 init_unistr( &info2.comment, "Created by rpcclient");
1397 init_unistr( &info2.printprocessor, "winprint");
1398 init_unistr( &info2.datatype, "RAW");
1399 info2.devmode = NULL;
1400 info2.secdesc = NULL;
1401 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1402 info2.priority = 0;
1403 info2.defaultpriority = 0;
1404 info2.starttime = 0;
1405 info2.untiltime = 0;
1407 /* These three fields must not be used by AddPrinter()
1408 as defined in the MS Platform SDK documentation..
1409 --jerry
1410 info2.status = 0;
1411 info2.cjobs = 0;
1412 info2.averageppm = 0;
1415 ctr.printers_2 = &info2;
1416 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1418 if (W_ERROR_IS_OK(result))
1419 printf ("Printer %s successfully installed.\n", argv[1]);
1421 return result;
1424 /****************************************************************************
1425 ****************************************************************************/
1427 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1428 TALLOC_CTX *mem_ctx,
1429 int argc, const char **argv)
1431 POLICY_HND pol;
1432 WERROR result;
1433 uint32 level = 2;
1434 bool opened_hnd = False;
1435 PRINTER_INFO_CTR ctr;
1436 PRINTER_INFO_2 info2;
1437 fstring servername,
1438 printername,
1439 user;
1441 /* parse the command arguements */
1442 if (argc != 3)
1444 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1445 return WERR_OK;
1448 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1449 strupper_m(servername);
1450 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1451 fstrcpy(user, cli->user_name);
1453 /* Get a printer handle */
1455 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1456 PRINTER_ALL_ACCESS,
1457 servername, user, &pol);
1459 if (!W_ERROR_IS_OK(result))
1460 goto done;
1462 opened_hnd = True;
1464 /* Get printer info */
1466 ZERO_STRUCT (info2);
1467 ctr.printers_2 = &info2;
1469 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1471 if (!W_ERROR_IS_OK(result)) {
1472 printf ("Unable to retrieve printer information!\n");
1473 goto done;
1476 /* Set the printer driver */
1478 init_unistr(&ctr.printers_2->drivername, argv[2]);
1480 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1482 if (!W_ERROR_IS_OK(result)) {
1483 printf("SetPrinter call failed!\n");
1484 goto done;;
1487 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1489 done:
1490 /* Cleanup */
1492 if (opened_hnd)
1493 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1495 return result;
1499 /****************************************************************************
1500 ****************************************************************************/
1502 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1503 TALLOC_CTX *mem_ctx,
1504 int argc, const char **argv)
1506 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1508 int i;
1509 int vers = -1;
1511 const char *arch = NULL;
1513 /* parse the command arguements */
1514 if (argc < 2 || argc > 4) {
1515 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1516 return WERR_OK;
1519 if (argc >= 3)
1520 arch = argv[2];
1521 if (argc == 4)
1522 vers = atoi (argv[3]);
1525 /* delete the driver for all architectures */
1526 for (i=0; archi_table[i].long_archi; i++) {
1528 if (arch && !strequal( archi_table[i].long_archi, arch))
1529 continue;
1531 if (vers >= 0 && archi_table[i].version != vers)
1532 continue;
1534 /* make the call to remove the driver */
1535 result = rpccli_spoolss_deleteprinterdriverex(
1536 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1538 if ( !W_ERROR_IS_OK(result) )
1540 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1541 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1542 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1545 else
1547 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1548 archi_table[i].long_archi, archi_table[i].version);
1549 ret = WERR_OK;
1553 return ret;
1557 /****************************************************************************
1558 ****************************************************************************/
1560 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1561 TALLOC_CTX *mem_ctx,
1562 int argc, const char **argv)
1564 WERROR result = WERR_OK;
1565 fstring servername;
1566 int i;
1568 /* parse the command arguements */
1569 if (argc != 2) {
1570 printf ("Usage: %s <driver>\n", argv[0]);
1571 return WERR_OK;
1574 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1575 strupper_m(servername);
1577 /* delete the driver for all architectures */
1578 for (i=0; archi_table[i].long_archi; i++) {
1579 /* make the call to remove the driver */
1580 result = rpccli_spoolss_deleteprinterdriver(
1581 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1583 if ( !W_ERROR_IS_OK(result) ) {
1584 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1585 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1586 argv[1], archi_table[i].long_archi,
1587 W_ERROR_V(result));
1589 } else {
1590 printf ("Driver %s removed for arch [%s].\n", argv[1],
1591 archi_table[i].long_archi);
1595 return result;
1598 /****************************************************************************
1599 ****************************************************************************/
1601 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1602 TALLOC_CTX *mem_ctx,
1603 int argc, const char **argv)
1605 WERROR result;
1606 char *servername = NULL, *environment = NULL;
1607 fstring procdir;
1609 /* parse the command arguements */
1610 if (argc > 2) {
1611 printf ("Usage: %s [environment]\n", argv[0]);
1612 return WERR_OK;
1615 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1616 return WERR_NOMEM;
1617 strupper_m(servername);
1619 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1620 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1621 SAFE_FREE(servername);
1622 return WERR_NOMEM;
1625 result = rpccli_spoolss_getprintprocessordirectory(
1626 cli, mem_ctx, servername, environment, procdir);
1628 if (W_ERROR_IS_OK(result))
1629 printf("%s\n", procdir);
1631 SAFE_FREE(servername);
1632 SAFE_FREE(environment);
1634 return result;
1637 /****************************************************************************
1638 ****************************************************************************/
1640 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1641 int argc, const char **argv)
1643 POLICY_HND handle;
1644 WERROR werror;
1645 char *servername = NULL, *printername = NULL;
1646 FORM form;
1647 bool got_handle = False;
1649 /* Parse the command arguements */
1651 if (argc != 3) {
1652 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1653 return WERR_OK;
1656 /* Get a printer handle */
1658 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1659 strupper_m(servername);
1660 asprintf(&printername, "%s\\%s", servername, argv[1]);
1662 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1663 PRINTER_ALL_ACCESS,
1664 servername, cli->user_name, &handle);
1666 if (!W_ERROR_IS_OK(werror))
1667 goto done;
1669 got_handle = True;
1671 /* Dummy up some values for the form data */
1673 form.flags = FORM_USER;
1674 form.size_x = form.size_y = 100;
1675 form.left = 0;
1676 form.top = 10;
1677 form.right = 20;
1678 form.bottom = 30;
1680 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1682 /* Add the form */
1685 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1687 done:
1688 if (got_handle)
1689 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1691 SAFE_FREE(servername);
1692 SAFE_FREE(printername);
1694 return werror;
1697 /****************************************************************************
1698 ****************************************************************************/
1700 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1701 int argc, const char **argv)
1703 POLICY_HND handle;
1704 WERROR werror;
1705 char *servername = NULL, *printername = NULL;
1706 FORM form;
1707 bool got_handle = False;
1709 /* Parse the command arguements */
1711 if (argc != 3) {
1712 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1713 return WERR_OK;
1716 /* Get a printer handle */
1718 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1719 strupper_m(servername);
1720 asprintf(&printername, "%s\\%s", servername, argv[1]);
1722 werror = rpccli_spoolss_open_printer_ex(
1723 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1724 servername, cli->user_name, &handle);
1726 if (!W_ERROR_IS_OK(werror))
1727 goto done;
1729 got_handle = True;
1731 /* Dummy up some values for the form data */
1733 form.flags = FORM_PRINTER;
1734 form.size_x = form.size_y = 100;
1735 form.left = 0;
1736 form.top = 1000;
1737 form.right = 2000;
1738 form.bottom = 3000;
1740 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1742 /* Set the form */
1744 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1746 done:
1747 if (got_handle)
1748 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1750 SAFE_FREE(servername);
1751 SAFE_FREE(printername);
1753 return werror;
1756 /****************************************************************************
1757 ****************************************************************************/
1759 static const char *get_form_flag(int form_flag)
1761 switch (form_flag) {
1762 case FORM_USER:
1763 return "FORM_USER";
1764 case FORM_BUILTIN:
1765 return "FORM_BUILTIN";
1766 case FORM_PRINTER:
1767 return "FORM_PRINTER";
1768 default:
1769 return "unknown";
1773 /****************************************************************************
1774 ****************************************************************************/
1776 static void display_form(FORM_1 *form)
1778 fstring form_name = "";
1780 if (form->name.buffer)
1781 rpcstr_pull(form_name, form->name.buffer,
1782 sizeof(form_name), -1, STR_TERMINATE);
1784 printf("%s\n" \
1785 "\tflag: %s (%d)\n" \
1786 "\twidth: %d, length: %d\n" \
1787 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1788 form_name, get_form_flag(form->flag), form->flag,
1789 form->width, form->length,
1790 form->left, form->right,
1791 form->top, form->bottom);
1794 /****************************************************************************
1795 ****************************************************************************/
1797 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1798 int argc, const char **argv)
1800 POLICY_HND handle;
1801 WERROR werror;
1802 char *servername = NULL, *printername = NULL;
1803 FORM_1 form;
1804 bool got_handle = False;
1806 /* Parse the command arguements */
1808 if (argc != 3) {
1809 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1810 return WERR_OK;
1813 /* Get a printer handle */
1815 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1816 strupper_m(servername);
1817 asprintf(&printername, "%s\\%s", servername, argv[1]);
1819 werror = rpccli_spoolss_open_printer_ex(
1820 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1821 servername, cli->user_name, &handle);
1823 if (!W_ERROR_IS_OK(werror))
1824 goto done;
1826 got_handle = True;
1828 /* Get the form */
1830 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1832 if (!W_ERROR_IS_OK(werror))
1833 goto done;
1835 display_form(&form);
1837 done:
1838 if (got_handle)
1839 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1841 SAFE_FREE(servername);
1842 SAFE_FREE(printername);
1844 return werror;
1847 /****************************************************************************
1848 ****************************************************************************/
1850 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1851 TALLOC_CTX *mem_ctx, int argc,
1852 const char **argv)
1854 POLICY_HND handle;
1855 WERROR werror;
1856 char *servername = NULL, *printername = NULL;
1857 bool got_handle = False;
1859 /* Parse the command arguements */
1861 if (argc != 3) {
1862 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1863 return WERR_OK;
1866 /* Get a printer handle */
1868 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1869 strupper_m(servername);
1870 asprintf(&printername, "%s\\%s", servername, argv[1]);
1872 werror = rpccli_spoolss_open_printer_ex(
1873 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1874 servername, cli->user_name, &handle);
1876 if (!W_ERROR_IS_OK(werror))
1877 goto done;
1879 got_handle = True;
1881 /* Delete the form */
1883 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1885 done:
1886 if (got_handle)
1887 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1889 SAFE_FREE(servername);
1890 SAFE_FREE(printername);
1892 return werror;
1895 /****************************************************************************
1896 ****************************************************************************/
1898 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1899 TALLOC_CTX *mem_ctx, int argc,
1900 const char **argv)
1902 POLICY_HND handle;
1903 WERROR werror;
1904 char *servername = NULL, *printername = NULL;
1905 bool got_handle = False;
1906 uint32 num_forms, level = 1, i;
1907 FORM_1 *forms;
1909 /* Parse the command arguements */
1911 if (argc != 2) {
1912 printf ("Usage: %s <printer>\n", argv[0]);
1913 return WERR_OK;
1916 /* Get a printer handle */
1918 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1919 strupper_m(servername);
1920 asprintf(&printername, "%s\\%s", servername, argv[1]);
1922 werror = rpccli_spoolss_open_printer_ex(
1923 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1924 servername, cli->user_name, &handle);
1926 if (!W_ERROR_IS_OK(werror))
1927 goto done;
1929 got_handle = True;
1931 /* Enumerate forms */
1933 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1935 if (!W_ERROR_IS_OK(werror))
1936 goto done;
1938 /* Display output */
1940 for (i = 0; i < num_forms; i++) {
1942 display_form(&forms[i]);
1946 done:
1947 if (got_handle)
1948 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1950 SAFE_FREE(servername);
1951 SAFE_FREE(printername);
1953 return werror;
1956 /****************************************************************************
1957 ****************************************************************************/
1959 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1960 TALLOC_CTX *mem_ctx,
1961 int argc, const char **argv)
1963 WERROR result;
1964 fstring servername, printername, user;
1965 POLICY_HND pol;
1966 bool opened_hnd = False;
1967 PRINTER_INFO_CTR ctr;
1968 PRINTER_INFO_0 info;
1969 REGISTRY_VALUE value;
1970 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1972 /* parse the command arguements */
1973 if (argc < 5) {
1974 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1975 " <value> <data>\n",
1976 argv[0]);
1977 result = WERR_INVALID_PARAM;
1978 goto done;
1981 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1982 strupper_m(servername);
1983 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1984 fstrcpy(user, cli->user_name);
1986 value.type = REG_NONE;
1988 if (strequal(argv[2], "string")) {
1989 value.type = REG_SZ;
1992 if (strequal(argv[2], "binary")) {
1993 value.type = REG_BINARY;
1996 if (strequal(argv[2], "dword")) {
1997 value.type = REG_DWORD;
2000 if (strequal(argv[2], "multistring")) {
2001 value.type = REG_MULTI_SZ;
2004 if (value.type == REG_NONE) {
2005 printf("Unknown data type: %s\n", argv[2]);
2006 result = WERR_INVALID_PARAM;
2007 goto done;
2010 /* get a printer handle */
2011 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2012 MAXIMUM_ALLOWED_ACCESS, servername,
2013 user, &pol);
2014 if (!W_ERROR_IS_OK(result))
2015 goto done;
2017 opened_hnd = True;
2019 ctr.printers_0 = &info;
2021 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2023 if (!W_ERROR_IS_OK(result))
2024 goto done;
2026 printf("%s\n", current_timestring(tmp_ctx, True));
2027 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2029 /* Set the printer data */
2031 fstrcpy(value.valuename, argv[3]);
2033 switch (value.type) {
2034 case REG_SZ: {
2035 UNISTR2 data;
2036 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2037 value.size = data.uni_str_len * 2;
2038 if (value.size) {
2039 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2040 value.size);
2041 } else {
2042 value.data_p = NULL;
2044 break;
2046 case REG_DWORD: {
2047 uint32 data = strtoul(argv[4], NULL, 10);
2048 value.size = sizeof(data);
2049 if (sizeof(data)) {
2050 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2051 sizeof(data));
2052 } else {
2053 value.data_p = NULL;
2055 break;
2057 case REG_BINARY: {
2058 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2059 value.data_p = data.data;
2060 value.size = data.length;
2061 break;
2063 case REG_MULTI_SZ: {
2064 int i;
2065 size_t len = 0;
2066 char *p;
2068 for (i=4; i<argc; i++) {
2069 if (strcmp(argv[i], "NULL") == 0) {
2070 argv[i] = "";
2072 len += strlen(argv[i])+1;
2075 value.size = len*2;
2076 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2077 if (value.data_p == NULL) {
2078 result = WERR_NOMEM;
2079 goto done;
2082 p = (char *)value.data_p;
2083 len = value.size;
2084 for (i=4; i<argc; i++) {
2085 size_t l = (strlen(argv[i])+1)*2;
2086 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2087 p += l;
2088 len -= l;
2090 SMB_ASSERT(len == 0);
2091 break;
2093 default:
2094 printf("Unknown data type: %s\n", argv[2]);
2095 result = WERR_INVALID_PARAM;
2096 goto done;
2099 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2101 if (!W_ERROR_IS_OK(result)) {
2102 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2103 goto done;
2105 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2107 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2109 if (!W_ERROR_IS_OK(result))
2110 goto done;
2112 printf("%s\n", current_timestring(tmp_ctx, True));
2113 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2115 done:
2116 /* cleanup */
2117 TALLOC_FREE(tmp_ctx);
2118 if (opened_hnd)
2119 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2121 return result;
2124 /****************************************************************************
2125 ****************************************************************************/
2127 static void display_job_info_1(JOB_INFO_1 *job)
2129 fstring username = "", document = "", text_status = "";
2131 rpcstr_pull(username, job->username.buffer,
2132 sizeof(username), -1, STR_TERMINATE);
2134 rpcstr_pull(document, job->document.buffer,
2135 sizeof(document), -1, STR_TERMINATE);
2137 rpcstr_pull(text_status, job->text_status.buffer,
2138 sizeof(text_status), -1, STR_TERMINATE);
2140 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2141 username, document, text_status, job->pagesprinted,
2142 job->totalpages);
2145 /****************************************************************************
2146 ****************************************************************************/
2148 static void display_job_info_2(JOB_INFO_2 *job)
2150 fstring username = "", document = "", text_status = "";
2152 rpcstr_pull(username, job->username.buffer,
2153 sizeof(username), -1, STR_TERMINATE);
2155 rpcstr_pull(document, job->document.buffer,
2156 sizeof(document), -1, STR_TERMINATE);
2158 rpcstr_pull(text_status, job->text_status.buffer,
2159 sizeof(text_status), -1, STR_TERMINATE);
2161 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2162 username, document, text_status, job->pagesprinted,
2163 job->totalpages, job->size);
2166 /****************************************************************************
2167 ****************************************************************************/
2169 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2170 TALLOC_CTX *mem_ctx, int argc,
2171 const char **argv)
2173 WERROR result;
2174 uint32 level = 1, num_jobs, i;
2175 bool got_hnd = False;
2176 char *printername = NULL;
2177 fstring servername, user;
2178 POLICY_HND hnd;
2179 JOB_INFO_CTR ctr;
2181 if (argc < 2 || argc > 3) {
2182 printf("Usage: %s printername [level]\n", argv[0]);
2183 return WERR_OK;
2186 if (argc == 3)
2187 level = atoi(argv[2]);
2189 /* Open printer handle */
2191 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2192 strupper_m(servername);
2193 fstrcpy(user, cli->user_name);
2194 printername = talloc_asprintf(mem_ctx,
2195 "\\\\%s\\",
2196 cli->cli->desthost);
2197 if (!printername) {
2198 return WERR_NOMEM;
2200 strupper_m(printername);
2201 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2202 if (!printername) {
2203 return WERR_NOMEM;
2206 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2207 "", MAXIMUM_ALLOWED_ACCESS,
2208 servername, user, &hnd);
2210 if (!W_ERROR_IS_OK(result))
2211 goto done;
2213 got_hnd = True;
2215 /* Enumerate ports */
2217 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2218 &num_jobs, &ctr);
2220 if (!W_ERROR_IS_OK(result))
2221 goto done;
2223 for (i = 0; i < num_jobs; i++) {
2224 switch(level) {
2225 case 1:
2226 display_job_info_1(&ctr.job.job_info_1[i]);
2227 break;
2228 case 2:
2229 display_job_info_2(&ctr.job.job_info_2[i]);
2230 break;
2231 default:
2232 d_printf("unknown info level %d\n", level);
2233 break;
2237 done:
2238 if (got_hnd)
2239 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2241 return result;
2244 /****************************************************************************
2245 ****************************************************************************/
2247 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2248 TALLOC_CTX *mem_ctx, int argc,
2249 const char **argv)
2251 WERROR result;
2252 uint32 i=0, val_needed, data_needed;
2253 bool got_hnd = False;
2254 char *printername = NULL;
2255 fstring servername, user;
2256 POLICY_HND hnd;
2258 if (argc != 2) {
2259 printf("Usage: %s printername\n", argv[0]);
2260 return WERR_OK;
2263 /* Open printer handle */
2265 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2266 strupper_m(servername);
2267 fstrcpy(user, cli->user_name);
2268 printername = talloc_asprintf(mem_ctx,
2269 "\\\\%s\\",
2270 cli->cli->desthost);
2271 if (!printername) {
2272 return WERR_NOMEM;
2274 strupper_m(printername);
2275 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2276 if (!printername) {
2277 return WERR_NOMEM;
2280 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2281 "", MAXIMUM_ALLOWED_ACCESS,
2282 servername, user, &hnd);
2284 if (!W_ERROR_IS_OK(result))
2285 goto done;
2287 got_hnd = True;
2289 /* Enumerate data */
2291 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2292 &val_needed, &data_needed,
2293 NULL);
2294 while (W_ERROR_IS_OK(result)) {
2295 REGISTRY_VALUE value;
2296 result = rpccli_spoolss_enumprinterdata(
2297 cli, mem_ctx, &hnd, i++, val_needed,
2298 data_needed, 0, 0, &value);
2299 if (W_ERROR_IS_OK(result))
2300 display_reg_value(value);
2302 if (W_ERROR_V(result) == ERRnomoreitems)
2303 result = W_ERROR(ERRsuccess);
2305 done:
2306 if (got_hnd)
2307 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2309 return result;
2312 /****************************************************************************
2313 ****************************************************************************/
2315 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2316 TALLOC_CTX *mem_ctx, int argc,
2317 const char **argv)
2319 WERROR result;
2320 uint32 i;
2321 bool got_hnd = False;
2322 char *printername = NULL;
2323 fstring servername, user;
2324 const char *keyname = NULL;
2325 POLICY_HND hnd;
2326 REGVAL_CTR *ctr = NULL;
2328 if (argc != 3) {
2329 printf("Usage: %s printername <keyname>\n", argv[0]);
2330 return WERR_OK;
2333 keyname = argv[2];
2335 /* Open printer handle */
2337 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2338 strupper_m(servername);
2339 fstrcpy(user, cli->user_name);
2341 printername = talloc_asprintf(mem_ctx,
2342 "\\\\%s\\",
2343 cli->cli->desthost);
2344 if (!printername) {
2345 return WERR_NOMEM;
2347 strupper_m(printername);
2348 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2349 if (!printername) {
2350 return WERR_NOMEM;
2353 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2354 "", MAXIMUM_ALLOWED_ACCESS,
2355 servername, user, &hnd);
2357 if (!W_ERROR_IS_OK(result))
2358 goto done;
2360 got_hnd = True;
2362 /* Enumerate subkeys */
2364 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2365 return WERR_NOMEM;
2367 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2369 if (!W_ERROR_IS_OK(result))
2370 goto done;
2372 for (i=0; i < ctr->num_values; i++) {
2373 display_reg_value(*(ctr->values[i]));
2376 TALLOC_FREE( ctr );
2378 done:
2379 if (got_hnd)
2380 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2382 return result;
2385 /****************************************************************************
2386 ****************************************************************************/
2388 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2389 TALLOC_CTX *mem_ctx, int argc,
2390 const char **argv)
2392 WERROR result;
2393 bool got_hnd = False;
2394 char *printername = NULL;
2395 fstring servername, user;
2396 const char *keyname = NULL;
2397 POLICY_HND hnd;
2398 uint16 *keylist = NULL, *curkey;
2400 if (argc < 2 || argc > 3) {
2401 printf("Usage: %s printername [keyname]\n", argv[0]);
2402 return WERR_OK;
2405 if (argc == 3)
2406 keyname = argv[2];
2407 else
2408 keyname = "";
2410 /* Open printer handle */
2412 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2413 strupper_m(servername);
2414 fstrcpy(user, cli->user_name);
2416 printername = talloc_asprintf(mem_ctx,
2417 "\\\\%s\\",
2418 cli->cli->desthost);
2419 if (!printername) {
2420 return WERR_NOMEM;
2422 strupper_m(printername);
2423 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2424 if (!printername) {
2425 return WERR_NOMEM;
2429 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2430 "", MAXIMUM_ALLOWED_ACCESS,
2431 servername, user, &hnd);
2433 if (!W_ERROR_IS_OK(result))
2434 goto done;
2436 got_hnd = True;
2438 /* Enumerate subkeys */
2440 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2442 if (!W_ERROR_IS_OK(result))
2443 goto done;
2445 curkey = keylist;
2446 while (*curkey != 0) {
2447 char *subkey = NULL;
2448 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2449 STR_TERMINATE);
2450 if (!subkey) {
2451 break;
2453 printf("%s\n", subkey);
2454 curkey += strlen(subkey) + 1;
2457 done:
2459 SAFE_FREE(keylist);
2461 if (got_hnd)
2462 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2464 return result;
2467 /****************************************************************************
2468 ****************************************************************************/
2470 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2471 TALLOC_CTX *mem_ctx, int argc,
2472 const char **argv)
2474 fstring servername, printername;
2475 POLICY_HND hnd;
2476 bool got_hnd = False;
2477 WERROR result;
2478 SPOOL_NOTIFY_OPTION option;
2480 if (argc != 2) {
2481 printf("Usage: %s printername\n", argv[0]);
2482 result = WERR_OK;
2483 goto done;
2486 /* Open printer */
2488 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2489 strupper_m(servername);
2491 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2492 argv[1]);
2493 strupper_m(printername);
2495 result = rpccli_spoolss_open_printer_ex(
2496 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2497 servername, cli->user_name, &hnd);
2499 if (!W_ERROR_IS_OK(result)) {
2500 printf("Error opening %s\n", argv[1]);
2501 goto done;
2504 got_hnd = True;
2506 /* Create spool options */
2508 ZERO_STRUCT(option);
2510 option.version = 2;
2511 option.option_type_ptr = 1;
2512 option.count = option.ctr.count = 2;
2514 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2515 if (option.ctr.type == NULL) {
2516 result = WERR_NOMEM;
2517 goto done;
2520 ZERO_STRUCT(option.ctr.type[0]);
2521 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2522 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2523 option.ctr.type[0].fields_ptr = 1;
2524 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2526 ZERO_STRUCT(option.ctr.type[1]);
2527 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2528 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2529 option.ctr.type[1].fields_ptr = 1;
2530 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2532 /* Send rffpcnex */
2534 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2535 strupper_m(servername);
2537 result = rpccli_spoolss_rffpcnex(
2538 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2540 if (!W_ERROR_IS_OK(result)) {
2541 printf("Error rffpcnex %s\n", argv[1]);
2542 goto done;
2545 done:
2546 if (got_hnd)
2547 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2549 return result;
2552 /****************************************************************************
2553 ****************************************************************************/
2555 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2556 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2558 PRINTER_INFO_CTR ctr1, ctr2;
2559 WERROR werror;
2560 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2562 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2563 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2564 if ( !W_ERROR_IS_OK(werror) ) {
2565 printf("failed (%s)\n", dos_errstr(werror));
2566 talloc_destroy(mem_ctx);
2567 return False;
2569 printf("ok\n");
2571 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2572 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2573 if ( !W_ERROR_IS_OK(werror) ) {
2574 printf("failed (%s)\n", dos_errstr(werror));
2575 talloc_destroy(mem_ctx);
2576 return False;
2578 printf("ok\n");
2580 talloc_destroy(mem_ctx);
2582 return True;
2585 /****************************************************************************
2586 ****************************************************************************/
2588 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2589 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2591 PRINTER_INFO_CTR ctr1, ctr2;
2592 WERROR werror;
2593 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2594 SEC_DESC *sd1, *sd2;
2595 bool result = True;
2598 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2599 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2600 if ( !W_ERROR_IS_OK(werror) ) {
2601 printf("failed (%s)\n", dos_errstr(werror));
2602 result = False;
2603 goto done;
2605 printf("ok\n");
2607 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2608 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2609 if ( !W_ERROR_IS_OK(werror) ) {
2610 printf("failed (%s)\n", dos_errstr(werror));
2611 result = False;
2612 goto done;
2614 printf("ok\n");
2617 printf("++ ");
2619 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2620 printf("NULL PRINTER_INFO_3!\n");
2621 result = False;
2622 goto done;
2625 sd1 = ctr1.printers_3->secdesc;
2626 sd2 = ctr2.printers_3->secdesc;
2628 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2629 printf("NULL secdesc!\n");
2630 result = False;
2631 goto done;
2634 if (!sec_desc_equal( sd1, sd2 ) ) {
2635 printf("Security Descriptors *not* equal!\n");
2636 result = False;
2637 goto done;
2640 printf("Security descriptors match\n");
2642 done:
2643 talloc_destroy(mem_ctx);
2644 return result;
2648 /****************************************************************************
2649 ****************************************************************************/
2651 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2652 TALLOC_CTX *mem_ctx, int argc,
2653 const char **argv)
2655 fstring printername, servername1, servername2;
2656 char *printername_path = NULL;
2657 struct cli_state *cli_server1 = cli->cli;
2658 struct cli_state *cli_server2 = NULL;
2659 struct rpc_pipe_client *cli2 = NULL;
2660 POLICY_HND hPrinter1, hPrinter2;
2661 NTSTATUS nt_status;
2662 WERROR werror;
2664 if ( argc != 3 ) {
2665 printf("Usage: %s <printer> <server>\n", argv[0]);
2666 return WERR_OK;
2669 fstrcpy( printername, argv[1] );
2671 fstrcpy( servername1, cli->cli->desthost );
2672 fstrcpy( servername2, argv[2] );
2673 strupper_m( servername1 );
2674 strupper_m( servername2 );
2676 /* first get the connection to the remote server */
2678 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2679 NULL, 0,
2680 "IPC$", "IPC",
2681 get_cmdline_auth_info_username(),
2682 lp_workgroup(),
2683 get_cmdline_auth_info_password(),
2684 get_cmdline_auth_info_use_kerberos() ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2685 get_cmdline_auth_info_signing_state(), NULL);
2687 if ( !NT_STATUS_IS_OK(nt_status) )
2688 return WERR_GENERAL_FAILURE;
2690 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2691 if (!cli2) {
2692 printf("failed to open spoolss pipe on server %s (%s)\n",
2693 servername2, nt_errstr(nt_status));
2694 return WERR_GENERAL_FAILURE;
2697 /* now open up both printers */
2699 printername_path = talloc_asprintf(mem_ctx,
2700 "\\\\%s\\%s",
2701 servername1,
2702 printername);
2703 if (!printername_path) {
2704 return WERR_NOMEM;
2706 printf("Opening %s...", printername_path);
2707 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2708 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2709 if ( !W_ERROR_IS_OK(werror) ) {
2710 printf("failed (%s)\n", dos_errstr(werror));
2711 goto done;
2713 printf("ok\n");
2715 printername_path = talloc_asprintf(mem_ctx,
2716 "\\\\%s\\%s",
2717 servername2,
2718 printername);
2719 if (!printername_path) {
2720 return WERR_NOMEM;
2722 printf("Opening %s...", printername_path);
2723 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2724 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2725 if ( !W_ERROR_IS_OK(werror) ) {
2726 printf("failed (%s)\n", dos_errstr(werror));
2727 goto done;
2729 printf("ok\n");
2731 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2732 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2733 #if 0
2734 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2735 #endif
2738 done:
2739 /* cleanup */
2741 printf("Closing printers...");
2742 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2743 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2744 printf("ok\n");
2746 /* close the second remote connection */
2748 cli_shutdown( cli_server2 );
2749 return WERR_OK;
2752 /* List of commands exported by this module */
2753 struct cmd_set spoolss_commands[] = {
2755 { "SPOOLSS" },
2757 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2758 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2759 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2760 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2761 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2762 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2763 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2764 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2765 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2766 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2767 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2768 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2769 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2770 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2771 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2772 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2773 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2774 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2775 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2776 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2777 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2778 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2779 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2780 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2781 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2782 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2783 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2784 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2785 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },
2787 { NULL }