net: use NetUserDel for "net rpc user delete".
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_spoolss.c
blob7530ab191128e6e8fa2068bae95b4d933417c812
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)
1224 char *ptr;
1225 char *saveptr;
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);
1259 str = get_driver_3_param (NULL, ":", &info->driverpath);
1260 str = get_driver_3_param (NULL, ":", &info->datafile);
1261 str = get_driver_3_param (NULL, ":", &info->configfile);
1262 str = get_driver_3_param (NULL, ":", &info->helpfile);
1263 str = get_driver_3_param (NULL, ":", &info->monitorname);
1264 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1266 /* <Comma Separated List of Dependent Files> */
1267 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1268 str = str2;
1270 /* begin to strip out each filename */
1271 str = strtok_r(str, ",", &saveptr);
1272 len = 0;
1273 while (str != NULL)
1275 /* keep a cumlative count of the str lengths */
1276 len += strlen(str)+1;
1277 str = strtok_r(NULL, ",", &saveptr);
1280 /* allocate the space; add one extra slot for a terminating NULL.
1281 Each filename is NULL terminated and the end contains a double
1282 NULL */
1283 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1285 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1286 return False;
1288 for (i=0; i<len; i++)
1290 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1292 info->dependentfiles[len] = '\0';
1294 return True;
1298 /****************************************************************************
1299 ****************************************************************************/
1301 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1302 TALLOC_CTX *mem_ctx,
1303 int argc, const char **argv)
1305 WERROR result;
1306 uint32 level = 3;
1307 PRINTER_DRIVER_CTR ctr;
1308 DRIVER_INFO_3 info3;
1309 const char *arch;
1310 fstring driver_name;
1311 char *driver_args;
1313 /* parse the command arguements */
1314 if (argc != 3 && argc != 4)
1316 printf ("Usage: %s <Environment> \\\n", argv[0]);
1317 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1318 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1319 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1320 printf ("\t[version]\n");
1322 return WERR_OK;
1325 /* Fill in the DRIVER_INFO_3 struct */
1326 ZERO_STRUCT(info3);
1327 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1329 printf ("Error Unknown architechture [%s]\n", argv[1]);
1330 return WERR_INVALID_PARAM;
1332 else
1333 set_drv_info_3_env(&info3, arch);
1335 driver_args = talloc_strdup( mem_ctx, argv[2] );
1336 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1338 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1339 return WERR_INVALID_PARAM;
1342 /* if printer driver version specified, override the default version
1343 * used by the architecture. This allows installation of Windows
1344 * 2000 (version 3) printer drivers. */
1345 if (argc == 4)
1347 info3.version = atoi(argv[3]);
1351 ctr.info3 = &info3;
1352 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1354 if (W_ERROR_IS_OK(result)) {
1355 rpcstr_pull(driver_name, info3.name.buffer,
1356 sizeof(driver_name), -1, STR_TERMINATE);
1357 printf ("Printer Driver %s successfully installed.\n",
1358 driver_name);
1361 return result;
1365 /****************************************************************************
1366 ****************************************************************************/
1368 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1369 TALLOC_CTX *mem_ctx,
1370 int argc, const char **argv)
1372 WERROR result;
1373 uint32 level = 2;
1374 PRINTER_INFO_CTR ctr;
1375 PRINTER_INFO_2 info2;
1376 fstring servername;
1378 /* parse the command arguements */
1379 if (argc != 5)
1381 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1382 return WERR_OK;
1385 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1386 strupper_m(servername);
1388 /* Fill in the DRIVER_INFO_2 struct */
1389 ZERO_STRUCT(info2);
1391 init_unistr( &info2.printername, argv[1]);
1392 init_unistr( &info2.sharename, argv[2]);
1393 init_unistr( &info2.drivername, argv[3]);
1394 init_unistr( &info2.portname, argv[4]);
1395 init_unistr( &info2.comment, "Created by rpcclient");
1396 init_unistr( &info2.printprocessor, "winprint");
1397 init_unistr( &info2.datatype, "RAW");
1398 info2.devmode = NULL;
1399 info2.secdesc = NULL;
1400 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1401 info2.priority = 0;
1402 info2.defaultpriority = 0;
1403 info2.starttime = 0;
1404 info2.untiltime = 0;
1406 /* These three fields must not be used by AddPrinter()
1407 as defined in the MS Platform SDK documentation..
1408 --jerry
1409 info2.status = 0;
1410 info2.cjobs = 0;
1411 info2.averageppm = 0;
1414 ctr.printers_2 = &info2;
1415 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1417 if (W_ERROR_IS_OK(result))
1418 printf ("Printer %s successfully installed.\n", argv[1]);
1420 return result;
1423 /****************************************************************************
1424 ****************************************************************************/
1426 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1427 TALLOC_CTX *mem_ctx,
1428 int argc, const char **argv)
1430 POLICY_HND pol;
1431 WERROR result;
1432 uint32 level = 2;
1433 bool opened_hnd = False;
1434 PRINTER_INFO_CTR ctr;
1435 PRINTER_INFO_2 info2;
1436 fstring servername,
1437 printername,
1438 user;
1440 /* parse the command arguements */
1441 if (argc != 3)
1443 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1444 return WERR_OK;
1447 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1448 strupper_m(servername);
1449 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1450 fstrcpy(user, cli->user_name);
1452 /* Get a printer handle */
1454 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1455 PRINTER_ALL_ACCESS,
1456 servername, user, &pol);
1458 if (!W_ERROR_IS_OK(result))
1459 goto done;
1461 opened_hnd = True;
1463 /* Get printer info */
1465 ZERO_STRUCT (info2);
1466 ctr.printers_2 = &info2;
1468 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1470 if (!W_ERROR_IS_OK(result)) {
1471 printf ("Unable to retrieve printer information!\n");
1472 goto done;
1475 /* Set the printer driver */
1477 init_unistr(&ctr.printers_2->drivername, argv[2]);
1479 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1481 if (!W_ERROR_IS_OK(result)) {
1482 printf("SetPrinter call failed!\n");
1483 goto done;;
1486 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1488 done:
1489 /* Cleanup */
1491 if (opened_hnd)
1492 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1494 return result;
1498 /****************************************************************************
1499 ****************************************************************************/
1501 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1502 TALLOC_CTX *mem_ctx,
1503 int argc, const char **argv)
1505 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1507 int i;
1508 int vers = -1;
1510 const char *arch = NULL;
1512 /* parse the command arguements */
1513 if (argc < 2 || argc > 4) {
1514 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1515 return WERR_OK;
1518 if (argc >= 3)
1519 arch = argv[2];
1520 if (argc == 4)
1521 vers = atoi (argv[3]);
1524 /* delete the driver for all architectures */
1525 for (i=0; archi_table[i].long_archi; i++) {
1527 if (arch && !strequal( archi_table[i].long_archi, arch))
1528 continue;
1530 if (vers >= 0 && archi_table[i].version != vers)
1531 continue;
1533 /* make the call to remove the driver */
1534 result = rpccli_spoolss_deleteprinterdriverex(
1535 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1537 if ( !W_ERROR_IS_OK(result) )
1539 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1540 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1541 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1544 else
1546 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1547 archi_table[i].long_archi, archi_table[i].version);
1548 ret = WERR_OK;
1552 return ret;
1556 /****************************************************************************
1557 ****************************************************************************/
1559 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1560 TALLOC_CTX *mem_ctx,
1561 int argc, const char **argv)
1563 WERROR result = WERR_OK;
1564 fstring servername;
1565 int i;
1567 /* parse the command arguements */
1568 if (argc != 2) {
1569 printf ("Usage: %s <driver>\n", argv[0]);
1570 return WERR_OK;
1573 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1574 strupper_m(servername);
1576 /* delete the driver for all architectures */
1577 for (i=0; archi_table[i].long_archi; i++) {
1578 /* make the call to remove the driver */
1579 result = rpccli_spoolss_deleteprinterdriver(
1580 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1582 if ( !W_ERROR_IS_OK(result) ) {
1583 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1584 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1585 argv[1], archi_table[i].long_archi,
1586 W_ERROR_V(result));
1588 } else {
1589 printf ("Driver %s removed for arch [%s].\n", argv[1],
1590 archi_table[i].long_archi);
1594 return result;
1597 /****************************************************************************
1598 ****************************************************************************/
1600 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1601 TALLOC_CTX *mem_ctx,
1602 int argc, const char **argv)
1604 WERROR result;
1605 char *servername = NULL, *environment = NULL;
1606 fstring procdir;
1608 /* parse the command arguements */
1609 if (argc > 2) {
1610 printf ("Usage: %s [environment]\n", argv[0]);
1611 return WERR_OK;
1614 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1615 return WERR_NOMEM;
1616 strupper_m(servername);
1618 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1619 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1620 SAFE_FREE(servername);
1621 return WERR_NOMEM;
1624 result = rpccli_spoolss_getprintprocessordirectory(
1625 cli, mem_ctx, servername, environment, procdir);
1627 if (W_ERROR_IS_OK(result))
1628 printf("%s\n", procdir);
1630 SAFE_FREE(servername);
1631 SAFE_FREE(environment);
1633 return result;
1636 /****************************************************************************
1637 ****************************************************************************/
1639 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1640 int argc, const char **argv)
1642 POLICY_HND handle;
1643 WERROR werror;
1644 char *servername = NULL, *printername = NULL;
1645 FORM form;
1646 bool got_handle = False;
1648 /* Parse the command arguements */
1650 if (argc != 3) {
1651 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1652 return WERR_OK;
1655 /* Get a printer handle */
1657 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1658 strupper_m(servername);
1659 asprintf(&printername, "%s\\%s", servername, argv[1]);
1661 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1662 PRINTER_ALL_ACCESS,
1663 servername, cli->user_name, &handle);
1665 if (!W_ERROR_IS_OK(werror))
1666 goto done;
1668 got_handle = True;
1670 /* Dummy up some values for the form data */
1672 form.flags = FORM_USER;
1673 form.size_x = form.size_y = 100;
1674 form.left = 0;
1675 form.top = 10;
1676 form.right = 20;
1677 form.bottom = 30;
1679 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1681 /* Add the form */
1684 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1686 done:
1687 if (got_handle)
1688 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1690 SAFE_FREE(servername);
1691 SAFE_FREE(printername);
1693 return werror;
1696 /****************************************************************************
1697 ****************************************************************************/
1699 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1700 int argc, const char **argv)
1702 POLICY_HND handle;
1703 WERROR werror;
1704 char *servername = NULL, *printername = NULL;
1705 FORM form;
1706 bool got_handle = False;
1708 /* Parse the command arguements */
1710 if (argc != 3) {
1711 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1712 return WERR_OK;
1715 /* Get a printer handle */
1717 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1718 strupper_m(servername);
1719 asprintf(&printername, "%s\\%s", servername, argv[1]);
1721 werror = rpccli_spoolss_open_printer_ex(
1722 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1723 servername, cli->user_name, &handle);
1725 if (!W_ERROR_IS_OK(werror))
1726 goto done;
1728 got_handle = True;
1730 /* Dummy up some values for the form data */
1732 form.flags = FORM_PRINTER;
1733 form.size_x = form.size_y = 100;
1734 form.left = 0;
1735 form.top = 1000;
1736 form.right = 2000;
1737 form.bottom = 3000;
1739 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1741 /* Set the form */
1743 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1745 done:
1746 if (got_handle)
1747 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1749 SAFE_FREE(servername);
1750 SAFE_FREE(printername);
1752 return werror;
1755 /****************************************************************************
1756 ****************************************************************************/
1758 static const char *get_form_flag(int form_flag)
1760 switch (form_flag) {
1761 case FORM_USER:
1762 return "FORM_USER";
1763 case FORM_BUILTIN:
1764 return "FORM_BUILTIN";
1765 case FORM_PRINTER:
1766 return "FORM_PRINTER";
1767 default:
1768 return "unknown";
1772 /****************************************************************************
1773 ****************************************************************************/
1775 static void display_form(FORM_1 *form)
1777 fstring form_name = "";
1779 if (form->name.buffer)
1780 rpcstr_pull(form_name, form->name.buffer,
1781 sizeof(form_name), -1, STR_TERMINATE);
1783 printf("%s\n" \
1784 "\tflag: %s (%d)\n" \
1785 "\twidth: %d, length: %d\n" \
1786 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1787 form_name, get_form_flag(form->flag), form->flag,
1788 form->width, form->length,
1789 form->left, form->right,
1790 form->top, form->bottom);
1793 /****************************************************************************
1794 ****************************************************************************/
1796 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1797 int argc, const char **argv)
1799 POLICY_HND handle;
1800 WERROR werror;
1801 char *servername = NULL, *printername = NULL;
1802 FORM_1 form;
1803 bool got_handle = False;
1805 /* Parse the command arguements */
1807 if (argc != 3) {
1808 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1809 return WERR_OK;
1812 /* Get a printer handle */
1814 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1815 strupper_m(servername);
1816 asprintf(&printername, "%s\\%s", servername, argv[1]);
1818 werror = rpccli_spoolss_open_printer_ex(
1819 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1820 servername, cli->user_name, &handle);
1822 if (!W_ERROR_IS_OK(werror))
1823 goto done;
1825 got_handle = True;
1827 /* Get the form */
1829 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1831 if (!W_ERROR_IS_OK(werror))
1832 goto done;
1834 display_form(&form);
1836 done:
1837 if (got_handle)
1838 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1840 SAFE_FREE(servername);
1841 SAFE_FREE(printername);
1843 return werror;
1846 /****************************************************************************
1847 ****************************************************************************/
1849 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1850 TALLOC_CTX *mem_ctx, int argc,
1851 const char **argv)
1853 POLICY_HND handle;
1854 WERROR werror;
1855 char *servername = NULL, *printername = NULL;
1856 bool got_handle = False;
1858 /* Parse the command arguements */
1860 if (argc != 3) {
1861 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1862 return WERR_OK;
1865 /* Get a printer handle */
1867 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1868 strupper_m(servername);
1869 asprintf(&printername, "%s\\%s", servername, argv[1]);
1871 werror = rpccli_spoolss_open_printer_ex(
1872 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1873 servername, cli->user_name, &handle);
1875 if (!W_ERROR_IS_OK(werror))
1876 goto done;
1878 got_handle = True;
1880 /* Delete the form */
1882 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1884 done:
1885 if (got_handle)
1886 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1888 SAFE_FREE(servername);
1889 SAFE_FREE(printername);
1891 return werror;
1894 /****************************************************************************
1895 ****************************************************************************/
1897 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1898 TALLOC_CTX *mem_ctx, int argc,
1899 const char **argv)
1901 POLICY_HND handle;
1902 WERROR werror;
1903 char *servername = NULL, *printername = NULL;
1904 bool got_handle = False;
1905 uint32 num_forms, level = 1, i;
1906 FORM_1 *forms;
1908 /* Parse the command arguements */
1910 if (argc != 2) {
1911 printf ("Usage: %s <printer>\n", argv[0]);
1912 return WERR_OK;
1915 /* Get a printer handle */
1917 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1918 strupper_m(servername);
1919 asprintf(&printername, "%s\\%s", servername, argv[1]);
1921 werror = rpccli_spoolss_open_printer_ex(
1922 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1923 servername, cli->user_name, &handle);
1925 if (!W_ERROR_IS_OK(werror))
1926 goto done;
1928 got_handle = True;
1930 /* Enumerate forms */
1932 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1934 if (!W_ERROR_IS_OK(werror))
1935 goto done;
1937 /* Display output */
1939 for (i = 0; i < num_forms; i++) {
1941 display_form(&forms[i]);
1945 done:
1946 if (got_handle)
1947 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1949 SAFE_FREE(servername);
1950 SAFE_FREE(printername);
1952 return werror;
1955 /****************************************************************************
1956 ****************************************************************************/
1958 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1959 TALLOC_CTX *mem_ctx,
1960 int argc, const char **argv)
1962 WERROR result;
1963 fstring servername, printername, user;
1964 POLICY_HND pol;
1965 bool opened_hnd = False;
1966 PRINTER_INFO_CTR ctr;
1967 PRINTER_INFO_0 info;
1968 REGISTRY_VALUE value;
1969 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1971 /* parse the command arguements */
1972 if (argc < 5) {
1973 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1974 " <value> <data>\n",
1975 argv[0]);
1976 result = WERR_INVALID_PARAM;
1977 goto done;
1980 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1981 strupper_m(servername);
1982 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1983 fstrcpy(user, cli->user_name);
1985 value.type = REG_NONE;
1987 if (strequal(argv[2], "string")) {
1988 value.type = REG_SZ;
1991 if (strequal(argv[2], "binary")) {
1992 value.type = REG_BINARY;
1995 if (strequal(argv[2], "dword")) {
1996 value.type = REG_DWORD;
1999 if (strequal(argv[2], "multistring")) {
2000 value.type = REG_MULTI_SZ;
2003 if (value.type == REG_NONE) {
2004 printf("Unknown data type: %s\n", argv[2]);
2005 result = WERR_INVALID_PARAM;
2006 goto done;
2009 /* get a printer handle */
2010 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2011 MAXIMUM_ALLOWED_ACCESS, servername,
2012 user, &pol);
2013 if (!W_ERROR_IS_OK(result))
2014 goto done;
2016 opened_hnd = True;
2018 ctr.printers_0 = &info;
2020 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2022 if (!W_ERROR_IS_OK(result))
2023 goto done;
2025 printf("%s\n", current_timestring(tmp_ctx, True));
2026 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2028 /* Set the printer data */
2030 fstrcpy(value.valuename, argv[3]);
2032 switch (value.type) {
2033 case REG_SZ: {
2034 UNISTR2 data;
2035 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2036 value.size = data.uni_str_len * 2;
2037 if (value.size) {
2038 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2039 value.size);
2040 } else {
2041 value.data_p = NULL;
2043 break;
2045 case REG_DWORD: {
2046 uint32 data = strtoul(argv[4], NULL, 10);
2047 value.size = sizeof(data);
2048 if (sizeof(data)) {
2049 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2050 sizeof(data));
2051 } else {
2052 value.data_p = NULL;
2054 break;
2056 case REG_BINARY: {
2057 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2058 value.data_p = data.data;
2059 value.size = data.length;
2060 break;
2062 case REG_MULTI_SZ: {
2063 int i;
2064 size_t len = 0;
2065 char *p;
2067 for (i=4; i<argc; i++) {
2068 if (strcmp(argv[i], "NULL") == 0) {
2069 argv[i] = "";
2071 len += strlen(argv[i])+1;
2074 value.size = len*2;
2075 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2076 if (value.data_p == NULL) {
2077 result = WERR_NOMEM;
2078 goto done;
2081 p = (char *)value.data_p;
2082 len = value.size;
2083 for (i=4; i<argc; i++) {
2084 size_t l = (strlen(argv[i])+1)*2;
2085 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2086 p += l;
2087 len -= l;
2089 SMB_ASSERT(len == 0);
2090 break;
2092 default:
2093 printf("Unknown data type: %s\n", argv[2]);
2094 result = WERR_INVALID_PARAM;
2095 goto done;
2098 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2100 if (!W_ERROR_IS_OK(result)) {
2101 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2102 goto done;
2104 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2106 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2108 if (!W_ERROR_IS_OK(result))
2109 goto done;
2111 printf("%s\n", current_timestring(tmp_ctx, True));
2112 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2114 done:
2115 /* cleanup */
2116 TALLOC_FREE(tmp_ctx);
2117 if (opened_hnd)
2118 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2120 return result;
2123 /****************************************************************************
2124 ****************************************************************************/
2126 static void display_job_info_1(JOB_INFO_1 *job)
2128 fstring username = "", document = "", text_status = "";
2130 rpcstr_pull(username, job->username.buffer,
2131 sizeof(username), -1, STR_TERMINATE);
2133 rpcstr_pull(document, job->document.buffer,
2134 sizeof(document), -1, STR_TERMINATE);
2136 rpcstr_pull(text_status, job->text_status.buffer,
2137 sizeof(text_status), -1, STR_TERMINATE);
2139 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2140 username, document, text_status, job->pagesprinted,
2141 job->totalpages);
2144 /****************************************************************************
2145 ****************************************************************************/
2147 static void display_job_info_2(JOB_INFO_2 *job)
2149 fstring username = "", document = "", text_status = "";
2151 rpcstr_pull(username, job->username.buffer,
2152 sizeof(username), -1, STR_TERMINATE);
2154 rpcstr_pull(document, job->document.buffer,
2155 sizeof(document), -1, STR_TERMINATE);
2157 rpcstr_pull(text_status, job->text_status.buffer,
2158 sizeof(text_status), -1, STR_TERMINATE);
2160 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2161 username, document, text_status, job->pagesprinted,
2162 job->totalpages, job->size);
2165 /****************************************************************************
2166 ****************************************************************************/
2168 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2169 TALLOC_CTX *mem_ctx, int argc,
2170 const char **argv)
2172 WERROR result;
2173 uint32 level = 1, num_jobs, i;
2174 bool got_hnd = False;
2175 char *printername = NULL;
2176 fstring servername, user;
2177 POLICY_HND hnd;
2178 JOB_INFO_CTR ctr;
2180 if (argc < 2 || argc > 3) {
2181 printf("Usage: %s printername [level]\n", argv[0]);
2182 return WERR_OK;
2185 if (argc == 3)
2186 level = atoi(argv[2]);
2188 /* Open printer handle */
2190 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2191 strupper_m(servername);
2192 fstrcpy(user, cli->user_name);
2193 printername = talloc_asprintf(mem_ctx,
2194 "\\\\%s\\",
2195 cli->cli->desthost);
2196 if (!printername) {
2197 return WERR_NOMEM;
2199 strupper_m(printername);
2200 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2201 if (!printername) {
2202 return WERR_NOMEM;
2205 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2206 "", MAXIMUM_ALLOWED_ACCESS,
2207 servername, user, &hnd);
2209 if (!W_ERROR_IS_OK(result))
2210 goto done;
2212 got_hnd = True;
2214 /* Enumerate ports */
2216 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2217 &num_jobs, &ctr);
2219 if (!W_ERROR_IS_OK(result))
2220 goto done;
2222 for (i = 0; i < num_jobs; i++) {
2223 switch(level) {
2224 case 1:
2225 display_job_info_1(&ctr.job.job_info_1[i]);
2226 break;
2227 case 2:
2228 display_job_info_2(&ctr.job.job_info_2[i]);
2229 break;
2230 default:
2231 d_printf("unknown info level %d\n", level);
2232 break;
2236 done:
2237 if (got_hnd)
2238 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2240 return result;
2243 /****************************************************************************
2244 ****************************************************************************/
2246 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2247 TALLOC_CTX *mem_ctx, int argc,
2248 const char **argv)
2250 WERROR result;
2251 uint32 i=0, val_needed, data_needed;
2252 bool got_hnd = False;
2253 char *printername = NULL;
2254 fstring servername, user;
2255 POLICY_HND hnd;
2257 if (argc != 2) {
2258 printf("Usage: %s printername\n", argv[0]);
2259 return WERR_OK;
2262 /* Open printer handle */
2264 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2265 strupper_m(servername);
2266 fstrcpy(user, cli->user_name);
2267 printername = talloc_asprintf(mem_ctx,
2268 "\\\\%s\\",
2269 cli->cli->desthost);
2270 if (!printername) {
2271 return WERR_NOMEM;
2273 strupper_m(printername);
2274 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2275 if (!printername) {
2276 return WERR_NOMEM;
2279 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2280 "", MAXIMUM_ALLOWED_ACCESS,
2281 servername, user, &hnd);
2283 if (!W_ERROR_IS_OK(result))
2284 goto done;
2286 got_hnd = True;
2288 /* Enumerate data */
2290 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2291 &val_needed, &data_needed,
2292 NULL);
2293 while (W_ERROR_IS_OK(result)) {
2294 REGISTRY_VALUE value;
2295 result = rpccli_spoolss_enumprinterdata(
2296 cli, mem_ctx, &hnd, i++, val_needed,
2297 data_needed, 0, 0, &value);
2298 if (W_ERROR_IS_OK(result))
2299 display_reg_value(value);
2301 if (W_ERROR_V(result) == ERRnomoreitems)
2302 result = W_ERROR(ERRsuccess);
2304 done:
2305 if (got_hnd)
2306 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2308 return result;
2311 /****************************************************************************
2312 ****************************************************************************/
2314 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2315 TALLOC_CTX *mem_ctx, int argc,
2316 const char **argv)
2318 WERROR result;
2319 uint32 i;
2320 bool got_hnd = False;
2321 char *printername = NULL;
2322 fstring servername, user;
2323 const char *keyname = NULL;
2324 POLICY_HND hnd;
2325 REGVAL_CTR *ctr = NULL;
2327 if (argc != 3) {
2328 printf("Usage: %s printername <keyname>\n", argv[0]);
2329 return WERR_OK;
2332 keyname = argv[2];
2334 /* Open printer handle */
2336 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2337 strupper_m(servername);
2338 fstrcpy(user, cli->user_name);
2340 printername = talloc_asprintf(mem_ctx,
2341 "\\\\%s\\",
2342 cli->cli->desthost);
2343 if (!printername) {
2344 return WERR_NOMEM;
2346 strupper_m(printername);
2347 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2348 if (!printername) {
2349 return WERR_NOMEM;
2352 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2353 "", MAXIMUM_ALLOWED_ACCESS,
2354 servername, user, &hnd);
2356 if (!W_ERROR_IS_OK(result))
2357 goto done;
2359 got_hnd = True;
2361 /* Enumerate subkeys */
2363 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2364 return WERR_NOMEM;
2366 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2368 if (!W_ERROR_IS_OK(result))
2369 goto done;
2371 for (i=0; i < ctr->num_values; i++) {
2372 display_reg_value(*(ctr->values[i]));
2375 TALLOC_FREE( ctr );
2377 done:
2378 if (got_hnd)
2379 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2381 return result;
2384 /****************************************************************************
2385 ****************************************************************************/
2387 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2388 TALLOC_CTX *mem_ctx, int argc,
2389 const char **argv)
2391 WERROR result;
2392 bool got_hnd = False;
2393 char *printername = NULL;
2394 fstring servername, user;
2395 const char *keyname = NULL;
2396 POLICY_HND hnd;
2397 uint16 *keylist = NULL, *curkey;
2399 if (argc < 2 || argc > 3) {
2400 printf("Usage: %s printername [keyname]\n", argv[0]);
2401 return WERR_OK;
2404 if (argc == 3)
2405 keyname = argv[2];
2406 else
2407 keyname = "";
2409 /* Open printer handle */
2411 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2412 strupper_m(servername);
2413 fstrcpy(user, cli->user_name);
2415 printername = talloc_asprintf(mem_ctx,
2416 "\\\\%s\\",
2417 cli->cli->desthost);
2418 if (!printername) {
2419 return WERR_NOMEM;
2421 strupper_m(printername);
2422 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2423 if (!printername) {
2424 return WERR_NOMEM;
2428 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2429 "", MAXIMUM_ALLOWED_ACCESS,
2430 servername, user, &hnd);
2432 if (!W_ERROR_IS_OK(result))
2433 goto done;
2435 got_hnd = True;
2437 /* Enumerate subkeys */
2439 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2441 if (!W_ERROR_IS_OK(result))
2442 goto done;
2444 curkey = keylist;
2445 while (*curkey != 0) {
2446 char *subkey = NULL;
2447 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2448 STR_TERMINATE);
2449 if (!subkey) {
2450 break;
2452 printf("%s\n", subkey);
2453 curkey += strlen(subkey) + 1;
2456 done:
2458 SAFE_FREE(keylist);
2460 if (got_hnd)
2461 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2463 return result;
2466 /****************************************************************************
2467 ****************************************************************************/
2469 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2470 TALLOC_CTX *mem_ctx, int argc,
2471 const char **argv)
2473 fstring servername, printername;
2474 POLICY_HND hnd;
2475 bool got_hnd = False;
2476 WERROR result;
2477 SPOOL_NOTIFY_OPTION option;
2479 if (argc != 2) {
2480 printf("Usage: %s printername\n", argv[0]);
2481 result = WERR_OK;
2482 goto done;
2485 /* Open printer */
2487 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2488 strupper_m(servername);
2490 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2491 argv[1]);
2492 strupper_m(printername);
2494 result = rpccli_spoolss_open_printer_ex(
2495 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2496 servername, cli->user_name, &hnd);
2498 if (!W_ERROR_IS_OK(result)) {
2499 printf("Error opening %s\n", argv[1]);
2500 goto done;
2503 got_hnd = True;
2505 /* Create spool options */
2507 ZERO_STRUCT(option);
2509 option.version = 2;
2510 option.option_type_ptr = 1;
2511 option.count = option.ctr.count = 2;
2513 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2514 if (option.ctr.type == NULL) {
2515 result = WERR_NOMEM;
2516 goto done;
2519 ZERO_STRUCT(option.ctr.type[0]);
2520 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2521 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2522 option.ctr.type[0].fields_ptr = 1;
2523 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2525 ZERO_STRUCT(option.ctr.type[1]);
2526 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2527 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2528 option.ctr.type[1].fields_ptr = 1;
2529 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2531 /* Send rffpcnex */
2533 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2534 strupper_m(servername);
2536 result = rpccli_spoolss_rffpcnex(
2537 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2539 if (!W_ERROR_IS_OK(result)) {
2540 printf("Error rffpcnex %s\n", argv[1]);
2541 goto done;
2544 done:
2545 if (got_hnd)
2546 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2548 return result;
2551 /****************************************************************************
2552 ****************************************************************************/
2554 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2555 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2557 PRINTER_INFO_CTR ctr1, ctr2;
2558 WERROR werror;
2559 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2561 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2562 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2563 if ( !W_ERROR_IS_OK(werror) ) {
2564 printf("failed (%s)\n", dos_errstr(werror));
2565 talloc_destroy(mem_ctx);
2566 return False;
2568 printf("ok\n");
2570 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2571 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2572 if ( !W_ERROR_IS_OK(werror) ) {
2573 printf("failed (%s)\n", dos_errstr(werror));
2574 talloc_destroy(mem_ctx);
2575 return False;
2577 printf("ok\n");
2579 talloc_destroy(mem_ctx);
2581 return True;
2584 /****************************************************************************
2585 ****************************************************************************/
2587 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2588 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2590 PRINTER_INFO_CTR ctr1, ctr2;
2591 WERROR werror;
2592 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2593 SEC_DESC *sd1, *sd2;
2594 bool result = True;
2597 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2598 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2599 if ( !W_ERROR_IS_OK(werror) ) {
2600 printf("failed (%s)\n", dos_errstr(werror));
2601 result = False;
2602 goto done;
2604 printf("ok\n");
2606 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2607 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2608 if ( !W_ERROR_IS_OK(werror) ) {
2609 printf("failed (%s)\n", dos_errstr(werror));
2610 result = False;
2611 goto done;
2613 printf("ok\n");
2616 printf("++ ");
2618 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2619 printf("NULL PRINTER_INFO_3!\n");
2620 result = False;
2621 goto done;
2624 sd1 = ctr1.printers_3->secdesc;
2625 sd2 = ctr2.printers_3->secdesc;
2627 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2628 printf("NULL secdesc!\n");
2629 result = False;
2630 goto done;
2633 if (!sec_desc_equal( sd1, sd2 ) ) {
2634 printf("Security Descriptors *not* equal!\n");
2635 result = False;
2636 goto done;
2639 printf("Security descriptors match\n");
2641 done:
2642 talloc_destroy(mem_ctx);
2643 return result;
2647 /****************************************************************************
2648 ****************************************************************************/
2650 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2651 TALLOC_CTX *mem_ctx, int argc,
2652 const char **argv)
2654 fstring printername, servername1, servername2;
2655 char *printername_path = NULL;
2656 struct cli_state *cli_server1 = cli->cli;
2657 struct cli_state *cli_server2 = NULL;
2658 struct rpc_pipe_client *cli2 = NULL;
2659 POLICY_HND hPrinter1, hPrinter2;
2660 NTSTATUS nt_status;
2661 WERROR werror;
2663 if ( argc != 3 ) {
2664 printf("Usage: %s <printer> <server>\n", argv[0]);
2665 return WERR_OK;
2668 fstrcpy( printername, argv[1] );
2670 fstrcpy( servername1, cli->cli->desthost );
2671 fstrcpy( servername2, argv[2] );
2672 strupper_m( servername1 );
2673 strupper_m( servername2 );
2675 /* first get the connection to the remote server */
2677 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2678 NULL, 0,
2679 "IPC$", "IPC",
2680 get_cmdline_auth_info_username(),
2681 lp_workgroup(),
2682 get_cmdline_auth_info_password(),
2683 get_cmdline_auth_info_use_kerberos() ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2684 get_cmdline_auth_info_signing_state(), NULL);
2686 if ( !NT_STATUS_IS_OK(nt_status) )
2687 return WERR_GENERAL_FAILURE;
2689 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2690 if (!cli2) {
2691 printf("failed to open spoolss pipe on server %s (%s)\n",
2692 servername2, nt_errstr(nt_status));
2693 return WERR_GENERAL_FAILURE;
2696 /* now open up both printers */
2698 printername_path = talloc_asprintf(mem_ctx,
2699 "\\\\%s\\%s",
2700 servername1,
2701 printername);
2702 if (!printername_path) {
2703 return WERR_NOMEM;
2705 printf("Opening %s...", printername_path);
2706 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2707 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2708 if ( !W_ERROR_IS_OK(werror) ) {
2709 printf("failed (%s)\n", dos_errstr(werror));
2710 goto done;
2712 printf("ok\n");
2714 printername_path = talloc_asprintf(mem_ctx,
2715 "\\\\%s\\%s",
2716 servername2,
2717 printername);
2718 if (!printername_path) {
2719 return WERR_NOMEM;
2721 printf("Opening %s...", printername_path);
2722 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2723 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2724 if ( !W_ERROR_IS_OK(werror) ) {
2725 printf("failed (%s)\n", dos_errstr(werror));
2726 goto done;
2728 printf("ok\n");
2730 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2731 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2732 #if 0
2733 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2734 #endif
2737 done:
2738 /* cleanup */
2740 printf("Closing printers...");
2741 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2742 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2743 printf("ok\n");
2745 /* close the second remote connection */
2747 cli_shutdown( cli_server2 );
2748 return WERR_OK;
2751 /* List of commands exported by this module */
2752 struct cmd_set spoolss_commands[] = {
2754 { "SPOOLSS" },
2756 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2757 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2758 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2759 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2760 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2761 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2762 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2763 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2764 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2765 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2766 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2767 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2768 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2769 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2770 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2771 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2772 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2773 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2774 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2775 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2776 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2777 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2778 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2779 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2780 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2781 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2782 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2783 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2784 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },
2786 { NULL }