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 (const 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 (
1314 TALLOC_CTX *mem_ctx,
1315 DRIVER_INFO_3 *info,
1322 /* fill in the UNISTR fields */
1323 str = get_driver_3_param (args, ":", &info->name);
1324 str = get_driver_3_param (NULL, ":", &info->driverpath);
1325 str = get_driver_3_param (NULL, ":", &info->datafile);
1326 str = get_driver_3_param (NULL, ":", &info->configfile);
1327 str = get_driver_3_param (NULL, ":", &info->helpfile);
1328 str = get_driver_3_param (NULL, ":", &info->monitorname);
1329 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1331 /* <Comma Separated List of Dependent Files> */
1332 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1335 /* begin to strip out each filename */
1336 str = strtok(str, ",");
1340 /* keep a cumlative count of the str lengths */
1341 len += strlen(str)+1;
1342 str = strtok(NULL, ",");
1345 /* allocate the space; add one extra slot for a terminating NULL.
1346 Each filename is NULL terminated and the end contains a double
1348 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1350 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1353 for (i=0; i<len; i++)
1355 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1357 info->dependentfiles[len] = '\0';
1363 static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
1364 TALLOC_CTX *mem_ctx,
1365 int argc, const char **argv)
1369 PRINTER_DRIVER_CTR ctr;
1370 DRIVER_INFO_3 info3;
1372 fstring driver_name;
1374 /* parse the command arguements */
1375 if (argc != 3 && argc != 4)
1377 printf ("Usage: %s <Environment> \\\n", argv[0]);
1378 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1379 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1380 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1381 printf ("\t[version]\n");
1386 /* Fill in the DRIVER_INFO_3 struct */
1388 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1390 printf ("Error Unknown architechture [%s]\n", argv[1]);
1391 return WERR_INVALID_PARAM;
1394 set_drv_info_3_env(&info3, arch);
1396 if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
1398 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1399 return WERR_INVALID_PARAM;
1402 /* if printer driver version specified, override the default version
1403 * used by the architecture. This allows installation of Windows
1404 * 2000 (version 3) printer drivers. */
1407 info3.version = atoi(argv[3]);
1412 result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1414 if (W_ERROR_IS_OK(result)) {
1415 rpcstr_pull(driver_name, info3.name.buffer,
1416 sizeof(driver_name), -1, STR_TERMINATE);
1417 printf ("Printer Driver %s successfully installed.\n",
1425 static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
1426 TALLOC_CTX *mem_ctx,
1427 int argc, const char **argv)
1431 PRINTER_INFO_CTR ctr;
1432 PRINTER_INFO_2 info2;
1435 /* parse the command arguements */
1438 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1442 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1443 strupper_m(servername);
1445 /* Fill in the DRIVER_INFO_2 struct */
1448 init_unistr( &info2.servername, servername);
1450 init_unistr( &info2.printername, argv[1]);
1451 init_unistr( &info2.sharename, argv[2]);
1452 init_unistr( &info2.drivername, argv[3]);
1453 init_unistr( &info2.portname, argv[4]);
1454 init_unistr( &info2.comment, "Created by rpcclient");
1455 init_unistr( &info2.printprocessor, "winprint");
1456 init_unistr( &info2.datatype, "RAW");
1457 info2.devmode = NULL;
1458 info2.secdesc = NULL;
1459 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1461 info2.defaultpriority = 0;
1462 info2.starttime = 0;
1463 info2.untiltime = 0;
1465 /* These three fields must not be used by AddPrinter()
1466 as defined in the MS Platform SDK documentation..
1470 info2.averageppm = 0;
1473 ctr.printers_2 = &info2;
1474 result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1476 if (W_ERROR_IS_OK(result))
1477 printf ("Printer %s successfully installed.\n", argv[1]);
1482 static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
1483 TALLOC_CTX *mem_ctx,
1484 int argc, const char **argv)
1489 BOOL opened_hnd = False;
1490 PRINTER_INFO_CTR ctr;
1491 PRINTER_INFO_2 info2;
1497 /* parse the command arguements */
1500 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1504 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1505 strupper_m(servername);
1506 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1507 fstrcpy(user, cli->user_name);
1509 /* Get a printer handle */
1511 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1513 servername, user, &pol);
1515 if (!W_ERROR_IS_OK(result))
1520 /* Get printer info */
1522 ZERO_STRUCT (info2);
1523 ctr.printers_2 = &info2;
1525 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
1528 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1529 result = cli_spoolss_getprinter(
1530 cli, mem_ctx, needed, NULL, &pol, level, &ctr);
1532 if (!W_ERROR_IS_OK(result)) {
1533 printf ("Unable to retrieve printer information!\n");
1537 /* Set the printer driver */
1539 init_unistr(&ctr.printers_2->drivername, argv[2]);
1541 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1543 if (!W_ERROR_IS_OK(result)) {
1544 printf("SetPrinter call failed!\n");
1548 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1554 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1560 static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli,
1561 TALLOC_CTX *mem_ctx,
1562 int argc, const char **argv)
1564 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1569 const char *arch = NULL;
1571 /* parse the command arguements */
1572 if (argc < 2 || argc > 4) {
1573 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1580 vers = atoi (argv[3]);
1583 /* delete the driver for all architectures */
1584 for (i=0; archi_table[i].long_archi; i++) {
1586 if (arch && !strequal( archi_table[i].long_archi, arch))
1589 if (vers >= 0 && archi_table[i].version != vers)
1592 /* make the call to remove the driver */
1593 result = cli_spoolss_deleteprinterdriverex(
1594 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1596 if ( !W_ERROR_IS_OK(result) )
1598 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1599 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1600 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1605 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1606 archi_table[i].long_archi, archi_table[i].version);
1615 static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
1616 TALLOC_CTX *mem_ctx,
1617 int argc, const char **argv)
1623 /* parse the command arguements */
1626 printf ("Usage: %s <driver>\n", argv[0]);
1630 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1631 strupper_m(servername);
1633 /* delete the driver for all architectures */
1634 for (i=0; archi_table[i].long_archi; i++)
1636 /* make the call to remove the driver */
1637 result = cli_spoolss_deleteprinterdriver(
1638 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1640 if ( !W_ERROR_IS_OK(result) ) {
1641 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1642 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1643 argv[1], archi_table[i].long_archi,
1649 printf ("Driver %s removed for arch [%s].\n", argv[1],
1650 archi_table[i].long_archi);
1657 static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
1658 TALLOC_CTX *mem_ctx,
1659 int argc, const char **argv)
1662 char *servername = NULL, *environment = NULL;
1666 /* parse the command arguements */
1668 printf ("Usage: %s [environment]\n", argv[0]);
1672 if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1674 strupper_m(servername);
1676 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1677 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1678 SAFE_FREE(servername);
1682 result = cli_spoolss_getprintprocessordirectory(
1683 cli, mem_ctx, 0, &needed, servername, environment, procdir);
1685 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1686 result = cli_spoolss_getprintprocessordirectory(
1687 cli, mem_ctx, needed, NULL, servername, environment,
1690 if (W_ERROR_IS_OK(result))
1691 printf("%s\n", procdir);
1693 SAFE_FREE(servername);
1694 SAFE_FREE(environment);
1701 static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1702 int argc, const char **argv)
1706 char *servername = NULL, *printername = NULL;
1708 BOOL got_handle = False;
1710 /* Parse the command arguements */
1713 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1717 /* Get a printer handle */
1719 asprintf(&servername, "\\\\%s", cli->desthost);
1720 strupper_m(servername);
1721 asprintf(&printername, "%s\\%s", servername, argv[1]);
1723 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1725 servername, cli->user_name, &handle);
1727 if (!W_ERROR_IS_OK(werror))
1732 /* Dummy up some values for the form data */
1734 form.flags = FORM_USER;
1735 form.size_x = form.size_y = 100;
1741 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1746 werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1750 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1752 SAFE_FREE(servername);
1753 SAFE_FREE(printername);
1760 static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1761 int argc, const char **argv)
1765 char *servername = NULL, *printername = NULL;
1767 BOOL got_handle = False;
1769 /* Parse the command arguements */
1772 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1776 /* Get a printer handle */
1778 asprintf(&servername, "\\\\%s", cli->desthost);
1779 strupper_m(servername);
1780 asprintf(&printername, "%s\\%s", servername, argv[1]);
1782 werror = cli_spoolss_open_printer_ex(
1783 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1784 servername, cli->user_name, &handle);
1786 if (!W_ERROR_IS_OK(werror))
1791 /* Dummy up some values for the form data */
1793 form.flags = FORM_PRINTER;
1794 form.size_x = form.size_y = 100;
1800 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1804 werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1808 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1810 SAFE_FREE(servername);
1811 SAFE_FREE(printername);
1816 static const char *get_form_flag(int form_flag)
1818 switch (form_flag) {
1822 return "FORM_BUILTIN";
1824 return "FORM_PRINTER";
1830 static void display_form(FORM_1 *form)
1832 fstring form_name = "";
1834 if (form->name.buffer)
1835 rpcstr_pull(form_name, form->name.buffer,
1836 sizeof(form_name), -1, STR_TERMINATE);
1839 "\tflag: %s (%d)\n" \
1840 "\twidth: %d, length: %d\n" \
1841 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1842 form_name, get_form_flag(form->flag), form->flag,
1843 form->width, form->length,
1844 form->left, form->right,
1845 form->top, form->bottom);
1850 static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1851 int argc, const char **argv)
1855 char *servername = NULL, *printername = NULL;
1857 BOOL got_handle = False;
1860 /* Parse the command arguements */
1863 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1867 /* Get a printer handle */
1869 asprintf(&servername, "\\\\%s", cli->desthost);
1870 strupper_m(servername);
1871 asprintf(&printername, "%s\\%s", servername, argv[1]);
1873 werror = cli_spoolss_open_printer_ex(
1874 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1875 servername, cli->user_name, &handle);
1877 if (!W_ERROR_IS_OK(werror))
1884 werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
1885 &handle, argv[2], 1, &form);
1887 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1888 werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
1889 &handle, argv[2], 1, &form);
1891 if (!W_ERROR_IS_OK(werror))
1894 display_form(&form);
1898 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1900 SAFE_FREE(servername);
1901 SAFE_FREE(printername);
1908 static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
1909 TALLOC_CTX *mem_ctx, int argc,
1914 char *servername = NULL, *printername = NULL;
1915 BOOL got_handle = False;
1917 /* Parse the command arguements */
1920 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1924 /* Get a printer handle */
1926 asprintf(&servername, "\\\\%s", cli->desthost);
1927 strupper_m(servername);
1928 asprintf(&printername, "%s\\%s", servername, argv[1]);
1930 werror = cli_spoolss_open_printer_ex(
1931 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1932 servername, cli->user_name, &handle);
1934 if (!W_ERROR_IS_OK(werror))
1939 /* Delete the form */
1941 werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1945 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1947 SAFE_FREE(servername);
1948 SAFE_FREE(printername);
1953 /* Enumerate forms */
1955 static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
1956 TALLOC_CTX *mem_ctx, int argc,
1961 char *servername = NULL, *printername = NULL;
1962 BOOL got_handle = False;
1963 uint32 needed, num_forms, level = 1, i;
1966 /* Parse the command arguements */
1969 printf ("Usage: %s <printer>\n", argv[0]);
1973 /* Get a printer handle */
1975 asprintf(&servername, "\\\\%s", cli->desthost);
1976 strupper_m(servername);
1977 asprintf(&printername, "%s\\%s", servername, argv[1]);
1979 werror = cli_spoolss_open_printer_ex(
1980 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1981 servername, cli->user_name, &handle);
1983 if (!W_ERROR_IS_OK(werror))
1988 /* Enumerate forms */
1990 werror = cli_spoolss_enumforms(
1991 cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
1993 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1994 werror = cli_spoolss_enumforms(
1995 cli, mem_ctx, needed, NULL, &handle, level,
1996 &num_forms, &forms);
1998 if (!W_ERROR_IS_OK(werror))
2001 /* Display output */
2003 for (i = 0; i < num_forms; i++) {
2005 display_form(&forms[i]);
2011 cli_spoolss_close_printer(cli, mem_ctx, &handle);
2013 SAFE_FREE(servername);
2014 SAFE_FREE(printername);
2019 static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
2020 TALLOC_CTX *mem_ctx,
2021 int argc, const char **argv)
2025 fstring servername, printername, user;
2027 BOOL opened_hnd = False;
2028 PRINTER_INFO_CTR ctr;
2029 PRINTER_INFO_0 info;
2030 REGISTRY_VALUE value;
2033 /* parse the command arguements */
2035 printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
2039 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2040 strupper_m(servername);
2041 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
2042 fstrcpy(user, cli->user_name);
2044 /* get a printer handle */
2045 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2046 MAXIMUM_ALLOWED_ACCESS, servername,
2048 if (!W_ERROR_IS_OK(result))
2053 ctr.printers_0 = &info;
2055 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
2058 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2059 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2061 if (!W_ERROR_IS_OK(result))
2064 printf("%s\n", timestring(True));
2065 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2067 /* Set the printer data */
2069 init_unistr2(&data, argv[3], UNI_STR_TERMINATE);
2070 fstrcpy(value.valuename, argv[2]);
2071 value.type = REG_SZ;
2072 value.size = data.uni_str_len * 2;
2073 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2075 result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2077 if (!W_ERROR_IS_OK(result)) {
2078 printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
2081 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
2083 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
2085 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2086 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2088 if (!W_ERROR_IS_OK(result))
2091 printf("%s\n", timestring(True));
2092 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2097 cli_spoolss_close_printer(cli, mem_ctx, &pol);
2102 static void display_job_info_1(JOB_INFO_1 *job)
2104 fstring username = "", document = "", text_status = "";
2106 rpcstr_pull(username, job->username.buffer,
2107 sizeof(username), -1, STR_TERMINATE);
2109 rpcstr_pull(document, job->document.buffer,
2110 sizeof(document), -1, STR_TERMINATE);
2112 rpcstr_pull(text_status, job->text_status.buffer,
2113 sizeof(text_status), -1, STR_TERMINATE);
2115 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2116 username, document, text_status, job->pagesprinted,
2120 static void display_job_info_2(JOB_INFO_2 *job)
2122 fstring username = "", document = "", text_status = "";
2124 rpcstr_pull(username, job->username.buffer,
2125 sizeof(username), -1, STR_TERMINATE);
2127 rpcstr_pull(document, job->document.buffer,
2128 sizeof(document), -1, STR_TERMINATE);
2130 rpcstr_pull(text_status, job->text_status.buffer,
2131 sizeof(text_status), -1, STR_TERMINATE);
2133 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2134 username, document, text_status, job->pagesprinted,
2135 job->totalpages, job->size);
2138 /* Enumerate jobs */
2140 static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
2141 TALLOC_CTX *mem_ctx, int argc,
2145 uint32 needed, level = 1, num_jobs, i;
2146 BOOL got_hnd = False;
2147 pstring printername;
2148 fstring servername, user;
2152 if (argc < 2 || argc > 3) {
2153 printf("Usage: %s printername [level]\n", argv[0]);
2158 level = atoi(argv[2]);
2160 /* Open printer handle */
2162 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2163 strupper_m(servername);
2164 fstrcpy(user, cli->user_name);
2165 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
2166 strupper_m(printername);
2167 pstrcat(printername, argv[1]);
2169 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2170 "", MAXIMUM_ALLOWED_ACCESS,
2171 servername, user, &hnd);
2173 if (!W_ERROR_IS_OK(result))
2178 /* Enumerate ports */
2180 result = cli_spoolss_enumjobs(
2181 cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
2184 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2185 result = cli_spoolss_enumjobs(
2186 cli, mem_ctx, needed, NULL, &hnd, level, 0,
2187 1000, &num_jobs, &ctr);
2189 if (!W_ERROR_IS_OK(result))
2192 for (i = 0; i < num_jobs; i++) {
2195 display_job_info_1(&ctr.job.job_info_1[i]);
2198 display_job_info_2(&ctr.job.job_info_2[i]);
2201 d_printf("unknown info level %d\n", level);
2208 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2213 /* enumerate data */
2215 static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
2216 TALLOC_CTX *mem_ctx, int argc,
2220 uint32 i=0, val_needed, data_needed;
2221 BOOL got_hnd = False;
2222 pstring printername;
2223 fstring servername, user;
2227 printf("Usage: %s printername\n", argv[0]);
2231 /* Open printer handle */
2233 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2234 strupper_m(servername);
2235 fstrcpy(user, cli->user_name);
2236 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2237 strupper_m(printername);
2238 pstrcat(printername, argv[1]);
2240 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2241 "", MAXIMUM_ALLOWED_ACCESS,
2242 servername, user, &hnd);
2244 if (!W_ERROR_IS_OK(result))
2249 /* Enumerate data */
2251 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2252 &val_needed, &data_needed,
2254 while (W_ERROR_IS_OK(result)) {
2255 REGISTRY_VALUE value;
2256 result = cli_spoolss_enumprinterdata(
2257 cli, mem_ctx, &hnd, i++, val_needed,
2258 data_needed, 0, 0, &value);
2259 if (W_ERROR_IS_OK(result))
2260 display_reg_value(value);
2262 if (W_ERROR_V(result) == ERRnomoreitems)
2263 result = W_ERROR(ERRsuccess);
2267 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2272 /* enumerate data for a given key */
2274 static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
2275 TALLOC_CTX *mem_ctx, int argc,
2280 BOOL got_hnd = False;
2281 pstring printername;
2282 fstring servername, user;
2283 const char *keyname = NULL;
2288 printf("Usage: %s printername <keyname>\n", argv[0]);
2294 /* Open printer handle */
2296 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2297 strupper_m(servername);
2298 fstrcpy(user, cli->user_name);
2299 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2300 strupper_m(printername);
2301 pstrcat(printername, argv[1]);
2303 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2304 "", MAXIMUM_ALLOWED_ACCESS,
2305 servername, user, &hnd);
2307 if (!W_ERROR_IS_OK(result))
2312 /* Enumerate subkeys */
2314 result = cli_spoolss_enumprinterdataex(
2315 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
2317 if (W_ERROR_V(result) == ERRmoredata)
2318 result = cli_spoolss_enumprinterdataex(
2319 cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
2321 if (!W_ERROR_IS_OK(result))
2324 for (i=0; i < ctr.num_values; i++) {
2325 display_reg_value(*(ctr.values[i]));
2328 regval_ctr_destroy(&ctr);
2332 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2337 /* enumerate subkeys */
2339 static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
2340 TALLOC_CTX *mem_ctx, int argc,
2344 uint32 needed, returned;
2345 BOOL got_hnd = False;
2346 pstring printername;
2347 fstring servername, user;
2348 const char *keyname = NULL;
2350 uint16 *keylist = NULL, *curkey;
2352 if (argc < 2 || argc > 3) {
2353 printf("Usage: %s printername [keyname]\n", argv[0]);
2362 /* Open printer handle */
2364 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2365 strupper_m(servername);
2366 fstrcpy(user, cli->user_name);
2367 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2368 strupper_m(printername);
2369 pstrcat(printername, argv[1]);
2371 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2372 "", MAXIMUM_ALLOWED_ACCESS,
2373 servername, user, &hnd);
2375 if (!W_ERROR_IS_OK(result))
2380 /* Enumerate subkeys */
2382 result = cli_spoolss_enumprinterkey(
2383 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
2385 if (W_ERROR_V(result) == ERRmoredata)
2386 result = cli_spoolss_enumprinterkey(
2387 cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
2390 if (!W_ERROR_IS_OK(result))
2394 while (*curkey != 0) {
2396 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2398 printf("%s\n", subkey);
2399 curkey += strlen(subkey) + 1;
2406 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2411 static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
2412 TALLOC_CTX *mem_ctx, int argc,
2415 fstring servername, printername;
2417 BOOL got_hnd = False;
2419 SPOOL_NOTIFY_OPTION option;
2422 printf("Usage: %s printername\n", argv[0]);
2429 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2430 strupper_m(servername);
2432 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
2434 strupper_m(printername);
2436 result = cli_spoolss_open_printer_ex(
2437 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2438 servername, cli->user_name, &hnd);
2440 if (!W_ERROR_IS_OK(result)) {
2441 printf("Error opening %s\n", argv[1]);
2447 /* Create spool options */
2449 ZERO_STRUCT(option);
2452 option.option_type_ptr = 1;
2453 option.count = option.ctr.count = 2;
2455 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2457 ZERO_STRUCT(option.ctr.type[0]);
2458 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2459 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2460 option.ctr.type[0].fields_ptr = 1;
2461 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2463 ZERO_STRUCT(option.ctr.type[1]);
2464 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2465 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2466 option.ctr.type[1].fields_ptr = 1;
2467 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2471 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2472 strupper_m(servername);
2474 result = cli_spoolss_rffpcnex(
2475 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2477 if (!W_ERROR_IS_OK(result)) {
2478 printf("Error rffpcnex %s\n", argv[1]);
2484 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2489 /* List of commands exported by this module */
2490 struct cmd_set spoolss_commands[] = {
2494 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" },
2495 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" },
2496 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" },
2497 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, "Delete a printer driver with files", "" },
2498 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" },
2499 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" },
2500 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" },
2501 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" },
2502 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" },
2503 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" },
2504 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" },
2505 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" },
2506 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""},
2507 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" },
2508 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" },
2509 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" },
2510 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" },
2511 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" },
2512 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
2513 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" },
2514 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" },
2515 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" },
2516 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" },
2517 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" },
2518 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" },
2519 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, "Set printername", "" },
2520 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" },
2521 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" },