r9742: merging reg_objects and NT_PRINTER_DATA changes from SAMBA_3_0
[Samba.git] / source / rpcclient / cmd_spoolss.c
blob412847fc78fbe18cba078ac3d9f28a0e0ca6c663
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "rpcclient.h"
28 struct table_node {
29 const char *long_archi;
30 const char *short_archi;
31 int version;
34 /* The version int is used by getdrivers. Note that
35 all architecture strings that support mutliple
36 versions must be grouped together since enumdrivers
37 uses this property to prevent issuing multiple
38 enumdriver calls for the same arch */
41 static const struct table_node archi_table[]= {
43 {"Windows 4.0", "WIN40", 0 },
44 {"Windows NT x86", "W32X86", 2 },
45 {"Windows NT x86", "W32X86", 3 },
46 {"Windows NT R4000", "W32MIPS", 2 },
47 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
48 {"Windows NT PowerPC", "W32PPC", 2 },
49 {"Windows IA64", "IA64", 3 },
50 {"Windows x64", "x64", 3 },
51 {NULL, "", -1 }
54 /**
55 * @file
57 * rpcclient module for SPOOLSS rpc pipe.
59 * This generally just parses and checks command lines, and then calls
60 * a cli_spoolss function.
61 **/
63 /****************************************************************************
64 function to do the mapping between the long architecture name and
65 the short one.
66 ****************************************************************************/
68 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
70 int i=-1;
72 DEBUG(107,("Getting architecture dependant directory\n"));
73 do {
74 i++;
75 } while ( (archi_table[i].long_archi!=NULL ) &&
76 StrCaseCmp(long_archi, archi_table[i].long_archi) );
78 if (archi_table[i].long_archi==NULL) {
79 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
80 return NULL;
83 /* this might be client code - but shouldn't this be an fstrcpy etc? */
86 DEBUGADD(108,("index: [%d]\n", i));
87 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
88 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
90 return archi_table[i].short_archi;
93 /****************************************************************************
94 ****************************************************************************/
96 static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli,
97 TALLOC_CTX *mem_ctx,
98 int argc, const char **argv)
100 WERROR werror;
101 fstring printername;
102 fstring servername, user;
103 POLICY_HND hnd;
105 if (argc != 2) {
106 printf("Usage: %s <printername>\n", argv[0]);
107 return WERR_OK;
110 if (!cli)
111 return WERR_GENERAL_FAILURE;
113 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
114 strupper_m(servername);
115 fstrcpy(user, cli->user_name);
116 fstrcpy(printername, argv[1]);
118 /* Open the printer handle */
120 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
121 "", PRINTER_ALL_ACCESS,
122 servername, user, &hnd);
124 if (W_ERROR_IS_OK(werror)) {
125 printf("Printer %s opened successfully\n", printername);
126 werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
128 if (!W_ERROR_IS_OK(werror)) {
129 printf("Error closing printer handle! (%s)\n",
130 get_dos_error_msg(werror));
134 return werror;
138 /****************************************************************************
139 ****************************************************************************/
141 static void display_print_info_0(PRINTER_INFO_0 *i0)
143 fstring name = "";
144 fstring servername = "";
146 if (!i0)
147 return;
149 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
151 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
153 printf("\tprintername:[%s]\n", name);
154 printf("\tservername:[%s]\n", servername);
155 printf("\tcjobs:[0x%x]\n", i0->cjobs);
156 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
158 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
159 i0->day, i0->dayofweek);
160 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
161 i0->second, i0->milliseconds);
163 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
164 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
166 printf("\tmajorversion:[0x%x]\n", i0->major_version);
167 printf("\tbuildversion:[0x%x]\n", i0->build_version);
169 printf("\tunknown7:[0x%x]\n", i0->unknown7);
170 printf("\tunknown8:[0x%x]\n", i0->unknown8);
171 printf("\tunknown9:[0x%x]\n", i0->unknown9);
172 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
173 printf("\tunknown11:[0x%x]\n", i0->unknown11);
174 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
175 printf("\tunknown13:[0x%x]\n", i0->unknown13);
176 printf("\tunknown14:[0x%x]\n", i0->unknown14);
177 printf("\tunknown15:[0x%x]\n", i0->unknown15);
178 printf("\tunknown16:[0x%x]\n", i0->unknown16);
179 printf("\tchange_id:[0x%x]\n", i0->change_id);
180 printf("\tunknown18:[0x%x]\n", i0->unknown18);
181 printf("\tstatus:[0x%x]\n", i0->status);
182 printf("\tunknown20:[0x%x]\n", i0->unknown20);
183 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
184 printf("\tunknown22:[0x%x]\n", i0->unknown22);
185 printf("\tunknown23:[0x%x]\n", i0->unknown23);
186 printf("\tunknown24:[0x%x]\n", i0->unknown24);
187 printf("\tunknown25:[0x%x]\n", i0->unknown25);
188 printf("\tunknown26:[0x%x]\n", i0->unknown26);
189 printf("\tunknown27:[0x%x]\n", i0->unknown27);
190 printf("\tunknown28:[0x%x]\n", i0->unknown28);
191 printf("\tunknown29:[0x%x]\n", i0->unknown29);
193 printf("\n");
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info_1(PRINTER_INFO_1 *i1)
201 fstring desc = "";
202 fstring name = "";
203 fstring comm = "";
205 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
206 STR_TERMINATE);
208 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
209 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
211 printf("\tflags:[0x%x]\n", i1->flags);
212 printf("\tname:[%s]\n", name);
213 printf("\tdescription:[%s]\n", desc);
214 printf("\tcomment:[%s]\n", comm);
216 printf("\n");
219 /****************************************************************************
220 ****************************************************************************/
222 static void display_print_info_2(PRINTER_INFO_2 *i2)
224 fstring servername = "";
225 fstring printername = "";
226 fstring sharename = "";
227 fstring portname = "";
228 fstring drivername = "";
229 fstring comment = "";
230 fstring location = "";
231 fstring sepfile = "";
232 fstring printprocessor = "";
233 fstring datatype = "";
234 fstring parameters = "";
236 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
237 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
238 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
239 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
240 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
241 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
242 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
243 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
244 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
245 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
246 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
248 printf("\tservername:[%s]\n", servername);
249 printf("\tprintername:[%s]\n", printername);
250 printf("\tsharename:[%s]\n", sharename);
251 printf("\tportname:[%s]\n", portname);
252 printf("\tdrivername:[%s]\n", drivername);
253 printf("\tcomment:[%s]\n", comment);
254 printf("\tlocation:[%s]\n", location);
255 printf("\tsepfile:[%s]\n", sepfile);
256 printf("\tprintprocessor:[%s]\n", printprocessor);
257 printf("\tdatatype:[%s]\n", datatype);
258 printf("\tparameters:[%s]\n", parameters);
259 printf("\tattributes:[0x%x]\n", i2->attributes);
260 printf("\tpriority:[0x%x]\n", i2->priority);
261 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
262 printf("\tstarttime:[0x%x]\n", i2->starttime);
263 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
264 printf("\tstatus:[0x%x]\n", i2->status);
265 printf("\tcjobs:[0x%x]\n", i2->cjobs);
266 printf("\taverageppm:[0x%x]\n", i2->averageppm);
268 if (i2->secdesc)
269 display_sec_desc(i2->secdesc);
271 printf("\n");
274 /****************************************************************************
275 ****************************************************************************/
277 static void display_print_info_3(PRINTER_INFO_3 *i3)
279 printf("\tflags:[0x%x]\n", i3->flags);
281 display_sec_desc(i3->secdesc);
283 printf("\n");
286 /****************************************************************************
287 ****************************************************************************/
289 static void display_print_info_7(PRINTER_INFO_7 *i7)
291 fstring guid = "";
292 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
293 printf("\tguid:[%s]\n", guid);
294 printf("\taction:[0x%x]\n", i7->action);
298 /****************************************************************************
299 ****************************************************************************/
301 static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
302 TALLOC_CTX *mem_ctx,
303 int argc, const char **argv)
305 WERROR result;
306 uint32 info_level = 1;
307 PRINTER_INFO_CTR ctr;
308 uint32 i = 0, num_printers;
309 fstring name;
311 if (argc > 3)
313 printf("Usage: %s [level] [name]\n", argv[0]);
314 return WERR_OK;
317 if (argc >= 2)
318 info_level = atoi(argv[1]);
320 if (argc == 3)
321 fstrcpy(name, argv[2]);
322 else {
323 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
324 strupper_m(name);
327 ZERO_STRUCT(ctr);
329 result = cli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
330 info_level, &num_printers, &ctr);
332 if (W_ERROR_IS_OK(result)) {
334 if (!num_printers) {
335 printf ("No printers returned.\n");
336 goto done;
339 for (i = 0; i < num_printers; i++) {
340 switch(info_level) {
341 case 0:
342 display_print_info_0(&ctr.printers_0[i]);
343 break;
344 case 1:
345 display_print_info_1(&ctr.printers_1[i]);
346 break;
347 case 2:
348 display_print_info_2(&ctr.printers_2[i]);
349 break;
350 case 3:
351 display_print_info_3(&ctr.printers_3[i]);
352 break;
353 default:
354 printf("unknown info level %d\n", info_level);
355 goto done;
359 done:
361 return result;
364 /****************************************************************************
365 ****************************************************************************/
367 static void display_port_info_1(PORT_INFO_1 *i1)
369 fstring buffer;
371 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
372 printf("\tPort Name:\t[%s]\n", buffer);
375 /****************************************************************************
376 ****************************************************************************/
378 static void display_port_info_2(PORT_INFO_2 *i2)
380 fstring buffer;
382 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
383 printf("\tPort Name:\t[%s]\n", buffer);
384 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
386 printf("\tMonitor Name:\t[%s]\n", buffer);
387 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
389 printf("\tDescription:\t[%s]\n", buffer);
390 printf("\tPort Type:\t" );
391 if ( i2->port_type ) {
392 int comma = 0; /* hack */
393 printf( "[" );
394 if ( i2->port_type & PORT_TYPE_READ ) {
395 printf( "Read" );
396 comma = 1;
398 if ( i2->port_type & PORT_TYPE_WRITE ) {
399 printf( "%sWrite", comma ? ", " : "" );
400 comma = 1;
402 /* These two have slightly different interpretations
403 on 95/98/ME but I'm disregarding that for now */
404 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
405 printf( "%sRedirected", comma ? ", " : "" );
406 comma = 1;
408 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
409 printf( "%sNet-Attached", comma ? ", " : "" );
411 printf( "]\n" );
412 } else {
413 printf( "[Unset]\n" );
415 printf("\tReserved:\t[%d]\n", i2->reserved);
416 printf("\n");
419 /****************************************************************************
420 ****************************************************************************/
422 static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
423 TALLOC_CTX *mem_ctx, int argc,
424 const char **argv)
426 WERROR result;
427 uint32 info_level = 1;
428 PORT_INFO_CTR ctr;
429 uint32 returned;
431 if (argc > 2) {
432 printf("Usage: %s [level]\n", argv[0]);
433 return WERR_OK;
436 if (argc == 2)
437 info_level = atoi(argv[1]);
439 /* Enumerate ports */
441 ZERO_STRUCT(ctr);
443 result = cli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
445 if (W_ERROR_IS_OK(result)) {
446 int i;
448 for (i = 0; i < returned; i++) {
449 switch (info_level) {
450 case 1:
451 display_port_info_1(&ctr.port.info_1[i]);
452 break;
453 case 2:
454 display_port_info_2(&ctr.port.info_2[i]);
455 break;
456 default:
457 printf("unknown info level %d\n", info_level);
458 break;
463 return result;
466 /****************************************************************************
467 ****************************************************************************/
469 static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
470 TALLOC_CTX *mem_ctx,
471 int argc, const char **argv)
473 POLICY_HND pol;
474 WERROR result;
475 uint32 info_level = 2;
476 BOOL opened_hnd = False;
477 PRINTER_INFO_CTR ctr;
478 fstring printername,
479 servername,
480 user,
481 comment;
483 if (argc == 1 || argc > 3) {
484 printf("Usage: %s printername comment\n", argv[0]);
486 return WERR_OK;
489 /* Open a printer handle */
490 if (argc == 3) {
491 fstrcpy(comment, argv[2]);
494 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
495 strupper_m(servername);
496 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
497 fstrcpy(user, cli->user_name);
499 /* get a printer handle */
500 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
501 PRINTER_ALL_ACCESS, servername,
502 user, &pol);
504 if (!W_ERROR_IS_OK(result))
505 goto done;
507 opened_hnd = True;
509 /* Get printer info */
510 result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
512 if (!W_ERROR_IS_OK(result))
513 goto done;
516 /* Modify the comment. */
517 init_unistr(&ctr.printers_2->comment, comment);
518 ctr.printers_2->devmode = NULL;
519 ctr.printers_2->secdesc = NULL;
521 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
522 if (W_ERROR_IS_OK(result))
523 printf("Success in setting comment.\n");
525 done:
526 if (opened_hnd)
527 cli_spoolss_close_printer(cli, mem_ctx, &pol);
529 return result;
532 /****************************************************************************
533 ****************************************************************************/
535 static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
536 TALLOC_CTX *mem_ctx,
537 int argc, const char **argv)
539 POLICY_HND pol;
540 WERROR result;
541 uint32 info_level = 2;
542 BOOL opened_hnd = False;
543 PRINTER_INFO_CTR ctr;
544 fstring printername,
545 servername,
546 user,
547 new_printername;
549 if (argc == 1 || argc > 3) {
550 printf("Usage: %s printername new_printername\n", argv[0]);
552 return WERR_OK;
555 /* Open a printer handle */
556 if (argc == 3) {
557 fstrcpy(new_printername, argv[2]);
560 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
561 strupper_m(servername);
562 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
563 fstrcpy(user, cli->user_name);
565 /* get a printer handle */
566 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
567 PRINTER_ALL_ACCESS, servername,
568 user, &pol);
570 if (!W_ERROR_IS_OK(result))
571 goto done;
573 opened_hnd = True;
575 /* Get printer info */
576 result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
578 if (!W_ERROR_IS_OK(result))
579 goto done;
581 /* Modify the printername. */
582 init_unistr(&ctr.printers_2->printername, new_printername);
583 ctr.printers_2->devmode = NULL;
584 ctr.printers_2->secdesc = NULL;
586 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
587 if (W_ERROR_IS_OK(result))
588 printf("Success in setting printername.\n");
590 done:
591 if (opened_hnd)
592 cli_spoolss_close_printer(cli, mem_ctx, &pol);
594 return result;
597 /****************************************************************************
598 ****************************************************************************/
600 static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
601 TALLOC_CTX *mem_ctx,
602 int argc, const char **argv)
604 POLICY_HND pol;
605 WERROR result;
606 uint32 info_level = 1;
607 BOOL opened_hnd = False;
608 PRINTER_INFO_CTR ctr;
609 fstring printername,
610 servername,
611 user;
613 if (argc == 1 || argc > 3) {
614 printf("Usage: %s <printername> [level]\n", argv[0]);
615 return WERR_OK;
618 /* Open a printer handle */
619 if (argc == 3) {
620 info_level = atoi(argv[2]);
623 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
624 strupper_m(servername);
625 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
626 fstrcpy(user, cli->user_name);
628 /* get a printer handle */
630 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
631 "", MAXIMUM_ALLOWED_ACCESS,
632 servername, user, &pol);
634 if (!W_ERROR_IS_OK(result))
635 goto done;
637 opened_hnd = True;
639 /* Get printer info */
641 result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
643 if (!W_ERROR_IS_OK(result))
644 goto done;
646 /* Display printer info */
648 switch (info_level) {
649 case 0:
650 display_print_info_0(ctr.printers_0);
651 break;
652 case 1:
653 display_print_info_1(ctr.printers_1);
654 break;
655 case 2:
656 display_print_info_2(ctr.printers_2);
657 break;
658 case 3:
659 display_print_info_3(ctr.printers_3);
660 break;
661 case 7:
662 display_print_info_7(ctr.printers_7);
663 break;
664 default:
665 printf("unknown info level %d\n", info_level);
666 break;
669 done:
670 if (opened_hnd)
671 cli_spoolss_close_printer(cli, mem_ctx, &pol);
673 return result;
676 /****************************************************************************
677 ****************************************************************************/
679 static void display_reg_value(REGISTRY_VALUE value)
681 pstring text;
683 switch(value.type) {
684 case REG_DWORD:
685 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
686 *((uint32 *) value.data_p));
687 break;
688 case REG_SZ:
689 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
690 STR_TERMINATE);
691 printf("%s: REG_SZ: %s\n", value.valuename, text);
692 break;
693 case REG_BINARY: {
694 char *hex = hex_encode(NULL, value.data_p, value.size);
695 size_t i, len;
696 printf("%s: REG_BINARY:", value.valuename);
697 len = strlen(hex);
698 for (i=0; i<len; i++) {
699 if (hex[i] == '\0') {
700 break;
702 if (i%40 == 0) {
703 putchar('\n');
705 putchar(hex[i]);
707 talloc_free(hex);
708 putchar('\n');
709 break;
711 case REG_MULTI_SZ: {
712 uint16 *curstr = (uint16 *) value.data_p;
713 uint8 *start = value.data_p;
714 printf("%s: REG_MULTI_SZ:\n", value.valuename);
715 while (((uint8 *) curstr < start + value.size)) {
716 rpcstr_pull(text, curstr, sizeof(text), -1,
717 STR_TERMINATE);
718 printf(" %s\n", *text != 0 ? text : "NULL");
719 curstr += strlen(text) + 1;
722 break;
723 default:
724 printf("%s: unknown type %d\n", value.valuename, value.type);
729 /****************************************************************************
730 ****************************************************************************/
732 static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
733 TALLOC_CTX *mem_ctx,
734 int argc, const char **argv)
736 POLICY_HND pol;
737 WERROR result;
738 BOOL opened_hnd = False;
739 fstring printername,
740 servername,
741 user;
742 const char *valuename;
743 REGISTRY_VALUE value;
745 if (argc != 3) {
746 printf("Usage: %s <printername> <valuename>\n", argv[0]);
747 printf("<printername> of . queries print server\n");
748 return WERR_OK;
750 valuename = argv[2];
752 /* Open a printer handle */
754 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
755 strupper_m(servername);
756 if (strncmp(argv[1], ".", sizeof(".")) == 0)
757 fstrcpy(printername, servername);
758 else
759 slprintf(printername, sizeof(servername)-1, "%s\\%s",
760 servername, argv[1]);
761 fstrcpy(user, cli->user_name);
763 /* get a printer handle */
765 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
766 "", MAXIMUM_ALLOWED_ACCESS,
767 servername, user, &pol);
769 if (!W_ERROR_IS_OK(result))
770 goto done;
772 opened_hnd = True;
774 /* Get printer info */
776 result = cli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
778 if (!W_ERROR_IS_OK(result))
779 goto done;
781 /* Display printer data */
783 fstrcpy(value.valuename, valuename);
784 display_reg_value(value);
787 done:
788 if (opened_hnd)
789 cli_spoolss_close_printer(cli, mem_ctx, &pol);
791 return result;
794 /****************************************************************************
795 ****************************************************************************/
797 static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
798 TALLOC_CTX *mem_ctx,
799 int argc, const char **argv)
801 POLICY_HND pol;
802 WERROR result;
803 BOOL opened_hnd = False;
804 fstring printername,
805 servername,
806 user;
807 const char *valuename, *keyname;
808 REGISTRY_VALUE value;
810 if (argc != 4) {
811 printf("Usage: %s <printername> <keyname> <valuename>\n",
812 argv[0]);
813 printf("<printername> of . queries print server\n");
814 return WERR_OK;
816 valuename = argv[3];
817 keyname = argv[2];
819 /* Open a printer handle */
821 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
822 strupper_m(servername);
823 if (strncmp(argv[1], ".", sizeof(".")) == 0)
824 fstrcpy(printername, servername);
825 else
826 slprintf(printername, sizeof(printername)-1, "%s\\%s",
827 servername, argv[1]);
828 fstrcpy(user, cli->user_name);
830 /* get a printer handle */
832 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
833 "", MAXIMUM_ALLOWED_ACCESS,
834 servername, user, &pol);
836 if (!W_ERROR_IS_OK(result))
837 goto done;
839 opened_hnd = True;
841 /* Get printer info */
843 result = cli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
844 valuename, &value);
846 if (!W_ERROR_IS_OK(result))
847 goto done;
849 /* Display printer data */
851 fstrcpy(value.valuename, valuename);
852 display_reg_value(value);
855 done:
856 if (opened_hnd)
857 cli_spoolss_close_printer(cli, mem_ctx, &pol);
859 return result;
862 /****************************************************************************
863 ****************************************************************************/
865 static void display_print_driver_1(DRIVER_INFO_1 *i1)
867 fstring name;
868 if (i1 == NULL)
869 return;
871 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
873 printf ("Printer Driver Info 1:\n");
874 printf ("\tDriver Name: [%s]\n\n", name);
876 return;
879 /****************************************************************************
880 ****************************************************************************/
882 static void display_print_driver_2(DRIVER_INFO_2 *i1)
884 fstring name;
885 fstring architecture;
886 fstring driverpath;
887 fstring datafile;
888 fstring configfile;
889 if (i1 == NULL)
890 return;
892 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
893 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
894 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
895 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
896 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
898 printf ("Printer Driver Info 2:\n");
899 printf ("\tVersion: [%x]\n", i1->version);
900 printf ("\tDriver Name: [%s]\n", name);
901 printf ("\tArchitecture: [%s]\n", architecture);
902 printf ("\tDriver Path: [%s]\n", driverpath);
903 printf ("\tDatafile: [%s]\n", datafile);
904 printf ("\tConfigfile: [%s]\n\n", configfile);
906 return;
909 /****************************************************************************
910 ****************************************************************************/
912 static void display_print_driver_3(DRIVER_INFO_3 *i1)
914 fstring name = "";
915 fstring architecture = "";
916 fstring driverpath = "";
917 fstring datafile = "";
918 fstring configfile = "";
919 fstring helpfile = "";
920 fstring dependentfiles = "";
921 fstring monitorname = "";
922 fstring defaultdatatype = "";
924 int length=0;
925 BOOL valid = True;
927 if (i1 == NULL)
928 return;
930 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
931 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
932 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
933 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
934 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
935 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
936 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
937 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
939 printf ("Printer Driver Info 3:\n");
940 printf ("\tVersion: [%x]\n", i1->version);
941 printf ("\tDriver Name: [%s]\n",name);
942 printf ("\tArchitecture: [%s]\n", architecture);
943 printf ("\tDriver Path: [%s]\n", driverpath);
944 printf ("\tDatafile: [%s]\n", datafile);
945 printf ("\tConfigfile: [%s]\n", configfile);
946 printf ("\tHelpfile: [%s]\n\n", helpfile);
948 while (valid)
950 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
952 length+=strlen(dependentfiles)+1;
954 if (strlen(dependentfiles) > 0)
956 printf ("\tDependentfiles: [%s]\n", dependentfiles);
958 else
960 valid = False;
964 printf ("\n");
966 printf ("\tMonitorname: [%s]\n", monitorname);
967 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
969 return;
972 /****************************************************************************
973 ****************************************************************************/
975 static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
976 TALLOC_CTX *mem_ctx,
977 int argc, const char **argv)
979 POLICY_HND pol;
980 WERROR werror;
981 uint32 info_level = 3;
982 BOOL opened_hnd = False;
983 PRINTER_DRIVER_CTR ctr;
984 fstring printername,
985 servername,
986 user;
987 uint32 i;
988 BOOL success = False;
990 if ((argc == 1) || (argc > 3))
992 printf("Usage: %s <printername> [level]\n", argv[0]);
993 return WERR_OK;
996 /* get the arguments need to open the printer handle */
997 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
998 strupper_m(servername);
999 fstrcpy(user, cli->user_name);
1000 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1001 if (argc == 3)
1002 info_level = atoi(argv[2]);
1004 /* Open a printer handle */
1006 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1007 PRINTER_ACCESS_USE,
1008 servername, user, &pol);
1010 if (!W_ERROR_IS_OK(werror)) {
1011 printf("Error opening printer handle for %s!\n", printername);
1012 return werror;
1015 opened_hnd = True;
1017 /* loop through and print driver info level for each architecture */
1019 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1021 werror = cli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1022 archi_table[i].long_archi, archi_table[i].version,
1023 &ctr);
1025 if (!W_ERROR_IS_OK(werror))
1026 continue;
1028 /* need at least one success */
1030 success = True;
1032 printf ("\n[%s]\n", archi_table[i].long_archi);
1034 switch (info_level) {
1035 case 1:
1036 display_print_driver_1 (ctr.info1);
1037 break;
1038 case 2:
1039 display_print_driver_2 (ctr.info2);
1040 break;
1041 case 3:
1042 display_print_driver_3 (ctr.info3);
1043 break;
1044 default:
1045 printf("unknown info level %d\n", info_level);
1046 break;
1050 /* Cleanup */
1052 if (opened_hnd)
1053 cli_spoolss_close_printer (cli, mem_ctx, &pol);
1055 if ( success )
1056 werror = WERR_OK;
1058 return werror;
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
1065 TALLOC_CTX *mem_ctx,
1066 int argc, const char **argv)
1068 WERROR werror;
1069 uint32 info_level = 1;
1070 PRINTER_DRIVER_CTR ctr;
1071 uint32 i, j,
1072 returned;
1074 if (argc > 2)
1076 printf("Usage: enumdrivers [level]\n");
1077 return WERR_OK;
1080 if (argc == 2)
1081 info_level = atoi(argv[1]);
1084 /* loop through and print driver info level for each architecture */
1085 for (i=0; archi_table[i].long_archi!=NULL; i++)
1087 /* check to see if we already asked for this architecture string */
1089 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1090 continue;
1092 werror = cli_spoolss_enumprinterdrivers(
1093 cli, mem_ctx, info_level,
1094 archi_table[i].long_archi, &returned, &ctr);
1096 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1097 printf ("Server does not support environment [%s]\n",
1098 archi_table[i].long_archi);
1099 werror = WERR_OK;
1100 continue;
1103 if (returned == 0)
1104 continue;
1106 if (!W_ERROR_IS_OK(werror)) {
1107 printf ("Error getting driver for environment [%s] - %d\n",
1108 archi_table[i].long_archi, W_ERROR_V(werror));
1109 continue;
1112 printf ("\n[%s]\n", archi_table[i].long_archi);
1113 switch (info_level)
1116 case 1:
1117 for (j=0; j < returned; j++) {
1118 display_print_driver_1 (&(ctr.info1[j]));
1120 break;
1121 case 2:
1122 for (j=0; j < returned; j++) {
1123 display_print_driver_2 (&(ctr.info2[j]));
1125 break;
1126 case 3:
1127 for (j=0; j < returned; j++) {
1128 display_print_driver_3 (&(ctr.info3[j]));
1130 break;
1131 default:
1132 printf("unknown info level %d\n", info_level);
1133 break;
1137 return werror;
1140 /****************************************************************************
1141 ****************************************************************************/
1143 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1145 fstring name;
1146 if (i1 == NULL)
1147 return;
1149 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1151 printf ("\tDirectory Name:[%s]\n", name);
1154 /****************************************************************************
1155 ****************************************************************************/
1157 static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli,
1158 TALLOC_CTX *mem_ctx,
1159 int argc, const char **argv)
1161 WERROR result;
1162 fstring env;
1163 DRIVER_DIRECTORY_CTR ctr;
1165 if (argc > 2) {
1166 printf("Usage: %s [environment]\n", argv[0]);
1167 return WERR_OK;
1170 /* Get the arguments need to open the printer handle */
1172 if (argc == 2)
1173 fstrcpy (env, argv[1]);
1174 else
1175 fstrcpy (env, "Windows NT x86");
1177 /* Get the directory. Only use Info level 1 */
1179 result = cli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1181 if (W_ERROR_IS_OK(result))
1182 display_printdriverdir_1(ctr.info1);
1184 return result;
1187 /****************************************************************************
1188 ****************************************************************************/
1190 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1193 int i;
1195 for (i=0; archi_table[i].long_archi != NULL; i++)
1197 if (strcmp(arch, archi_table[i].short_archi) == 0)
1199 info->version = archi_table[i].version;
1200 init_unistr (&info->architecture, archi_table[i].long_archi);
1201 break;
1205 if (archi_table[i].long_archi == NULL)
1207 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1210 return;
1214 /**************************************************************************
1215 wrapper for strtok to get the next parameter from a delimited list.
1216 Needed to handle the empty parameter string denoted by "NULL"
1217 *************************************************************************/
1219 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1221 char *ptr;
1223 /* get the next token */
1224 ptr = strtok(str, delim);
1226 /* a string of 'NULL' is used to represent an empty
1227 parameter because two consecutive delimiters
1228 will not return an empty string. See man strtok(3)
1229 for details */
1230 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1231 ptr = NULL;
1233 if (dest != NULL)
1234 init_unistr(dest, ptr);
1236 return ptr;
1239 /********************************************************************************
1240 fill in the members of a DRIVER_INFO_3 struct using a character
1241 string in the form of
1242 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1243 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1244 <Default Data Type>:<Comma Separated list of Files>
1245 *******************************************************************************/
1246 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1247 char *args )
1249 char *str, *str2;
1250 uint32 len, i;
1252 /* fill in the UNISTR fields */
1253 str = get_driver_3_param (args, ":", &info->name);
1254 str = get_driver_3_param (NULL, ":", &info->driverpath);
1255 str = get_driver_3_param (NULL, ":", &info->datafile);
1256 str = get_driver_3_param (NULL, ":", &info->configfile);
1257 str = get_driver_3_param (NULL, ":", &info->helpfile);
1258 str = get_driver_3_param (NULL, ":", &info->monitorname);
1259 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1261 /* <Comma Separated List of Dependent Files> */
1262 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1263 str = str2;
1265 /* begin to strip out each filename */
1266 str = strtok(str, ",");
1267 len = 0;
1268 while (str != NULL)
1270 /* keep a cumlative count of the str lengths */
1271 len += strlen(str)+1;
1272 str = strtok(NULL, ",");
1275 /* allocate the space; add one extra slot for a terminating NULL.
1276 Each filename is NULL terminated and the end contains a double
1277 NULL */
1278 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1280 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1281 return False;
1283 for (i=0; i<len; i++)
1285 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1287 info->dependentfiles[len] = '\0';
1289 return True;
1293 /****************************************************************************
1294 ****************************************************************************/
1296 static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
1297 TALLOC_CTX *mem_ctx,
1298 int argc, const char **argv)
1300 WERROR result;
1301 uint32 level = 3;
1302 PRINTER_DRIVER_CTR ctr;
1303 DRIVER_INFO_3 info3;
1304 const char *arch;
1305 fstring driver_name;
1306 char *driver_args;
1308 /* parse the command arguements */
1309 if (argc != 3 && argc != 4)
1311 printf ("Usage: %s <Environment> \\\n", argv[0]);
1312 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1313 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1314 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1315 printf ("\t[version]\n");
1317 return WERR_OK;
1320 /* Fill in the DRIVER_INFO_3 struct */
1321 ZERO_STRUCT(info3);
1322 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1324 printf ("Error Unknown architechture [%s]\n", argv[1]);
1325 return WERR_INVALID_PARAM;
1327 else
1328 set_drv_info_3_env(&info3, arch);
1330 driver_args = talloc_strdup( mem_ctx, argv[2] );
1331 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1333 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1334 return WERR_INVALID_PARAM;
1337 /* if printer driver version specified, override the default version
1338 * used by the architecture. This allows installation of Windows
1339 * 2000 (version 3) printer drivers. */
1340 if (argc == 4)
1342 info3.version = atoi(argv[3]);
1346 ctr.info3 = &info3;
1347 result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1349 if (W_ERROR_IS_OK(result)) {
1350 rpcstr_pull(driver_name, info3.name.buffer,
1351 sizeof(driver_name), -1, STR_TERMINATE);
1352 printf ("Printer Driver %s successfully installed.\n",
1353 driver_name);
1356 return result;
1360 /****************************************************************************
1361 ****************************************************************************/
1363 static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
1364 TALLOC_CTX *mem_ctx,
1365 int argc, const char **argv)
1367 WERROR result;
1368 uint32 level = 2;
1369 PRINTER_INFO_CTR ctr;
1370 PRINTER_INFO_2 info2;
1371 fstring servername;
1373 /* parse the command arguements */
1374 if (argc != 5)
1376 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1377 return WERR_OK;
1380 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1381 strupper_m(servername);
1383 /* Fill in the DRIVER_INFO_2 struct */
1384 ZERO_STRUCT(info2);
1386 init_unistr( &info2.printername, argv[1]);
1387 init_unistr( &info2.sharename, argv[2]);
1388 init_unistr( &info2.drivername, argv[3]);
1389 init_unistr( &info2.portname, argv[4]);
1390 init_unistr( &info2.comment, "Created by rpcclient");
1391 init_unistr( &info2.printprocessor, "winprint");
1392 init_unistr( &info2.datatype, "RAW");
1393 info2.devmode = NULL;
1394 info2.secdesc = NULL;
1395 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1396 info2.priority = 0;
1397 info2.defaultpriority = 0;
1398 info2.starttime = 0;
1399 info2.untiltime = 0;
1401 /* These three fields must not be used by AddPrinter()
1402 as defined in the MS Platform SDK documentation..
1403 --jerry
1404 info2.status = 0;
1405 info2.cjobs = 0;
1406 info2.averageppm = 0;
1409 ctr.printers_2 = &info2;
1410 result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1412 if (W_ERROR_IS_OK(result))
1413 printf ("Printer %s successfully installed.\n", argv[1]);
1415 return result;
1418 /****************************************************************************
1419 ****************************************************************************/
1421 static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
1422 TALLOC_CTX *mem_ctx,
1423 int argc, const char **argv)
1425 POLICY_HND pol;
1426 WERROR result;
1427 uint32 level = 2;
1428 BOOL opened_hnd = False;
1429 PRINTER_INFO_CTR ctr;
1430 PRINTER_INFO_2 info2;
1431 fstring servername,
1432 printername,
1433 user;
1435 /* parse the command arguements */
1436 if (argc != 3)
1438 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1439 return WERR_OK;
1442 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1443 strupper_m(servername);
1444 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1445 fstrcpy(user, cli->user_name);
1447 /* Get a printer handle */
1449 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1450 PRINTER_ALL_ACCESS,
1451 servername, user, &pol);
1453 if (!W_ERROR_IS_OK(result))
1454 goto done;
1456 opened_hnd = True;
1458 /* Get printer info */
1460 ZERO_STRUCT (info2);
1461 ctr.printers_2 = &info2;
1463 result = cli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1465 if (!W_ERROR_IS_OK(result)) {
1466 printf ("Unable to retrieve printer information!\n");
1467 goto done;
1470 /* Set the printer driver */
1472 init_unistr(&ctr.printers_2->drivername, argv[2]);
1474 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1476 if (!W_ERROR_IS_OK(result)) {
1477 printf("SetPrinter call failed!\n");
1478 goto done;;
1481 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1483 done:
1484 /* Cleanup */
1486 if (opened_hnd)
1487 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1489 return result;
1493 /****************************************************************************
1494 ****************************************************************************/
1496 static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli,
1497 TALLOC_CTX *mem_ctx,
1498 int argc, const char **argv)
1500 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1502 int i;
1503 int vers = -1;
1505 const char *arch = NULL;
1507 /* parse the command arguements */
1508 if (argc < 2 || argc > 4) {
1509 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1510 return WERR_OK;
1513 if (argc >= 3)
1514 arch = argv[2];
1515 if (argc == 4)
1516 vers = atoi (argv[3]);
1519 /* delete the driver for all architectures */
1520 for (i=0; archi_table[i].long_archi; i++) {
1522 if (arch && !strequal( archi_table[i].long_archi, arch))
1523 continue;
1525 if (vers >= 0 && archi_table[i].version != vers)
1526 continue;
1528 /* make the call to remove the driver */
1529 result = cli_spoolss_deleteprinterdriverex(
1530 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1532 if ( !W_ERROR_IS_OK(result) )
1534 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1535 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1536 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1539 else
1541 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1542 archi_table[i].long_archi, archi_table[i].version);
1543 ret = WERR_OK;
1547 return ret;
1551 /****************************************************************************
1552 ****************************************************************************/
1554 static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
1555 TALLOC_CTX *mem_ctx,
1556 int argc, const char **argv)
1558 WERROR result;
1559 fstring servername;
1560 int i;
1562 /* parse the command arguements */
1563 if (argc != 2)
1565 printf ("Usage: %s <driver>\n", argv[0]);
1566 return WERR_OK;
1569 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1570 strupper_m(servername);
1572 /* delete the driver for all architectures */
1573 for (i=0; archi_table[i].long_archi; i++)
1575 /* make the call to remove the driver */
1576 result = cli_spoolss_deleteprinterdriver(
1577 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1579 if ( !W_ERROR_IS_OK(result) ) {
1580 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1581 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1582 argv[1], archi_table[i].long_archi,
1583 W_ERROR_V(result));
1586 else
1588 printf ("Driver %s removed for arch [%s].\n", argv[1],
1589 archi_table[i].long_archi);
1593 return result;
1596 /****************************************************************************
1597 ****************************************************************************/
1599 static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
1600 TALLOC_CTX *mem_ctx,
1601 int argc, const char **argv)
1603 WERROR result;
1604 char *servername = NULL, *environment = NULL;
1605 fstring procdir;
1607 /* parse the command arguements */
1608 if (argc > 2) {
1609 printf ("Usage: %s [environment]\n", argv[0]);
1610 return WERR_OK;
1613 if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1614 return WERR_NOMEM;
1615 strupper_m(servername);
1617 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1618 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1619 SAFE_FREE(servername);
1620 return WERR_NOMEM;
1623 result = cli_spoolss_getprintprocessordirectory(
1624 cli, mem_ctx, servername, environment, procdir);
1626 if (W_ERROR_IS_OK(result))
1627 printf("%s\n", procdir);
1629 SAFE_FREE(servername);
1630 SAFE_FREE(environment);
1632 return result;
1635 /****************************************************************************
1636 ****************************************************************************/
1638 static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1639 int argc, const char **argv)
1641 POLICY_HND handle;
1642 WERROR werror;
1643 char *servername = NULL, *printername = NULL;
1644 FORM form;
1645 BOOL got_handle = False;
1647 /* Parse the command arguements */
1649 if (argc != 3) {
1650 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1651 return WERR_OK;
1654 /* Get a printer handle */
1656 asprintf(&servername, "\\\\%s", cli->desthost);
1657 strupper_m(servername);
1658 asprintf(&printername, "%s\\%s", servername, argv[1]);
1660 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1661 PRINTER_ALL_ACCESS,
1662 servername, cli->user_name, &handle);
1664 if (!W_ERROR_IS_OK(werror))
1665 goto done;
1667 got_handle = True;
1669 /* Dummy up some values for the form data */
1671 form.flags = FORM_USER;
1672 form.size_x = form.size_y = 100;
1673 form.left = 0;
1674 form.top = 10;
1675 form.right = 20;
1676 form.bottom = 30;
1678 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1680 /* Add the form */
1683 werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1685 done:
1686 if (got_handle)
1687 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1689 SAFE_FREE(servername);
1690 SAFE_FREE(printername);
1692 return werror;
1695 /****************************************************************************
1696 ****************************************************************************/
1698 static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1699 int argc, const char **argv)
1701 POLICY_HND handle;
1702 WERROR werror;
1703 char *servername = NULL, *printername = NULL;
1704 FORM form;
1705 BOOL got_handle = False;
1707 /* Parse the command arguements */
1709 if (argc != 3) {
1710 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1711 return WERR_OK;
1714 /* Get a printer handle */
1716 asprintf(&servername, "\\\\%s", cli->desthost);
1717 strupper_m(servername);
1718 asprintf(&printername, "%s\\%s", servername, argv[1]);
1720 werror = cli_spoolss_open_printer_ex(
1721 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1722 servername, cli->user_name, &handle);
1724 if (!W_ERROR_IS_OK(werror))
1725 goto done;
1727 got_handle = True;
1729 /* Dummy up some values for the form data */
1731 form.flags = FORM_PRINTER;
1732 form.size_x = form.size_y = 100;
1733 form.left = 0;
1734 form.top = 1000;
1735 form.right = 2000;
1736 form.bottom = 3000;
1738 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1740 /* Set the form */
1742 werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1744 done:
1745 if (got_handle)
1746 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1748 SAFE_FREE(servername);
1749 SAFE_FREE(printername);
1751 return werror;
1754 /****************************************************************************
1755 ****************************************************************************/
1757 static const char *get_form_flag(int form_flag)
1759 switch (form_flag) {
1760 case FORM_USER:
1761 return "FORM_USER";
1762 case FORM_BUILTIN:
1763 return "FORM_BUILTIN";
1764 case FORM_PRINTER:
1765 return "FORM_PRINTER";
1766 default:
1767 return "unknown";
1771 /****************************************************************************
1772 ****************************************************************************/
1774 static void display_form(FORM_1 *form)
1776 fstring form_name = "";
1778 if (form->name.buffer)
1779 rpcstr_pull(form_name, form->name.buffer,
1780 sizeof(form_name), -1, STR_TERMINATE);
1782 printf("%s\n" \
1783 "\tflag: %s (%d)\n" \
1784 "\twidth: %d, length: %d\n" \
1785 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1786 form_name, get_form_flag(form->flag), form->flag,
1787 form->width, form->length,
1788 form->left, form->right,
1789 form->top, form->bottom);
1792 /****************************************************************************
1793 ****************************************************************************/
1795 static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1796 int argc, const char **argv)
1798 POLICY_HND handle;
1799 WERROR werror;
1800 char *servername = NULL, *printername = NULL;
1801 FORM_1 form;
1802 BOOL got_handle = False;
1804 /* Parse the command arguements */
1806 if (argc != 3) {
1807 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1808 return WERR_OK;
1811 /* Get a printer handle */
1813 asprintf(&servername, "\\\\%s", cli->desthost);
1814 strupper_m(servername);
1815 asprintf(&printername, "%s\\%s", servername, argv[1]);
1817 werror = cli_spoolss_open_printer_ex(
1818 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1819 servername, cli->user_name, &handle);
1821 if (!W_ERROR_IS_OK(werror))
1822 goto done;
1824 got_handle = True;
1826 /* Get the form */
1828 werror = cli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1830 if (!W_ERROR_IS_OK(werror))
1831 goto done;
1833 display_form(&form);
1835 done:
1836 if (got_handle)
1837 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1839 SAFE_FREE(servername);
1840 SAFE_FREE(printername);
1842 return werror;
1845 /****************************************************************************
1846 ****************************************************************************/
1848 static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
1849 TALLOC_CTX *mem_ctx, int argc,
1850 const char **argv)
1852 POLICY_HND handle;
1853 WERROR werror;
1854 char *servername = NULL, *printername = NULL;
1855 BOOL got_handle = False;
1857 /* Parse the command arguements */
1859 if (argc != 3) {
1860 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1861 return WERR_OK;
1864 /* Get a printer handle */
1866 asprintf(&servername, "\\\\%s", cli->desthost);
1867 strupper_m(servername);
1868 asprintf(&printername, "%s\\%s", servername, argv[1]);
1870 werror = cli_spoolss_open_printer_ex(
1871 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1872 servername, cli->user_name, &handle);
1874 if (!W_ERROR_IS_OK(werror))
1875 goto done;
1877 got_handle = True;
1879 /* Delete the form */
1881 werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1883 done:
1884 if (got_handle)
1885 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1887 SAFE_FREE(servername);
1888 SAFE_FREE(printername);
1890 return werror;
1893 /****************************************************************************
1894 ****************************************************************************/
1896 static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
1897 TALLOC_CTX *mem_ctx, int argc,
1898 const char **argv)
1900 POLICY_HND handle;
1901 WERROR werror;
1902 char *servername = NULL, *printername = NULL;
1903 BOOL got_handle = False;
1904 uint32 needed, offered, num_forms, level = 1, i;
1905 FORM_1 *forms;
1907 /* Parse the command arguements */
1909 if (argc != 2) {
1910 printf ("Usage: %s <printer>\n", argv[0]);
1911 return WERR_OK;
1914 /* Get a printer handle */
1916 asprintf(&servername, "\\\\%s", cli->desthost);
1917 strupper_m(servername);
1918 asprintf(&printername, "%s\\%s", servername, argv[1]);
1920 werror = cli_spoolss_open_printer_ex(
1921 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1922 servername, cli->user_name, &handle);
1924 if (!W_ERROR_IS_OK(werror))
1925 goto done;
1927 got_handle = True;
1929 /* Enumerate forms */
1931 offered = needed = 0;
1932 werror = cli_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 cli_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 cli_state *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;
1970 /* parse the command arguements */
1971 if (argc < 5) {
1972 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1973 " <value> <data>\n",
1974 argv[0]);
1975 return WERR_INVALID_PARAM;
1978 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1979 strupper_m(servername);
1980 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1981 fstrcpy(user, cli->user_name);
1983 value.type = REG_NONE;
1985 if (strequal(argv[2], "string")) {
1986 value.type = REG_SZ;
1989 if (strequal(argv[2], "binary")) {
1990 value.type = REG_BINARY;
1993 if (strequal(argv[2], "dword")) {
1994 value.type = REG_DWORD;
1997 if (strequal(argv[2], "multistring")) {
1998 value.type = REG_MULTI_SZ;
2001 if (value.type == REG_NONE) {
2002 printf("Unknown data type: %s\n", argv[2]);
2003 return WERR_INVALID_PARAM;
2006 /* get a printer handle */
2007 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2008 MAXIMUM_ALLOWED_ACCESS, servername,
2009 user, &pol);
2010 if (!W_ERROR_IS_OK(result))
2011 goto done;
2013 opened_hnd = True;
2015 ctr.printers_0 = &info;
2017 result = cli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2019 if (!W_ERROR_IS_OK(result))
2020 goto done;
2022 printf("%s\n", timestring(True));
2023 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2025 /* Set the printer data */
2027 fstrcpy(value.valuename, argv[3]);
2029 switch (value.type) {
2030 case REG_SZ: {
2031 UNISTR2 data;
2032 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2033 value.size = data.uni_str_len * 2;
2034 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2035 break;
2037 case REG_DWORD: {
2038 uint32 data = strtoul(argv[4], NULL, 10);
2039 value.size = sizeof(data);
2040 value.data_p = TALLOC_MEMDUP(mem_ctx, &data, sizeof(data));
2041 break;
2043 case REG_BINARY: {
2044 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2045 value.data_p = data.data;
2046 value.size = data.length;
2047 break;
2049 case REG_MULTI_SZ: {
2050 int i;
2051 size_t len = 0;
2052 char *p;
2054 for (i=4; i<argc; i++) {
2055 if (strcmp(argv[i], "NULL") == 0) {
2056 argv[i] = "";
2058 len += strlen(argv[i])+1;
2061 value.size = len*2;
2062 value.data_p = TALLOC_ARRAY(mem_ctx, char, value.size);
2063 if (value.data_p == NULL) {
2064 result = WERR_NOMEM;
2065 goto done;
2068 p = value.data_p;
2069 len = value.size;
2070 for (i=4; i<argc; i++) {
2071 size_t l = (strlen(argv[i])+1)*2;
2072 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2073 p += l;
2074 len -= l;
2076 SMB_ASSERT(len == 0);
2077 break;
2079 default:
2080 printf("Unknown data type: %s\n", argv[2]);
2081 result = WERR_INVALID_PARAM;
2082 goto done;
2085 result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2087 if (!W_ERROR_IS_OK(result)) {
2088 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2089 goto done;
2091 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2093 result = cli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2095 if (!W_ERROR_IS_OK(result))
2096 goto done;
2098 printf("%s\n", timestring(True));
2099 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2101 done:
2102 /* cleanup */
2103 if (opened_hnd)
2104 cli_spoolss_close_printer(cli, mem_ctx, &pol);
2106 return result;
2109 /****************************************************************************
2110 ****************************************************************************/
2112 static void display_job_info_1(JOB_INFO_1 *job)
2114 fstring username = "", document = "", text_status = "";
2116 rpcstr_pull(username, job->username.buffer,
2117 sizeof(username), -1, STR_TERMINATE);
2119 rpcstr_pull(document, job->document.buffer,
2120 sizeof(document), -1, STR_TERMINATE);
2122 rpcstr_pull(text_status, job->text_status.buffer,
2123 sizeof(text_status), -1, STR_TERMINATE);
2125 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2126 username, document, text_status, job->pagesprinted,
2127 job->totalpages);
2130 /****************************************************************************
2131 ****************************************************************************/
2133 static void display_job_info_2(JOB_INFO_2 *job)
2135 fstring username = "", document = "", text_status = "";
2137 rpcstr_pull(username, job->username.buffer,
2138 sizeof(username), -1, STR_TERMINATE);
2140 rpcstr_pull(document, job->document.buffer,
2141 sizeof(document), -1, STR_TERMINATE);
2143 rpcstr_pull(text_status, job->text_status.buffer,
2144 sizeof(text_status), -1, STR_TERMINATE);
2146 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2147 username, document, text_status, job->pagesprinted,
2148 job->totalpages, job->size);
2151 /****************************************************************************
2152 ****************************************************************************/
2154 static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
2155 TALLOC_CTX *mem_ctx, int argc,
2156 const char **argv)
2158 WERROR result;
2159 uint32 needed, offered, level = 1, num_jobs, i;
2160 BOOL got_hnd = False;
2161 pstring printername;
2162 fstring servername, user;
2163 POLICY_HND hnd;
2164 JOB_INFO_CTR ctr;
2166 if (argc < 2 || argc > 3) {
2167 printf("Usage: %s printername [level]\n", argv[0]);
2168 return WERR_OK;
2171 if (argc == 3)
2172 level = atoi(argv[2]);
2174 /* Open printer handle */
2176 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2177 strupper_m(servername);
2178 fstrcpy(user, cli->user_name);
2179 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
2180 strupper_m(printername);
2181 pstrcat(printername, argv[1]);
2183 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2184 "", MAXIMUM_ALLOWED_ACCESS,
2185 servername, user, &hnd);
2187 if (!W_ERROR_IS_OK(result))
2188 goto done;
2190 got_hnd = True;
2192 /* Enumerate ports */
2194 offered = needed = 0;
2195 result = cli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2196 &num_jobs, &ctr);
2198 if (!W_ERROR_IS_OK(result))
2199 goto done;
2201 for (i = 0; i < num_jobs; i++) {
2202 switch(level) {
2203 case 1:
2204 display_job_info_1(&ctr.job.job_info_1[i]);
2205 break;
2206 case 2:
2207 display_job_info_2(&ctr.job.job_info_2[i]);
2208 break;
2209 default:
2210 d_printf("unknown info level %d\n", level);
2211 break;
2215 done:
2216 if (got_hnd)
2217 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2219 return result;
2222 /****************************************************************************
2223 ****************************************************************************/
2225 static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
2226 TALLOC_CTX *mem_ctx, int argc,
2227 const char **argv)
2229 WERROR result;
2230 uint32 i=0, val_needed, data_needed;
2231 BOOL got_hnd = False;
2232 pstring printername;
2233 fstring servername, user;
2234 POLICY_HND hnd;
2236 if (argc != 2) {
2237 printf("Usage: %s printername\n", argv[0]);
2238 return WERR_OK;
2241 /* Open printer handle */
2243 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2244 strupper_m(servername);
2245 fstrcpy(user, cli->user_name);
2246 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2247 strupper_m(printername);
2248 pstrcat(printername, argv[1]);
2250 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2251 "", MAXIMUM_ALLOWED_ACCESS,
2252 servername, user, &hnd);
2254 if (!W_ERROR_IS_OK(result))
2255 goto done;
2257 got_hnd = True;
2259 /* Enumerate data */
2261 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2262 &val_needed, &data_needed,
2263 NULL);
2264 while (W_ERROR_IS_OK(result)) {
2265 REGISTRY_VALUE value;
2266 result = cli_spoolss_enumprinterdata(
2267 cli, mem_ctx, &hnd, i++, val_needed,
2268 data_needed, 0, 0, &value);
2269 if (W_ERROR_IS_OK(result))
2270 display_reg_value(value);
2272 if (W_ERROR_V(result) == ERRnomoreitems)
2273 result = W_ERROR(ERRsuccess);
2275 done:
2276 if (got_hnd)
2277 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2279 return result;
2282 /****************************************************************************
2283 ****************************************************************************/
2285 static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
2286 TALLOC_CTX *mem_ctx, int argc,
2287 const char **argv)
2289 WERROR result;
2290 uint32 i;
2291 BOOL got_hnd = False;
2292 pstring printername;
2293 fstring servername, user;
2294 const char *keyname = NULL;
2295 POLICY_HND hnd;
2296 REGVAL_CTR *ctr = NULL;
2298 if (argc != 3) {
2299 printf("Usage: %s printername <keyname>\n", argv[0]);
2300 return WERR_OK;
2303 keyname = argv[2];
2305 /* Open printer handle */
2307 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2308 strupper_m(servername);
2309 fstrcpy(user, cli->user_name);
2310 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2311 strupper_m(printername);
2312 pstrcat(printername, argv[1]);
2314 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2315 "", MAXIMUM_ALLOWED_ACCESS,
2316 servername, user, &hnd);
2318 if (!W_ERROR_IS_OK(result))
2319 goto done;
2321 got_hnd = True;
2323 /* Enumerate subkeys */
2325 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2326 return WERR_NOMEM;
2328 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2330 if (!W_ERROR_IS_OK(result))
2331 goto done;
2333 for (i=0; i < ctr->num_values; i++) {
2334 display_reg_value(*(ctr->values[i]));
2337 TALLOC_FREE( ctr );
2339 done:
2340 if (got_hnd)
2341 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2343 return result;
2346 /****************************************************************************
2347 ****************************************************************************/
2349 static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
2350 TALLOC_CTX *mem_ctx, int argc,
2351 const char **argv)
2353 WERROR result;
2354 BOOL got_hnd = False;
2355 pstring printername;
2356 fstring servername, user;
2357 const char *keyname = NULL;
2358 POLICY_HND hnd;
2359 uint16 *keylist = NULL, *curkey;
2361 if (argc < 2 || argc > 3) {
2362 printf("Usage: %s printername [keyname]\n", argv[0]);
2363 return WERR_OK;
2366 if (argc == 3)
2367 keyname = argv[2];
2368 else
2369 keyname = "";
2371 /* Open printer handle */
2373 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2374 strupper_m(servername);
2375 fstrcpy(user, cli->user_name);
2376 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2377 strupper_m(printername);
2378 pstrcat(printername, argv[1]);
2380 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2381 "", MAXIMUM_ALLOWED_ACCESS,
2382 servername, user, &hnd);
2384 if (!W_ERROR_IS_OK(result))
2385 goto done;
2387 got_hnd = True;
2389 /* Enumerate subkeys */
2391 result = cli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2393 if (!W_ERROR_IS_OK(result))
2394 goto done;
2396 curkey = keylist;
2397 while (*curkey != 0) {
2398 pstring subkey;
2399 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2400 STR_TERMINATE);
2401 printf("%s\n", subkey);
2402 curkey += strlen(subkey) + 1;
2405 safe_free(keylist);
2407 done:
2408 if (got_hnd)
2409 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2411 return result;
2414 /****************************************************************************
2415 ****************************************************************************/
2417 static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
2418 TALLOC_CTX *mem_ctx, int argc,
2419 const char **argv)
2421 fstring servername, printername;
2422 POLICY_HND hnd;
2423 BOOL got_hnd = False;
2424 WERROR result;
2425 SPOOL_NOTIFY_OPTION option;
2427 if (argc != 2) {
2428 printf("Usage: %s printername\n", argv[0]);
2429 result = WERR_OK;
2430 goto done;
2433 /* Open printer */
2435 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2436 strupper_m(servername);
2438 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
2439 argv[1]);
2440 strupper_m(printername);
2442 result = cli_spoolss_open_printer_ex(
2443 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2444 servername, cli->user_name, &hnd);
2446 if (!W_ERROR_IS_OK(result)) {
2447 printf("Error opening %s\n", argv[1]);
2448 goto done;
2451 got_hnd = True;
2453 /* Create spool options */
2455 ZERO_STRUCT(option);
2457 option.version = 2;
2458 option.option_type_ptr = 1;
2459 option.count = option.ctr.count = 2;
2461 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2463 ZERO_STRUCT(option.ctr.type[0]);
2464 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2465 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2466 option.ctr.type[0].fields_ptr = 1;
2467 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2469 ZERO_STRUCT(option.ctr.type[1]);
2470 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2471 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2472 option.ctr.type[1].fields_ptr = 1;
2473 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2475 /* Send rffpcnex */
2477 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2478 strupper_m(servername);
2480 result = cli_spoolss_rffpcnex(
2481 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2483 if (!W_ERROR_IS_OK(result)) {
2484 printf("Error rffpcnex %s\n", argv[1]);
2485 goto done;
2488 done:
2489 if (got_hnd)
2490 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2492 return result;
2495 /****************************************************************************
2496 ****************************************************************************/
2498 static BOOL compare_printer( struct cli_state *cli1, POLICY_HND *hnd1,
2499 struct cli_state *cli2, POLICY_HND *hnd2 )
2501 PRINTER_INFO_CTR ctr1, ctr2;
2502 WERROR werror;
2503 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2505 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2506 werror = cli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2507 if ( !W_ERROR_IS_OK(werror) ) {
2508 printf("failed (%s)\n", dos_errstr(werror));
2509 talloc_destroy(mem_ctx);
2510 return False;
2512 printf("ok\n");
2514 printf("Retrieving printer properties for %s...", cli2->desthost);
2515 werror = cli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2516 if ( !W_ERROR_IS_OK(werror) ) {
2517 printf("failed (%s)\n", dos_errstr(werror));
2518 talloc_destroy(mem_ctx);
2519 return False;
2521 printf("ok\n");
2524 talloc_destroy(mem_ctx);
2526 return True;
2529 /****************************************************************************
2530 ****************************************************************************/
2532 static BOOL compare_printer_secdesc( struct cli_state *cli1, POLICY_HND *hnd1,
2533 struct cli_state *cli2, POLICY_HND *hnd2 )
2535 PRINTER_INFO_CTR ctr1, ctr2;
2536 WERROR werror;
2537 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2538 SEC_DESC *sd1, *sd2;
2539 BOOL result = True;
2542 printf("Retreiving printer security for %s...", cli1->desthost);
2543 werror = cli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2544 if ( !W_ERROR_IS_OK(werror) ) {
2545 printf("failed (%s)\n", dos_errstr(werror));
2546 result = False;
2547 goto done;
2549 printf("ok\n");
2551 printf("Retrieving printer security for %s...", cli2->desthost);
2552 werror = cli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2553 if ( !W_ERROR_IS_OK(werror) ) {
2554 printf("failed (%s)\n", dos_errstr(werror));
2555 result = False;
2556 goto done;
2558 printf("ok\n");
2561 printf("++ ");
2563 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2564 printf("NULL PRINTER_INFO_3!\n");
2565 result = False;
2566 goto done;
2569 sd1 = ctr1.printers_3->secdesc;
2570 sd2 = ctr2.printers_3->secdesc;
2572 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2573 printf("NULL secdesc!\n");
2574 result = False;
2575 goto done;
2578 if ( (ctr1.printers_3->flags != ctr1.printers_3->flags ) || !sec_desc_equal( sd1, sd2 ) ) {
2579 printf("Security Descriptors *not* equal!\n");
2580 result = False;
2581 goto done;
2584 printf("Security descriptors match\n");
2586 done:
2587 talloc_destroy(mem_ctx);
2588 return result;
2592 /****************************************************************************
2593 ****************************************************************************/
2595 static WERROR cmd_spoolss_printercmp(struct cli_state *cli,
2596 TALLOC_CTX *mem_ctx, int argc,
2597 const char **argv)
2599 fstring printername, servername1, servername2;
2600 pstring printername_path;
2601 struct cli_state *cli_server1 = cli;
2602 struct cli_state *cli_server2 = NULL;
2603 POLICY_HND hPrinter1, hPrinter2;
2604 NTSTATUS nt_status;
2605 WERROR werror;
2607 if ( argc != 3 ) {
2608 printf("Usage: %s <printer> <server>\n", argv[0]);
2609 return WERR_OK;
2612 fstrcpy( printername, argv[1] );
2614 fstr_sprintf( servername1, cli->desthost );
2615 fstrcpy( servername2, argv[2] );
2616 strupper_m( servername1 );
2617 strupper_m( servername2 );
2620 /* first get the connection to the remote server */
2622 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2623 NULL, 0,
2624 "IPC$", "IPC",
2625 cmdline_auth_info.username,
2626 lp_workgroup(),
2627 cmdline_auth_info.password,
2628 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2629 cmdline_auth_info.signing_state, NULL);
2631 if ( !NT_STATUS_IS_OK(nt_status) )
2632 return WERR_GENERAL_FAILURE;
2634 if ( !cli_nt_session_open(cli_server2, PI_SPOOLSS) )
2635 return WERR_GENERAL_FAILURE;
2637 /* now open up both printers */
2639 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2640 printf("Opening %s...", printername_path);
2641 werror = cli_spoolss_open_printer_ex( cli_server1, mem_ctx, printername_path,
2642 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2643 if ( !W_ERROR_IS_OK(werror) ) {
2644 printf("failed (%s)\n", dos_errstr(werror));
2645 goto done;
2647 printf("ok\n");
2649 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2650 printf("Opening %s...", printername_path);
2651 werror = cli_spoolss_open_printer_ex( cli_server2, mem_ctx, printername_path,
2652 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2653 if ( !W_ERROR_IS_OK(werror) ) {
2654 printf("failed (%s)\n", dos_errstr(werror));
2655 goto done;
2657 printf("ok\n");
2660 compare_printer( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2661 compare_printer_secdesc( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2662 #if 0
2663 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2664 #endif
2667 done:
2668 /* cleanup */
2670 printf("Closing printers...");
2671 cli_spoolss_close_printer( cli_server1, mem_ctx, &hPrinter1 );
2672 cli_spoolss_close_printer( cli_server2, mem_ctx, &hPrinter2 );
2673 printf("ok\n");
2675 /* close the second remote connection */
2677 cli_shutdown( cli_server2 );
2679 return WERR_OK;
2682 /* List of commands exported by this module */
2683 struct cmd_set spoolss_commands[] = {
2685 { "SPOOLSS" },
2687 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" },
2688 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" },
2689 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" },
2690 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, "Delete a printer driver with files", "" },
2691 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" },
2692 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" },
2693 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" },
2694 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" },
2695 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" },
2696 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" },
2697 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" },
2698 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" },
2699 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""},
2700 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" },
2701 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" },
2702 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" },
2703 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" },
2704 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" },
2705 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
2706 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" },
2707 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" },
2708 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" },
2709 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" },
2710 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" },
2711 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" },
2712 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, "Set printername", "" },
2713 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" },
2714 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" },
2715 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, "Printer comparison test", "" },
2717 { NULL }