2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001
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.
26 #include "rpcclient.h"
29 const char *long_archi;
30 const char *short_archi;
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 },
57 * rpcclient module for SPOOLSS rpc pipe.
59 * This generally just parses and checks command lines, and then calls
60 * a cli_spoolss function.
63 /****************************************************************************
64 function to do the mapping between the long architecture name and
66 ****************************************************************************/
67 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
71 DEBUG(107,("Getting architecture dependant directory\n"));
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));
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;
93 /**********************************************************************
94 * dummy function -- placeholder
96 static WERROR cmd_spoolss_not_implemented(struct cli_state *cli,
98 int argc, const char **argv)
100 printf ("(*) This command is not currently implemented.\n");
105 /***********************************************************************
106 * Get printer information
108 static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli,
110 int argc, const char **argv)
114 fstring servername, user;
118 printf("Usage: %s <printername>\n", argv[0]);
123 return WERR_GENERAL_FAILURE;
125 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
126 strupper_m(servername);
127 fstrcpy(user, cli->user_name);
128 fstrcpy(printername, argv[1]);
130 /* Open the printer handle */
132 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
133 "", PRINTER_ALL_ACCESS,
134 servername, user, &hnd);
136 if (W_ERROR_IS_OK(werror)) {
137 printf("Printer %s opened successfully\n", printername);
138 werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
140 if (!W_ERROR_IS_OK(werror)) {
141 printf("Error closing printer handle! (%s)\n",
142 get_dos_error_msg(werror));
150 /****************************************************************************
151 printer info level 0 display function
152 ****************************************************************************/
153 static void display_print_info_0(PRINTER_INFO_0 *i0)
156 fstring servername = "";
161 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
163 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
165 printf("\tprintername:[%s]\n", name);
166 printf("\tservername:[%s]\n", servername);
167 printf("\tcjobs:[0x%x]\n", i0->cjobs);
168 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
170 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
171 i0->day, i0->dayofweek);
172 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
173 i0->second, i0->milliseconds);
175 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
176 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
178 printf("\tmajorversion:[0x%x]\n", i0->major_version);
179 printf("\tbuildversion:[0x%x]\n", i0->build_version);
181 printf("\tunknown7:[0x%x]\n", i0->unknown7);
182 printf("\tunknown8:[0x%x]\n", i0->unknown8);
183 printf("\tunknown9:[0x%x]\n", i0->unknown9);
184 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
185 printf("\tunknown11:[0x%x]\n", i0->unknown11);
186 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
187 printf("\tunknown13:[0x%x]\n", i0->unknown13);
188 printf("\tunknown14:[0x%x]\n", i0->unknown14);
189 printf("\tunknown15:[0x%x]\n", i0->unknown15);
190 printf("\tunknown16:[0x%x]\n", i0->unknown16);
191 printf("\tchange_id:[0x%x]\n", i0->change_id);
192 printf("\tunknown18:[0x%x]\n", i0->unknown18);
193 printf("\tstatus:[0x%x]\n", i0->status);
194 printf("\tunknown20:[0x%x]\n", i0->unknown20);
195 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
196 printf("\tunknown22:[0x%x]\n", i0->unknown22);
197 printf("\tunknown23:[0x%x]\n", i0->unknown23);
198 printf("\tunknown24:[0x%x]\n", i0->unknown24);
199 printf("\tunknown25:[0x%x]\n", i0->unknown25);
200 printf("\tunknown26:[0x%x]\n", i0->unknown26);
201 printf("\tunknown27:[0x%x]\n", i0->unknown27);
202 printf("\tunknown28:[0x%x]\n", i0->unknown28);
203 printf("\tunknown29:[0x%x]\n", i0->unknown29);
208 /****************************************************************************
209 printer info level 1 display function
210 ****************************************************************************/
211 static void display_print_info_1(PRINTER_INFO_1 *i1)
217 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
220 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
221 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
223 printf("\tflags:[0x%x]\n", i1->flags);
224 printf("\tname:[%s]\n", name);
225 printf("\tdescription:[%s]\n", desc);
226 printf("\tcomment:[%s]\n", comm);
231 /****************************************************************************
232 printer info level 2 display function
233 ****************************************************************************/
234 static void display_print_info_2(PRINTER_INFO_2 *i2)
236 fstring servername = "";
237 fstring printername = "";
238 fstring sharename = "";
239 fstring portname = "";
240 fstring drivername = "";
241 fstring comment = "";
242 fstring location = "";
243 fstring sepfile = "";
244 fstring printprocessor = "";
245 fstring datatype = "";
246 fstring parameters = "";
248 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
250 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
252 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
254 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
256 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
258 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
260 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
262 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
264 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
266 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
268 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
270 printf("\tservername:[%s]\n", servername);
271 printf("\tprintername:[%s]\n", printername);
272 printf("\tsharename:[%s]\n", sharename);
273 printf("\tportname:[%s]\n", portname);
274 printf("\tdrivername:[%s]\n", drivername);
275 printf("\tcomment:[%s]\n", comment);
276 printf("\tlocation:[%s]\n", location);
277 printf("\tsepfile:[%s]\n", sepfile);
278 printf("\tprintprocessor:[%s]\n", printprocessor);
279 printf("\tdatatype:[%s]\n", datatype);
280 printf("\tparameters:[%s]\n", parameters);
281 printf("\tattributes:[0x%x]\n", i2->attributes);
282 printf("\tpriority:[0x%x]\n", i2->priority);
283 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
284 printf("\tstarttime:[0x%x]\n", i2->starttime);
285 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
286 printf("\tstatus:[0x%x]\n", i2->status);
287 printf("\tcjobs:[0x%x]\n", i2->cjobs);
288 printf("\taverageppm:[0x%x]\n", i2->averageppm);
291 display_sec_desc(i2->secdesc);
296 /****************************************************************************
297 printer info level 3 display function
298 ****************************************************************************/
299 static void display_print_info_3(PRINTER_INFO_3 *i3)
301 printf("\tflags:[0x%x]\n", i3->flags);
303 display_sec_desc(i3->secdesc);
308 /****************************************************************************
309 printer info level 7 display function
310 ****************************************************************************/
311 static void display_print_info_7(PRINTER_INFO_7 *i7)
314 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
315 printf("\tguid:[%s]\n", guid);
316 printf("\taction:[0x%x]\n", i7->action);
320 /* Enumerate printers */
322 static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
324 int argc, const char **argv)
327 uint32 info_level = 1;
328 PRINTER_INFO_CTR ctr;
329 uint32 i = 0, num_printers, needed;
334 printf("Usage: %s [level] [name]\n", argv[0]);
339 info_level = atoi(argv[1]);
342 fstrcpy(name, argv[2]);
344 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
348 /* Enumerate printers -- Should we enumerate types other
349 than PRINTER_ENUM_LOCAL? Maybe accept as a parameter? --jerry */
353 result = cli_spoolss_enum_printers(
354 cli, mem_ctx, 0, &needed, name, PRINTER_ENUM_LOCAL,
355 info_level, &num_printers, &ctr);
357 if (W_ERROR_V(result) == ERRinsufficientbuffer)
358 result = cli_spoolss_enum_printers(
359 cli, mem_ctx, needed, NULL, name, PRINTER_ENUM_LOCAL,
360 info_level, &num_printers, &ctr);
362 if (W_ERROR_IS_OK(result)) {
365 printf ("No printers returned.\n");
369 for (i = 0; i < num_printers; i++) {
372 display_print_info_0(&ctr.printers_0[i]);
375 display_print_info_1(&ctr.printers_1[i]);
378 display_print_info_2(&ctr.printers_2[i]);
381 display_print_info_3(&ctr.printers_3[i]);
384 printf("unknown info level %d\n", info_level);
394 /****************************************************************************
395 port info level 1 display function
396 ****************************************************************************/
397 static void display_port_info_1(PORT_INFO_1 *i1)
401 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
402 printf("\tPort Name:\t[%s]\n", buffer);
405 /****************************************************************************
406 port info level 2 display function
407 ****************************************************************************/
408 static void display_port_info_2(PORT_INFO_2 *i2)
412 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
413 printf("\tPort Name:\t[%s]\n", buffer);
414 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
416 printf("\tMonitor Name:\t[%s]\n", buffer);
417 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
419 printf("\tDescription:\t[%s]\n", buffer);
420 printf("\tPort Type:\t" );
421 if ( i2->port_type ) {
422 int comma = 0; /* hack */
424 if ( i2->port_type & PORT_TYPE_READ ) {
428 if ( i2->port_type & PORT_TYPE_WRITE ) {
429 printf( "%sWrite", comma ? ", " : "" );
432 /* These two have slightly different interpretations
433 on 95/98/ME but I'm disregarding that for now */
434 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
435 printf( "%sRedirected", comma ? ", " : "" );
438 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
439 printf( "%sNet-Attached", comma ? ", " : "" );
443 printf( "[Unset]\n" );
445 printf("\tReserved:\t[%d]\n", i2->reserved);
449 /* Enumerate ports */
451 static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
452 TALLOC_CTX *mem_ctx, int argc,
456 uint32 needed, info_level = 1;
461 printf("Usage: %s [level]\n", argv[0]);
466 info_level = atoi(argv[1]);
468 /* Enumerate ports */
472 result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level,
475 if (W_ERROR_V(result) == ERRinsufficientbuffer)
476 result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
477 info_level, &returned, &ctr);
479 if (W_ERROR_IS_OK(result)) {
482 for (i = 0; i < returned; i++) {
483 switch (info_level) {
485 display_port_info_1(&ctr.port.info_1[i]);
488 display_port_info_2(&ctr.port.info_2[i]);
491 printf("unknown info level %d\n", info_level);
500 /***********************************************************************
501 * Set printer comment - use a level2 set.
503 static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
505 int argc, const char **argv)
510 uint32 info_level = 2;
511 BOOL opened_hnd = False;
512 PRINTER_INFO_CTR ctr;
518 if (argc == 1 || argc > 3) {
519 printf("Usage: %s printername comment\n", argv[0]);
524 /* Open a printer handle */
526 fstrcpy(comment, argv[2]);
529 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
530 strupper_m(servername);
531 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
532 fstrcpy(user, cli->user_name);
534 /* get a printer handle */
535 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
536 PRINTER_ALL_ACCESS, servername,
539 if (!W_ERROR_IS_OK(result))
544 /* Get printer info */
545 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
547 if (W_ERROR_V(result) == ERRinsufficientbuffer)
548 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
550 if (!W_ERROR_IS_OK(result))
554 /* Modify the comment. */
555 init_unistr(&ctr.printers_2->comment, comment);
556 ctr.printers_2->devmode = NULL;
557 ctr.printers_2->secdesc = NULL;
559 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
560 if (W_ERROR_IS_OK(result))
561 printf("Success in setting comment.\n");
565 cli_spoolss_close_printer(cli, mem_ctx, &pol);
570 /***********************************************************************
571 * Set printer name - use a level2 set.
573 static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
575 int argc, const char **argv)
580 uint32 info_level = 2;
581 BOOL opened_hnd = False;
582 PRINTER_INFO_CTR ctr;
588 if (argc == 1 || argc > 3) {
589 printf("Usage: %s printername new_printername\n", argv[0]);
594 /* Open a printer handle */
596 fstrcpy(new_printername, argv[2]);
599 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
600 strupper_m(servername);
601 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
602 fstrcpy(user, cli->user_name);
604 /* get a printer handle */
605 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
606 PRINTER_ALL_ACCESS, servername,
609 if (!W_ERROR_IS_OK(result))
614 /* Get printer info */
615 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
617 if (W_ERROR_V(result) == ERRinsufficientbuffer)
618 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
620 if (!W_ERROR_IS_OK(result))
624 /* Modify the printername. */
625 init_unistr(&ctr.printers_2->printername, new_printername);
626 ctr.printers_2->devmode = NULL;
627 ctr.printers_2->secdesc = NULL;
629 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
630 if (W_ERROR_IS_OK(result))
631 printf("Success in setting printername.\n");
635 cli_spoolss_close_printer(cli, mem_ctx, &pol);
640 /***********************************************************************
641 * Get printer information
643 static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
645 int argc, const char **argv)
649 uint32 info_level = 1;
650 BOOL opened_hnd = False;
651 PRINTER_INFO_CTR ctr;
657 if (argc == 1 || argc > 3) {
658 printf("Usage: %s <printername> [level]\n", argv[0]);
662 /* Open a printer handle */
664 info_level = atoi(argv[2]);
667 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
668 strupper_m(servername);
669 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
670 fstrcpy(user, cli->user_name);
672 /* get a printer handle */
674 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
675 "", MAXIMUM_ALLOWED_ACCESS,
676 servername, user, &pol);
678 if (!W_ERROR_IS_OK(result))
683 /* Get printer info */
685 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
686 &pol, info_level, &ctr);
688 if (W_ERROR_V(result) == ERRinsufficientbuffer)
689 result = cli_spoolss_getprinter(
690 cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
692 if (!W_ERROR_IS_OK(result))
695 /* Display printer info */
697 switch (info_level) {
699 display_print_info_0(ctr.printers_0);
702 display_print_info_1(ctr.printers_1);
705 display_print_info_2(ctr.printers_2);
708 display_print_info_3(ctr.printers_3);
711 display_print_info_7(ctr.printers_7);
714 printf("unknown info level %d\n", info_level);
720 cli_spoolss_close_printer(cli, mem_ctx, &pol);
725 static void display_reg_value(REGISTRY_VALUE value)
731 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
732 *((uint32 *) value.data_p));
735 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
737 printf("%s: REG_SZ: %s\n", value.valuename, text);
740 printf("%s: REG_BINARY: unknown length value not displayed\n",
744 uint16 *curstr = (uint16 *) value.data_p;
745 uint8 *start = value.data_p;
746 printf("%s: REG_MULTI_SZ:\n", value.valuename);
747 while ((*curstr != 0) &&
748 ((uint8 *) curstr < start + value.size)) {
749 rpcstr_pull(text, curstr, sizeof(text), -1,
751 printf(" %s\n", text);
752 curstr += strlen(text) + 1;
757 printf("%s: unknown type %d\n", value.valuename, value.type);
762 /***********************************************************************
765 static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
767 int argc, const char **argv)
771 BOOL opened_hnd = False;
776 const char *valuename;
777 REGISTRY_VALUE value;
780 printf("Usage: %s <printername> <valuename>\n", argv[0]);
781 printf("<printername> of . queries print server\n");
786 /* Open a printer handle */
788 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
789 strupper_m(servername);
790 if (strncmp(argv[1], ".", sizeof(".")) == 0)
791 fstrcpy(printername, servername);
793 slprintf(printername, sizeof(servername)-1, "%s\\%s",
794 servername, argv[1]);
795 fstrcpy(user, cli->user_name);
797 /* get a printer handle */
799 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
800 "", MAXIMUM_ALLOWED_ACCESS,
801 servername, user, &pol);
803 if (!W_ERROR_IS_OK(result))
808 /* Get printer info */
810 result = cli_spoolss_getprinterdata(cli, mem_ctx, 0, &needed,
811 &pol, valuename, &value);
813 if (W_ERROR_V(result) == ERRmoredata)
814 result = cli_spoolss_getprinterdata(
815 cli, mem_ctx, needed, NULL, &pol, valuename, &value);
817 if (!W_ERROR_IS_OK(result))
820 /* Display printer data */
822 fstrcpy(value.valuename, valuename);
823 display_reg_value(value);
828 cli_spoolss_close_printer(cli, mem_ctx, &pol);
833 /***********************************************************************
836 static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
838 int argc, const char **argv)
842 BOOL opened_hnd = False;
847 const char *valuename, *keyname;
848 REGISTRY_VALUE value;
851 printf("Usage: %s <printername> <keyname> <valuename>\n",
853 printf("<printername> of . queries print server\n");
859 /* Open a printer handle */
861 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
862 strupper_m(servername);
863 if (strncmp(argv[1], ".", sizeof(".")) == 0)
864 fstrcpy(printername, servername);
866 slprintf(printername, sizeof(printername)-1, "%s\\%s",
867 servername, argv[1]);
868 fstrcpy(user, cli->user_name);
870 /* get a printer handle */
872 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
873 "", MAXIMUM_ALLOWED_ACCESS,
874 servername, user, &pol);
876 if (!W_ERROR_IS_OK(result))
881 /* Get printer info */
883 result = cli_spoolss_getprinterdataex(cli, mem_ctx, 0, &needed,
884 &pol, keyname, valuename,
887 if (W_ERROR_V(result) == ERRmoredata)
888 result = cli_spoolss_getprinterdataex(cli, mem_ctx, needed,
892 if (!W_ERROR_IS_OK(result))
895 /* Display printer data */
897 fstrcpy(value.valuename, valuename);
898 display_reg_value(value);
903 cli_spoolss_close_printer(cli, mem_ctx, &pol);
908 /****************************************************************************
909 printer info level 0 display function
910 ****************************************************************************/
911 static void display_print_driver_1(DRIVER_INFO_1 *i1)
917 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
919 printf ("Printer Driver Info 1:\n");
920 printf ("\tDriver Name: [%s]\n\n", name);
925 /****************************************************************************
926 printer info level 1 display function
927 ****************************************************************************/
928 static void display_print_driver_2(DRIVER_INFO_2 *i1)
931 fstring architecture;
938 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
939 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
940 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
941 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
942 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
944 printf ("Printer Driver Info 2:\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\n", configfile);
955 /****************************************************************************
956 printer info level 2 display function
957 ****************************************************************************/
958 static void display_print_driver_3(DRIVER_INFO_3 *i1)
961 fstring architecture = "";
962 fstring driverpath = "";
963 fstring datafile = "";
964 fstring configfile = "";
965 fstring helpfile = "";
966 fstring dependentfiles = "";
967 fstring monitorname = "";
968 fstring defaultdatatype = "";
976 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
977 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
978 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
979 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
980 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
981 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
982 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
983 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
985 printf ("Printer Driver Info 3:\n");
986 printf ("\tVersion: [%x]\n", i1->version);
987 printf ("\tDriver Name: [%s]\n",name);
988 printf ("\tArchitecture: [%s]\n", architecture);
989 printf ("\tDriver Path: [%s]\n", driverpath);
990 printf ("\tDatafile: [%s]\n", datafile);
991 printf ("\tConfigfile: [%s]\n", configfile);
992 printf ("\tHelpfile: [%s]\n\n", helpfile);
996 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
998 length+=strlen(dependentfiles)+1;
1000 if (strlen(dependentfiles) > 0)
1002 printf ("\tDependentfiles: [%s]\n", dependentfiles);
1012 printf ("\tMonitorname: [%s]\n", monitorname);
1013 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
1018 /***********************************************************************
1019 * Get printer information
1021 static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
1022 TALLOC_CTX *mem_ctx,
1023 int argc, const char **argv)
1027 uint32 info_level = 3;
1028 BOOL opened_hnd = False;
1029 PRINTER_DRIVER_CTR ctr;
1030 fstring printername,
1034 BOOL success = False;
1036 if ((argc == 1) || (argc > 3))
1038 printf("Usage: %s <printername> [level]\n", argv[0]);
1042 /* get the arguments need to open the printer handle */
1043 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1044 strupper_m(servername);
1045 fstrcpy(user, cli->user_name);
1046 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1048 info_level = atoi(argv[2]);
1050 /* Open a printer handle */
1052 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1054 servername, user, &pol);
1056 if (!W_ERROR_IS_OK(werror)) {
1057 printf("Error opening printer handle for %s!\n", printername);
1063 /* loop through and print driver info level for each architecture */
1065 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1068 werror = cli_spoolss_getprinterdriver(
1069 cli, mem_ctx, 0, &needed, &pol, info_level,
1070 archi_table[i].long_archi, archi_table[i].version,
1073 if (W_ERROR_V(werror) == ERRinsufficientbuffer) {
1074 werror = cli_spoolss_getprinterdriver(
1075 cli, mem_ctx, needed, NULL, &pol, info_level,
1076 archi_table[i].long_archi, archi_table[i].version,
1080 if (!W_ERROR_IS_OK(werror))
1083 /* need at least one success */
1087 printf ("\n[%s]\n", archi_table[i].long_archi);
1089 switch (info_level) {
1091 display_print_driver_1 (ctr.info1);
1094 display_print_driver_2 (ctr.info2);
1097 display_print_driver_3 (ctr.info3);
1100 printf("unknown info level %d\n", info_level);
1108 cli_spoolss_close_printer (cli, mem_ctx, &pol);
1116 /***********************************************************************
1117 * Get printer information
1119 static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
1120 TALLOC_CTX *mem_ctx,
1121 int argc, const char **argv)
1124 uint32 info_level = 1;
1125 PRINTER_DRIVER_CTR ctr;
1131 printf("Usage: enumdrivers [level]\n");
1136 info_level = atoi(argv[1]);
1139 /* loop through and print driver info level for each architecture */
1140 for (i=0; archi_table[i].long_archi!=NULL; i++)
1144 /* check to see if we already asked for this architecture string */
1146 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1149 werror = cli_spoolss_enumprinterdrivers(
1150 cli, mem_ctx, 0, &needed, info_level,
1151 archi_table[i].long_archi, &returned, &ctr);
1153 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1154 werror = cli_spoolss_enumprinterdrivers(
1155 cli, mem_ctx, needed, NULL, info_level,
1156 archi_table[i].long_archi, &returned, &ctr);
1158 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1159 printf ("Server does not support environment [%s]\n",
1160 archi_table[i].long_archi);
1168 if (!W_ERROR_IS_OK(werror)) {
1169 printf ("Error getting driver for environment [%s] - %d\n",
1170 archi_table[i].long_archi, W_ERROR_V(werror));
1174 printf ("\n[%s]\n", archi_table[i].long_archi);
1179 for (j=0; j < returned; j++) {
1180 display_print_driver_1 (&(ctr.info1[j]));
1184 for (j=0; j < returned; j++) {
1185 display_print_driver_2 (&(ctr.info2[j]));
1189 for (j=0; j < returned; j++) {
1190 display_print_driver_3 (&(ctr.info3[j]));
1194 printf("unknown info level %d\n", info_level);
1202 /****************************************************************************
1203 printer info level 1 display function
1204 ****************************************************************************/
1205 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1211 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1213 printf ("\tDirectory Name:[%s]\n", name);
1216 /***********************************************************************
1217 * Get printer driver directory information
1219 static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli,
1220 TALLOC_CTX *mem_ctx,
1221 int argc, const char **argv)
1225 DRIVER_DIRECTORY_CTR ctr;
1229 printf("Usage: %s [environment]\n", argv[0]);
1233 /* Get the arguments need to open the printer handle */
1236 fstrcpy (env, argv[1]);
1238 fstrcpy (env, "Windows NT x86");
1240 /* Get the directory. Only use Info level 1 */
1242 result = cli_spoolss_getprinterdriverdir(
1243 cli, mem_ctx, 0, &needed, 1, env, &ctr);
1245 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1246 result = cli_spoolss_getprinterdriverdir(
1247 cli, mem_ctx, needed, NULL, 1, env, &ctr);
1249 if (W_ERROR_IS_OK(result))
1250 display_printdriverdir_1(ctr.info1);
1255 /*******************************************************************************
1256 set the version and environment fields of a DRIVER_INFO_3 struct
1257 ******************************************************************************/
1258 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1263 for (i=0; archi_table[i].long_archi != NULL; i++)
1265 if (strcmp(arch, archi_table[i].short_archi) == 0)
1267 info->version = archi_table[i].version;
1268 init_unistr (&info->architecture, archi_table[i].long_archi);
1273 if (archi_table[i].long_archi == NULL)
1275 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1282 /**************************************************************************
1283 wrapper for strtok to get the next parameter from a delimited list.
1284 Needed to handle the empty parameter string denoted by "NULL"
1285 *************************************************************************/
1286 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1290 /* get the next token */
1291 ptr = strtok(str, delim);
1293 /* a string of 'NULL' is used to represent an empty
1294 parameter because two consecutive delimiters
1295 will not return an empty string. See man strtok(3)
1297 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1301 init_unistr(dest, ptr);
1306 /********************************************************************************
1307 fill in the members of a DRIVER_INFO_3 struct using a character
1308 string in the form of
1309 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1310 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1311 <Default Data Type>:<Comma Separated list of Files>
1312 *******************************************************************************/
1313 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1319 /* fill in the UNISTR fields */
1320 str = get_driver_3_param (args, ":", &info->name);
1321 str = get_driver_3_param (NULL, ":", &info->driverpath);
1322 str = get_driver_3_param (NULL, ":", &info->datafile);
1323 str = get_driver_3_param (NULL, ":", &info->configfile);
1324 str = get_driver_3_param (NULL, ":", &info->helpfile);
1325 str = get_driver_3_param (NULL, ":", &info->monitorname);
1326 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1328 /* <Comma Separated List of Dependent Files> */
1329 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1332 /* begin to strip out each filename */
1333 str = strtok(str, ",");
1337 /* keep a cumlative count of the str lengths */
1338 len += strlen(str)+1;
1339 str = strtok(NULL, ",");
1342 /* allocate the space; add one extra slot for a terminating NULL.
1343 Each filename is NULL terminated and the end contains a double
1345 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1347 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1350 for (i=0; i<len; i++)
1352 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1354 info->dependentfiles[len] = '\0';
1360 static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
1361 TALLOC_CTX *mem_ctx,
1362 int argc, const char **argv)
1366 PRINTER_DRIVER_CTR ctr;
1367 DRIVER_INFO_3 info3;
1369 fstring driver_name;
1372 /* parse the command arguements */
1373 if (argc != 3 && argc != 4)
1375 printf ("Usage: %s <Environment> \\\n", argv[0]);
1376 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1377 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1378 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1379 printf ("\t[version]\n");
1384 /* Fill in the DRIVER_INFO_3 struct */
1386 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1388 printf ("Error Unknown architechture [%s]\n", argv[1]);
1389 return WERR_INVALID_PARAM;
1392 set_drv_info_3_env(&info3, arch);
1394 driver_args = talloc_strdup( mem_ctx, argv[2] );
1395 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1397 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1398 return WERR_INVALID_PARAM;
1401 /* if printer driver version specified, override the default version
1402 * used by the architecture. This allows installation of Windows
1403 * 2000 (version 3) printer drivers. */
1406 info3.version = atoi(argv[3]);
1411 result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1413 if (W_ERROR_IS_OK(result)) {
1414 rpcstr_pull(driver_name, info3.name.buffer,
1415 sizeof(driver_name), -1, STR_TERMINATE);
1416 printf ("Printer Driver %s successfully installed.\n",
1424 static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
1425 TALLOC_CTX *mem_ctx,
1426 int argc, const char **argv)
1430 PRINTER_INFO_CTR ctr;
1431 PRINTER_INFO_2 info2;
1434 /* parse the command arguements */
1437 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1441 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1442 strupper_m(servername);
1444 /* Fill in the DRIVER_INFO_2 struct */
1447 init_unistr( &info2.servername, servername);
1449 init_unistr( &info2.printername, argv[1]);
1450 init_unistr( &info2.sharename, argv[2]);
1451 init_unistr( &info2.drivername, argv[3]);
1452 init_unistr( &info2.portname, argv[4]);
1453 init_unistr( &info2.comment, "Created by rpcclient");
1454 init_unistr( &info2.printprocessor, "winprint");
1455 init_unistr( &info2.datatype, "RAW");
1456 info2.devmode = NULL;
1457 info2.secdesc = NULL;
1458 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1460 info2.defaultpriority = 0;
1461 info2.starttime = 0;
1462 info2.untiltime = 0;
1464 /* These three fields must not be used by AddPrinter()
1465 as defined in the MS Platform SDK documentation..
1469 info2.averageppm = 0;
1472 ctr.printers_2 = &info2;
1473 result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1475 if (W_ERROR_IS_OK(result))
1476 printf ("Printer %s successfully installed.\n", argv[1]);
1481 static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
1482 TALLOC_CTX *mem_ctx,
1483 int argc, const char **argv)
1488 BOOL opened_hnd = False;
1489 PRINTER_INFO_CTR ctr;
1490 PRINTER_INFO_2 info2;
1496 /* parse the command arguements */
1499 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1503 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1504 strupper_m(servername);
1505 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1506 fstrcpy(user, cli->user_name);
1508 /* Get a printer handle */
1510 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1512 servername, user, &pol);
1514 if (!W_ERROR_IS_OK(result))
1519 /* Get printer info */
1521 ZERO_STRUCT (info2);
1522 ctr.printers_2 = &info2;
1524 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
1527 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1528 result = cli_spoolss_getprinter(
1529 cli, mem_ctx, needed, NULL, &pol, level, &ctr);
1531 if (!W_ERROR_IS_OK(result)) {
1532 printf ("Unable to retrieve printer information!\n");
1536 /* Set the printer driver */
1538 init_unistr(&ctr.printers_2->drivername, argv[2]);
1540 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1542 if (!W_ERROR_IS_OK(result)) {
1543 printf("SetPrinter call failed!\n");
1547 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1553 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1559 static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli,
1560 TALLOC_CTX *mem_ctx,
1561 int argc, const char **argv)
1563 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1568 const char *arch = NULL;
1570 /* parse the command arguements */
1571 if (argc < 2 || argc > 4) {
1572 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1579 vers = atoi (argv[3]);
1582 /* delete the driver for all architectures */
1583 for (i=0; archi_table[i].long_archi; i++) {
1585 if (arch && !strequal( archi_table[i].long_archi, arch))
1588 if (vers >= 0 && archi_table[i].version != vers)
1591 /* make the call to remove the driver */
1592 result = cli_spoolss_deleteprinterdriverex(
1593 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1595 if ( !W_ERROR_IS_OK(result) )
1597 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1598 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1599 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1604 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1605 archi_table[i].long_archi, archi_table[i].version);
1614 static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
1615 TALLOC_CTX *mem_ctx,
1616 int argc, const char **argv)
1622 /* parse the command arguements */
1625 printf ("Usage: %s <driver>\n", argv[0]);
1629 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1630 strupper_m(servername);
1632 /* delete the driver for all architectures */
1633 for (i=0; archi_table[i].long_archi; i++)
1635 /* make the call to remove the driver */
1636 result = cli_spoolss_deleteprinterdriver(
1637 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1639 if ( !W_ERROR_IS_OK(result) ) {
1640 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1641 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1642 argv[1], archi_table[i].long_archi,
1648 printf ("Driver %s removed for arch [%s].\n", argv[1],
1649 archi_table[i].long_archi);
1656 static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
1657 TALLOC_CTX *mem_ctx,
1658 int argc, const char **argv)
1661 char *servername = NULL, *environment = NULL;
1665 /* parse the command arguements */
1667 printf ("Usage: %s [environment]\n", argv[0]);
1671 if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1673 strupper_m(servername);
1675 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1676 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1677 SAFE_FREE(servername);
1681 result = cli_spoolss_getprintprocessordirectory(
1682 cli, mem_ctx, 0, &needed, servername, environment, procdir);
1684 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1685 result = cli_spoolss_getprintprocessordirectory(
1686 cli, mem_ctx, needed, NULL, servername, environment,
1689 if (W_ERROR_IS_OK(result))
1690 printf("%s\n", procdir);
1692 SAFE_FREE(servername);
1693 SAFE_FREE(environment);
1700 static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1701 int argc, const char **argv)
1705 char *servername = NULL, *printername = NULL;
1707 BOOL got_handle = False;
1709 /* Parse the command arguements */
1712 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1716 /* Get a printer handle */
1718 asprintf(&servername, "\\\\%s", cli->desthost);
1719 strupper_m(servername);
1720 asprintf(&printername, "%s\\%s", servername, argv[1]);
1722 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1724 servername, cli->user_name, &handle);
1726 if (!W_ERROR_IS_OK(werror))
1731 /* Dummy up some values for the form data */
1733 form.flags = FORM_USER;
1734 form.size_x = form.size_y = 100;
1740 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1745 werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1749 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1751 SAFE_FREE(servername);
1752 SAFE_FREE(printername);
1759 static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1760 int argc, const char **argv)
1764 char *servername = NULL, *printername = NULL;
1766 BOOL got_handle = False;
1768 /* Parse the command arguements */
1771 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1775 /* Get a printer handle */
1777 asprintf(&servername, "\\\\%s", cli->desthost);
1778 strupper_m(servername);
1779 asprintf(&printername, "%s\\%s", servername, argv[1]);
1781 werror = cli_spoolss_open_printer_ex(
1782 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1783 servername, cli->user_name, &handle);
1785 if (!W_ERROR_IS_OK(werror))
1790 /* Dummy up some values for the form data */
1792 form.flags = FORM_PRINTER;
1793 form.size_x = form.size_y = 100;
1799 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1803 werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1807 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1809 SAFE_FREE(servername);
1810 SAFE_FREE(printername);
1815 static const char *get_form_flag(int form_flag)
1817 switch (form_flag) {
1821 return "FORM_BUILTIN";
1823 return "FORM_PRINTER";
1829 static void display_form(FORM_1 *form)
1831 fstring form_name = "";
1833 if (form->name.buffer)
1834 rpcstr_pull(form_name, form->name.buffer,
1835 sizeof(form_name), -1, STR_TERMINATE);
1838 "\tflag: %s (%d)\n" \
1839 "\twidth: %d, length: %d\n" \
1840 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1841 form_name, get_form_flag(form->flag), form->flag,
1842 form->width, form->length,
1843 form->left, form->right,
1844 form->top, form->bottom);
1849 static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1850 int argc, const char **argv)
1854 char *servername = NULL, *printername = NULL;
1856 BOOL got_handle = False;
1859 /* Parse the command arguements */
1862 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1866 /* Get a printer handle */
1868 asprintf(&servername, "\\\\%s", cli->desthost);
1869 strupper_m(servername);
1870 asprintf(&printername, "%s\\%s", servername, argv[1]);
1872 werror = cli_spoolss_open_printer_ex(
1873 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1874 servername, cli->user_name, &handle);
1876 if (!W_ERROR_IS_OK(werror))
1883 werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
1884 &handle, argv[2], 1, &form);
1886 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1887 werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
1888 &handle, argv[2], 1, &form);
1890 if (!W_ERROR_IS_OK(werror))
1893 display_form(&form);
1897 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1899 SAFE_FREE(servername);
1900 SAFE_FREE(printername);
1907 static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
1908 TALLOC_CTX *mem_ctx, int argc,
1913 char *servername = NULL, *printername = NULL;
1914 BOOL got_handle = False;
1916 /* Parse the command arguements */
1919 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1923 /* Get a printer handle */
1925 asprintf(&servername, "\\\\%s", cli->desthost);
1926 strupper_m(servername);
1927 asprintf(&printername, "%s\\%s", servername, argv[1]);
1929 werror = cli_spoolss_open_printer_ex(
1930 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1931 servername, cli->user_name, &handle);
1933 if (!W_ERROR_IS_OK(werror))
1938 /* Delete the form */
1940 werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1944 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1946 SAFE_FREE(servername);
1947 SAFE_FREE(printername);
1952 /* Enumerate forms */
1954 static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
1955 TALLOC_CTX *mem_ctx, int argc,
1960 char *servername = NULL, *printername = NULL;
1961 BOOL got_handle = False;
1962 uint32 needed, num_forms, level = 1, i;
1965 /* Parse the command arguements */
1968 printf ("Usage: %s <printer>\n", argv[0]);
1972 /* Get a printer handle */
1974 asprintf(&servername, "\\\\%s", cli->desthost);
1975 strupper_m(servername);
1976 asprintf(&printername, "%s\\%s", servername, argv[1]);
1978 werror = cli_spoolss_open_printer_ex(
1979 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1980 servername, cli->user_name, &handle);
1982 if (!W_ERROR_IS_OK(werror))
1987 /* Enumerate forms */
1989 werror = cli_spoolss_enumforms(
1990 cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
1992 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1993 werror = cli_spoolss_enumforms(
1994 cli, mem_ctx, needed, NULL, &handle, level,
1995 &num_forms, &forms);
1997 if (!W_ERROR_IS_OK(werror))
2000 /* Display output */
2002 for (i = 0; i < num_forms; i++) {
2004 display_form(&forms[i]);
2010 cli_spoolss_close_printer(cli, mem_ctx, &handle);
2012 SAFE_FREE(servername);
2013 SAFE_FREE(printername);
2018 static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
2019 TALLOC_CTX *mem_ctx,
2020 int argc, const char **argv)
2024 fstring servername, printername, user;
2026 BOOL opened_hnd = False;
2027 PRINTER_INFO_CTR ctr;
2028 PRINTER_INFO_0 info;
2029 REGISTRY_VALUE value;
2032 /* parse the command arguements */
2034 printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
2038 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2039 strupper_m(servername);
2040 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
2041 fstrcpy(user, cli->user_name);
2043 /* get a printer handle */
2044 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2045 MAXIMUM_ALLOWED_ACCESS, servername,
2047 if (!W_ERROR_IS_OK(result))
2052 ctr.printers_0 = &info;
2054 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
2057 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2058 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2060 if (!W_ERROR_IS_OK(result))
2063 printf("%s\n", timestring(True));
2064 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2066 /* Set the printer data */
2068 init_unistr2(&data, argv[3], UNI_STR_TERMINATE);
2069 fstrcpy(value.valuename, argv[2]);
2070 value.type = REG_SZ;
2071 value.size = data.uni_str_len * 2;
2072 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2074 result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2076 if (!W_ERROR_IS_OK(result)) {
2077 printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
2080 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
2082 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
2084 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2085 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2087 if (!W_ERROR_IS_OK(result))
2090 printf("%s\n", timestring(True));
2091 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2096 cli_spoolss_close_printer(cli, mem_ctx, &pol);
2101 static void display_job_info_1(JOB_INFO_1 *job)
2103 fstring username = "", document = "", text_status = "";
2105 rpcstr_pull(username, job->username.buffer,
2106 sizeof(username), -1, STR_TERMINATE);
2108 rpcstr_pull(document, job->document.buffer,
2109 sizeof(document), -1, STR_TERMINATE);
2111 rpcstr_pull(text_status, job->text_status.buffer,
2112 sizeof(text_status), -1, STR_TERMINATE);
2114 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2115 username, document, text_status, job->pagesprinted,
2119 static void display_job_info_2(JOB_INFO_2 *job)
2121 fstring username = "", document = "", text_status = "";
2123 rpcstr_pull(username, job->username.buffer,
2124 sizeof(username), -1, STR_TERMINATE);
2126 rpcstr_pull(document, job->document.buffer,
2127 sizeof(document), -1, STR_TERMINATE);
2129 rpcstr_pull(text_status, job->text_status.buffer,
2130 sizeof(text_status), -1, STR_TERMINATE);
2132 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2133 username, document, text_status, job->pagesprinted,
2134 job->totalpages, job->size);
2137 /* Enumerate jobs */
2139 static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
2140 TALLOC_CTX *mem_ctx, int argc,
2144 uint32 needed, level = 1, num_jobs, i;
2145 BOOL got_hnd = False;
2146 pstring printername;
2147 fstring servername, user;
2151 if (argc < 2 || argc > 3) {
2152 printf("Usage: %s printername [level]\n", argv[0]);
2157 level = atoi(argv[2]);
2159 /* Open printer handle */
2161 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2162 strupper_m(servername);
2163 fstrcpy(user, cli->user_name);
2164 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
2165 strupper_m(printername);
2166 pstrcat(printername, argv[1]);
2168 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2169 "", MAXIMUM_ALLOWED_ACCESS,
2170 servername, user, &hnd);
2172 if (!W_ERROR_IS_OK(result))
2177 /* Enumerate ports */
2179 result = cli_spoolss_enumjobs(
2180 cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
2183 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2184 result = cli_spoolss_enumjobs(
2185 cli, mem_ctx, needed, NULL, &hnd, level, 0,
2186 1000, &num_jobs, &ctr);
2188 if (!W_ERROR_IS_OK(result))
2191 for (i = 0; i < num_jobs; i++) {
2194 display_job_info_1(&ctr.job.job_info_1[i]);
2197 display_job_info_2(&ctr.job.job_info_2[i]);
2200 d_printf("unknown info level %d\n", level);
2207 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2212 /* enumerate data */
2214 static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
2215 TALLOC_CTX *mem_ctx, int argc,
2219 uint32 i=0, val_needed, data_needed;
2220 BOOL got_hnd = False;
2221 pstring printername;
2222 fstring servername, user;
2226 printf("Usage: %s printername\n", argv[0]);
2230 /* Open printer handle */
2232 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2233 strupper_m(servername);
2234 fstrcpy(user, cli->user_name);
2235 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2236 strupper_m(printername);
2237 pstrcat(printername, argv[1]);
2239 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2240 "", MAXIMUM_ALLOWED_ACCESS,
2241 servername, user, &hnd);
2243 if (!W_ERROR_IS_OK(result))
2248 /* Enumerate data */
2250 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2251 &val_needed, &data_needed,
2253 while (W_ERROR_IS_OK(result)) {
2254 REGISTRY_VALUE value;
2255 result = cli_spoolss_enumprinterdata(
2256 cli, mem_ctx, &hnd, i++, val_needed,
2257 data_needed, 0, 0, &value);
2258 if (W_ERROR_IS_OK(result))
2259 display_reg_value(value);
2261 if (W_ERROR_V(result) == ERRnomoreitems)
2262 result = W_ERROR(ERRsuccess);
2266 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2271 /* enumerate data for a given key */
2273 static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
2274 TALLOC_CTX *mem_ctx, int argc,
2279 BOOL got_hnd = False;
2280 pstring printername;
2281 fstring servername, user;
2282 const char *keyname = NULL;
2287 printf("Usage: %s printername <keyname>\n", argv[0]);
2293 /* Open printer handle */
2295 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2296 strupper_m(servername);
2297 fstrcpy(user, cli->user_name);
2298 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2299 strupper_m(printername);
2300 pstrcat(printername, argv[1]);
2302 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2303 "", MAXIMUM_ALLOWED_ACCESS,
2304 servername, user, &hnd);
2306 if (!W_ERROR_IS_OK(result))
2311 /* Enumerate subkeys */
2313 result = cli_spoolss_enumprinterdataex(
2314 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
2316 if (W_ERROR_V(result) == ERRmoredata)
2317 result = cli_spoolss_enumprinterdataex(
2318 cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
2320 if (!W_ERROR_IS_OK(result))
2323 for (i=0; i < ctr.num_values; i++) {
2324 display_reg_value(*(ctr.values[i]));
2327 regval_ctr_destroy(&ctr);
2331 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2336 /* enumerate subkeys */
2338 static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
2339 TALLOC_CTX *mem_ctx, int argc,
2343 uint32 needed, returned;
2344 BOOL got_hnd = False;
2345 pstring printername;
2346 fstring servername, user;
2347 const char *keyname = NULL;
2349 uint16 *keylist = NULL, *curkey;
2351 if (argc < 2 || argc > 3) {
2352 printf("Usage: %s printername [keyname]\n", argv[0]);
2361 /* Open printer handle */
2363 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2364 strupper_m(servername);
2365 fstrcpy(user, cli->user_name);
2366 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2367 strupper_m(printername);
2368 pstrcat(printername, argv[1]);
2370 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2371 "", MAXIMUM_ALLOWED_ACCESS,
2372 servername, user, &hnd);
2374 if (!W_ERROR_IS_OK(result))
2379 /* Enumerate subkeys */
2381 result = cli_spoolss_enumprinterkey(
2382 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
2384 if (W_ERROR_V(result) == ERRmoredata)
2385 result = cli_spoolss_enumprinterkey(
2386 cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
2389 if (!W_ERROR_IS_OK(result))
2393 while (*curkey != 0) {
2395 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2397 printf("%s\n", subkey);
2398 curkey += strlen(subkey) + 1;
2405 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2410 static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
2411 TALLOC_CTX *mem_ctx, int argc,
2414 fstring servername, printername;
2416 BOOL got_hnd = False;
2418 SPOOL_NOTIFY_OPTION option;
2421 printf("Usage: %s printername\n", argv[0]);
2428 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2429 strupper_m(servername);
2431 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
2433 strupper_m(printername);
2435 result = cli_spoolss_open_printer_ex(
2436 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2437 servername, cli->user_name, &hnd);
2439 if (!W_ERROR_IS_OK(result)) {
2440 printf("Error opening %s\n", argv[1]);
2446 /* Create spool options */
2448 ZERO_STRUCT(option);
2451 option.option_type_ptr = 1;
2452 option.count = option.ctr.count = 2;
2454 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2456 ZERO_STRUCT(option.ctr.type[0]);
2457 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2458 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2459 option.ctr.type[0].fields_ptr = 1;
2460 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2462 ZERO_STRUCT(option.ctr.type[1]);
2463 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2464 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2465 option.ctr.type[1].fields_ptr = 1;
2466 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2470 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2471 strupper_m(servername);
2473 result = cli_spoolss_rffpcnex(
2474 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2476 if (!W_ERROR_IS_OK(result)) {
2477 printf("Error rffpcnex %s\n", argv[1]);
2483 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2488 /* List of commands exported by this module */
2489 struct cmd_set spoolss_commands[] = {
2493 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" },
2494 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" },
2495 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" },
2496 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, "Delete a printer driver with files", "" },
2497 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" },
2498 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" },
2499 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" },
2500 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" },
2501 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" },
2502 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" },
2503 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" },
2504 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" },
2505 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""},
2506 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" },
2507 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" },
2508 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" },
2509 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" },
2510 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" },
2511 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
2512 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" },
2513 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" },
2514 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" },
2515 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" },
2516 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" },
2517 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" },
2518 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, "Set printername", "" },
2519 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" },
2520 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" },