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);
1818 static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1819 int argc, const char **argv)
1823 char *servername = NULL, *printername = NULL;
1825 BOOL got_handle = False;
1828 /* Parse the command arguements */
1831 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1835 /* Get a printer handle */
1837 asprintf(&servername, "\\\\%s", cli->desthost);
1838 strupper_m(servername);
1839 asprintf(&printername, "%s\\%s", servername, argv[1]);
1841 werror = cli_spoolss_open_printer_ex(
1842 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1843 servername, cli->user_name, &handle);
1845 if (!W_ERROR_IS_OK(werror))
1852 werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
1853 &handle, argv[2], 1, &form);
1855 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1856 werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
1857 &handle, argv[2], 1, &form);
1859 if (!W_ERROR_IS_OK(werror))
1862 printf("width: %d\n", form.width);
1863 printf("length: %d\n", form.length);
1864 printf("left: %d\n", form.left);
1865 printf("top: %d\n", form.top);
1866 printf("right: %d\n", form.right);
1867 printf("bottom: %d\n", form.bottom);
1871 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1873 SAFE_FREE(servername);
1874 SAFE_FREE(printername);
1881 static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
1882 TALLOC_CTX *mem_ctx, int argc,
1887 char *servername = NULL, *printername = NULL;
1888 BOOL got_handle = False;
1890 /* Parse the command arguements */
1893 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1897 /* Get a printer handle */
1899 asprintf(&servername, "\\\\%s", cli->desthost);
1900 strupper_m(servername);
1901 asprintf(&printername, "%s\\%s", servername, argv[1]);
1903 werror = cli_spoolss_open_printer_ex(
1904 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1905 servername, cli->user_name, &handle);
1907 if (!W_ERROR_IS_OK(werror))
1912 /* Delete the form */
1914 werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1918 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1920 SAFE_FREE(servername);
1921 SAFE_FREE(printername);
1926 /* Enumerate forms */
1928 static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
1929 TALLOC_CTX *mem_ctx, int argc,
1934 char *servername = NULL, *printername = NULL;
1935 BOOL got_handle = False;
1936 uint32 needed, num_forms, level = 1, i;
1939 /* Parse the command arguements */
1942 printf ("Usage: %s <printer>\n", argv[0]);
1946 /* Get a printer handle */
1948 asprintf(&servername, "\\\\%s", cli->desthost);
1949 strupper_m(servername);
1950 asprintf(&printername, "%s\\%s", servername, argv[1]);
1952 werror = cli_spoolss_open_printer_ex(
1953 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1954 servername, cli->user_name, &handle);
1956 if (!W_ERROR_IS_OK(werror))
1961 /* Enumerate forms */
1963 werror = cli_spoolss_enumforms(
1964 cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
1966 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1967 werror = cli_spoolss_enumforms(
1968 cli, mem_ctx, needed, NULL, &handle, level,
1969 &num_forms, &forms);
1971 if (!W_ERROR_IS_OK(werror))
1974 /* Display output */
1976 for (i = 0; i < num_forms; i++) {
1979 if (forms[i].name.buffer)
1980 rpcstr_pull(form_name, forms[i].name.buffer,
1981 sizeof(form_name), -1, STR_TERMINATE);
1983 printf("%s\n", form_name);
1988 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1990 SAFE_FREE(servername);
1991 SAFE_FREE(printername);
1996 static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
1997 TALLOC_CTX *mem_ctx,
1998 int argc, const char **argv)
2002 fstring servername, printername, user;
2004 BOOL opened_hnd = False;
2005 PRINTER_INFO_CTR ctr;
2006 PRINTER_INFO_0 info;
2007 REGISTRY_VALUE value;
2010 /* parse the command arguements */
2012 printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
2016 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2017 strupper_m(servername);
2018 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
2019 fstrcpy(user, cli->user_name);
2021 /* get a printer handle */
2022 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2023 MAXIMUM_ALLOWED_ACCESS, servername,
2025 if (!W_ERROR_IS_OK(result))
2030 ctr.printers_0 = &info;
2032 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
2035 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2036 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2038 if (!W_ERROR_IS_OK(result))
2041 printf("%s\n", timestring(True));
2042 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2044 /* Set the printer data */
2046 init_unistr2(&data, argv[3], UNI_STR_TERMINATE);
2047 fstrcpy(value.valuename, argv[2]);
2048 value.type = REG_SZ;
2049 value.size = data.uni_str_len * 2;
2050 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2052 result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2054 if (!W_ERROR_IS_OK(result)) {
2055 printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
2058 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
2060 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
2062 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2063 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2065 if (!W_ERROR_IS_OK(result))
2068 printf("%s\n", timestring(True));
2069 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2074 cli_spoolss_close_printer(cli, mem_ctx, &pol);
2079 static void display_job_info_1(JOB_INFO_1 *job)
2081 fstring username = "", document = "", text_status = "";
2083 rpcstr_pull(username, job->username.buffer,
2084 sizeof(username), -1, STR_TERMINATE);
2086 rpcstr_pull(document, job->document.buffer,
2087 sizeof(document), -1, STR_TERMINATE);
2089 rpcstr_pull(text_status, job->text_status.buffer,
2090 sizeof(text_status), -1, STR_TERMINATE);
2092 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2093 username, document, text_status, job->pagesprinted,
2097 static void display_job_info_2(JOB_INFO_2 *job)
2099 fstring username = "", document = "", text_status = "";
2101 rpcstr_pull(username, job->username.buffer,
2102 sizeof(username), -1, STR_TERMINATE);
2104 rpcstr_pull(document, job->document.buffer,
2105 sizeof(document), -1, STR_TERMINATE);
2107 rpcstr_pull(text_status, job->text_status.buffer,
2108 sizeof(text_status), -1, STR_TERMINATE);
2110 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2111 username, document, text_status, job->pagesprinted,
2112 job->totalpages, job->size);
2115 /* Enumerate jobs */
2117 static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
2118 TALLOC_CTX *mem_ctx, int argc,
2122 uint32 needed, level = 1, num_jobs, i;
2123 BOOL got_hnd = False;
2124 pstring printername;
2125 fstring servername, user;
2129 if (argc < 2 || argc > 3) {
2130 printf("Usage: %s printername [level]\n", argv[0]);
2135 level = atoi(argv[2]);
2137 /* Open printer handle */
2139 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2140 strupper_m(servername);
2141 fstrcpy(user, cli->user_name);
2142 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
2143 strupper_m(printername);
2144 pstrcat(printername, argv[1]);
2146 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2147 "", MAXIMUM_ALLOWED_ACCESS,
2148 servername, user, &hnd);
2150 if (!W_ERROR_IS_OK(result))
2155 /* Enumerate ports */
2157 result = cli_spoolss_enumjobs(
2158 cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
2161 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2162 result = cli_spoolss_enumjobs(
2163 cli, mem_ctx, needed, NULL, &hnd, level, 0,
2164 1000, &num_jobs, &ctr);
2166 if (!W_ERROR_IS_OK(result))
2169 for (i = 0; i < num_jobs; i++) {
2172 display_job_info_1(&ctr.job.job_info_1[i]);
2175 display_job_info_2(&ctr.job.job_info_2[i]);
2178 d_printf("unknown info level %d\n", level);
2185 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2190 /* enumerate data */
2192 static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
2193 TALLOC_CTX *mem_ctx, int argc,
2197 uint32 i=0, val_needed, data_needed;
2198 BOOL got_hnd = False;
2199 pstring printername;
2200 fstring servername, user;
2204 printf("Usage: %s printername\n", argv[0]);
2208 /* Open printer handle */
2210 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2211 strupper_m(servername);
2212 fstrcpy(user, cli->user_name);
2213 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2214 strupper_m(printername);
2215 pstrcat(printername, argv[1]);
2217 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2218 "", MAXIMUM_ALLOWED_ACCESS,
2219 servername, user, &hnd);
2221 if (!W_ERROR_IS_OK(result))
2226 /* Enumerate data */
2228 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2229 &val_needed, &data_needed,
2231 while (W_ERROR_IS_OK(result)) {
2232 REGISTRY_VALUE value;
2233 result = cli_spoolss_enumprinterdata(
2234 cli, mem_ctx, &hnd, i++, val_needed,
2235 data_needed, 0, 0, &value);
2236 if (W_ERROR_IS_OK(result))
2237 display_reg_value(value);
2239 if (W_ERROR_V(result) == ERRnomoreitems)
2240 result = W_ERROR(ERRsuccess);
2244 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2249 /* enumerate data for a given key */
2251 static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
2252 TALLOC_CTX *mem_ctx, int argc,
2257 BOOL got_hnd = False;
2258 pstring printername;
2259 fstring servername, user;
2260 const char *keyname = NULL;
2265 printf("Usage: %s printername <keyname>\n", argv[0]);
2271 /* Open printer handle */
2273 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2274 strupper_m(servername);
2275 fstrcpy(user, cli->user_name);
2276 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2277 strupper_m(printername);
2278 pstrcat(printername, argv[1]);
2280 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2281 "", MAXIMUM_ALLOWED_ACCESS,
2282 servername, user, &hnd);
2284 if (!W_ERROR_IS_OK(result))
2289 /* Enumerate subkeys */
2291 result = cli_spoolss_enumprinterdataex(
2292 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
2294 if (W_ERROR_V(result) == ERRmoredata)
2295 result = cli_spoolss_enumprinterdataex(
2296 cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
2298 if (!W_ERROR_IS_OK(result))
2301 for (i=0; i < ctr.num_values; i++) {
2302 display_reg_value(*(ctr.values[i]));
2305 regval_ctr_destroy(&ctr);
2309 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2314 /* enumerate subkeys */
2316 static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
2317 TALLOC_CTX *mem_ctx, int argc,
2321 uint32 needed, returned;
2322 BOOL got_hnd = False;
2323 pstring printername;
2324 fstring servername, user;
2325 const char *keyname = NULL;
2327 uint16 *keylist = NULL, *curkey;
2329 if (argc < 2 || argc > 3) {
2330 printf("Usage: %s printername [keyname]\n", argv[0]);
2339 /* Open printer handle */
2341 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2342 strupper_m(servername);
2343 fstrcpy(user, cli->user_name);
2344 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2345 strupper_m(printername);
2346 pstrcat(printername, argv[1]);
2348 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2349 "", MAXIMUM_ALLOWED_ACCESS,
2350 servername, user, &hnd);
2352 if (!W_ERROR_IS_OK(result))
2357 /* Enumerate subkeys */
2359 result = cli_spoolss_enumprinterkey(
2360 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
2362 if (W_ERROR_V(result) == ERRmoredata)
2363 result = cli_spoolss_enumprinterkey(
2364 cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
2367 if (!W_ERROR_IS_OK(result))
2371 while (*curkey != 0) {
2373 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2375 printf("%s\n", subkey);
2376 curkey += strlen(subkey) + 1;
2383 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2388 static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
2389 TALLOC_CTX *mem_ctx, int argc,
2392 fstring servername, printername;
2394 BOOL got_hnd = False;
2396 SPOOL_NOTIFY_OPTION option;
2399 printf("Usage: %s printername\n", argv[0]);
2406 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2407 strupper_m(servername);
2409 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
2411 strupper_m(printername);
2413 result = cli_spoolss_open_printer_ex(
2414 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2415 servername, cli->user_name, &hnd);
2417 if (!W_ERROR_IS_OK(result)) {
2418 printf("Error opening %s\n", argv[1]);
2424 /* Create spool options */
2426 ZERO_STRUCT(option);
2429 option.option_type_ptr = 1;
2430 option.count = option.ctr.count = 2;
2432 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2434 ZERO_STRUCT(option.ctr.type[0]);
2435 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2436 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2437 option.ctr.type[0].fields_ptr = 1;
2438 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2440 ZERO_STRUCT(option.ctr.type[1]);
2441 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2442 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2443 option.ctr.type[1].fields_ptr = 1;
2444 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2448 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2449 strupper_m(servername);
2451 result = cli_spoolss_rffpcnex(
2452 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2454 if (!W_ERROR_IS_OK(result)) {
2455 printf("Error rffpcnex %s\n", argv[1]);
2461 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2466 /* List of commands exported by this module */
2467 struct cmd_set spoolss_commands[] = {
2471 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" },
2472 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" },
2473 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" },
2474 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, "Delete a printer driver with files", "" },
2475 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" },
2476 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" },
2477 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" },
2478 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" },
2479 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" },
2480 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" },
2481 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" },
2482 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" },
2483 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""},
2484 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" },
2485 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" },
2486 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" },
2487 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" },
2488 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" },
2489 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
2490 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" },
2491 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" },
2492 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" },
2493 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" },
2494 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" },
2495 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" },
2496 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, "Set printername", "" },
2497 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" },
2498 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" },