2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, 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 ****************************************************************************/
68 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
72 DEBUG(107,("Getting architecture dependant directory\n"));
75 } while ( (archi_table[i].long_archi!=NULL ) &&
76 StrCaseCmp(long_archi, archi_table[i].long_archi) );
78 if (archi_table[i].long_archi==NULL) {
79 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
83 /* this might be client code - but shouldn't this be an fstrcpy etc? */
86 DEBUGADD(108,("index: [%d]\n", i));
87 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
88 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
90 return archi_table[i].short_archi;
93 /****************************************************************************
94 ****************************************************************************/
96 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
98 int argc, const char **argv)
102 fstring servername, user;
106 printf("Usage: %s <printername>\n", argv[0]);
111 return WERR_GENERAL_FAILURE;
113 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
114 strupper_m(servername);
115 fstrcpy(user, cli->user_name);
116 fstrcpy(printername, argv[1]);
118 /* Open the printer handle */
120 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
121 "", PRINTER_ALL_ACCESS,
122 servername, user, &hnd);
124 if (W_ERROR_IS_OK(werror)) {
125 printf("Printer %s opened successfully\n", printername);
126 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
128 if (!W_ERROR_IS_OK(werror)) {
129 printf("Error closing printer handle! (%s)\n",
130 get_dos_error_msg(werror));
138 /****************************************************************************
139 ****************************************************************************/
141 static void display_print_info_0(PRINTER_INFO_0 *i0)
144 fstring servername = "";
149 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
151 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
153 printf("\tprintername:[%s]\n", name);
154 printf("\tservername:[%s]\n", servername);
155 printf("\tcjobs:[0x%x]\n", i0->cjobs);
156 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
158 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
159 i0->day, i0->dayofweek);
160 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
161 i0->second, i0->milliseconds);
163 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
164 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
166 printf("\tmajorversion:[0x%x]\n", i0->major_version);
167 printf("\tbuildversion:[0x%x]\n", i0->build_version);
169 printf("\tunknown7:[0x%x]\n", i0->unknown7);
170 printf("\tunknown8:[0x%x]\n", i0->unknown8);
171 printf("\tunknown9:[0x%x]\n", i0->unknown9);
172 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
173 printf("\tunknown11:[0x%x]\n", i0->unknown11);
174 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
175 printf("\tunknown13:[0x%x]\n", i0->unknown13);
176 printf("\tunknown14:[0x%x]\n", i0->unknown14);
177 printf("\tunknown15:[0x%x]\n", i0->unknown15);
178 printf("\tunknown16:[0x%x]\n", i0->unknown16);
179 printf("\tchange_id:[0x%x]\n", i0->change_id);
180 printf("\tunknown18:[0x%x]\n", i0->unknown18);
181 printf("\tstatus:[0x%x]\n", i0->status);
182 printf("\tunknown20:[0x%x]\n", i0->unknown20);
183 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
184 printf("\tunknown22:[0x%x]\n", i0->unknown22);
185 printf("\tunknown23:[0x%x]\n", i0->unknown23);
186 printf("\tunknown24:[0x%x]\n", i0->unknown24);
187 printf("\tunknown25:[0x%x]\n", i0->unknown25);
188 printf("\tunknown26:[0x%x]\n", i0->unknown26);
189 printf("\tunknown27:[0x%x]\n", i0->unknown27);
190 printf("\tunknown28:[0x%x]\n", i0->unknown28);
191 printf("\tunknown29:[0x%x]\n", i0->unknown29);
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info_1(PRINTER_INFO_1 *i1)
205 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
208 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
209 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
211 printf("\tflags:[0x%x]\n", i1->flags);
212 printf("\tname:[%s]\n", name);
213 printf("\tdescription:[%s]\n", desc);
214 printf("\tcomment:[%s]\n", comm);
219 /****************************************************************************
220 ****************************************************************************/
222 static void display_print_info_2(PRINTER_INFO_2 *i2)
224 fstring servername = "";
225 fstring printername = "";
226 fstring sharename = "";
227 fstring portname = "";
228 fstring drivername = "";
229 fstring comment = "";
230 fstring location = "";
231 fstring sepfile = "";
232 fstring printprocessor = "";
233 fstring datatype = "";
234 fstring parameters = "";
236 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
237 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
238 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
239 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
240 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
241 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
242 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
243 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
244 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
245 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
246 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
248 printf("\tservername:[%s]\n", servername);
249 printf("\tprintername:[%s]\n", printername);
250 printf("\tsharename:[%s]\n", sharename);
251 printf("\tportname:[%s]\n", portname);
252 printf("\tdrivername:[%s]\n", drivername);
253 printf("\tcomment:[%s]\n", comment);
254 printf("\tlocation:[%s]\n", location);
255 printf("\tsepfile:[%s]\n", sepfile);
256 printf("\tprintprocessor:[%s]\n", printprocessor);
257 printf("\tdatatype:[%s]\n", datatype);
258 printf("\tparameters:[%s]\n", parameters);
259 printf("\tattributes:[0x%x]\n", i2->attributes);
260 printf("\tpriority:[0x%x]\n", i2->priority);
261 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
262 printf("\tstarttime:[0x%x]\n", i2->starttime);
263 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
264 printf("\tstatus:[0x%x]\n", i2->status);
265 printf("\tcjobs:[0x%x]\n", i2->cjobs);
266 printf("\taverageppm:[0x%x]\n", i2->averageppm);
269 display_sec_desc(i2->secdesc);
274 /****************************************************************************
275 ****************************************************************************/
277 static void display_print_info_3(PRINTER_INFO_3 *i3)
279 display_sec_desc(i3->secdesc);
284 /****************************************************************************
285 ****************************************************************************/
287 static void display_print_info_7(PRINTER_INFO_7 *i7)
290 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
291 printf("\tguid:[%s]\n", guid);
292 printf("\taction:[0x%x]\n", i7->action);
296 /****************************************************************************
297 ****************************************************************************/
299 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
301 int argc, const char **argv)
304 uint32 info_level = 1;
305 PRINTER_INFO_CTR ctr;
306 uint32 i = 0, num_printers;
311 printf("Usage: %s [level] [name]\n", argv[0]);
316 info_level = atoi(argv[1]);
319 fstrcpy(name, argv[2]);
321 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
327 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
328 info_level, &num_printers, &ctr);
330 if (W_ERROR_IS_OK(result)) {
333 printf ("No printers returned.\n");
337 for (i = 0; i < num_printers; i++) {
340 display_print_info_0(&ctr.printers_0[i]);
343 display_print_info_1(&ctr.printers_1[i]);
346 display_print_info_2(&ctr.printers_2[i]);
349 display_print_info_3(&ctr.printers_3[i]);
352 printf("unknown info level %d\n", info_level);
362 /****************************************************************************
363 ****************************************************************************/
365 static void display_port_info_1(PORT_INFO_1 *i1)
369 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
370 printf("\tPort Name:\t[%s]\n", buffer);
373 /****************************************************************************
374 ****************************************************************************/
376 static void display_port_info_2(PORT_INFO_2 *i2)
380 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
381 printf("\tPort Name:\t[%s]\n", buffer);
382 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
384 printf("\tMonitor Name:\t[%s]\n", buffer);
385 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
387 printf("\tDescription:\t[%s]\n", buffer);
388 printf("\tPort Type:\t" );
389 if ( i2->port_type ) {
390 int comma = 0; /* hack */
392 if ( i2->port_type & PORT_TYPE_READ ) {
396 if ( i2->port_type & PORT_TYPE_WRITE ) {
397 printf( "%sWrite", comma ? ", " : "" );
400 /* These two have slightly different interpretations
401 on 95/98/ME but I'm disregarding that for now */
402 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
403 printf( "%sRedirected", comma ? ", " : "" );
406 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
407 printf( "%sNet-Attached", comma ? ", " : "" );
411 printf( "[Unset]\n" );
413 printf("\tReserved:\t[%d]\n", i2->reserved);
417 /****************************************************************************
418 ****************************************************************************/
420 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
421 TALLOC_CTX *mem_ctx, int argc,
425 uint32 info_level = 1;
430 printf("Usage: %s [level]\n", argv[0]);
435 info_level = atoi(argv[1]);
437 /* Enumerate ports */
441 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
443 if (W_ERROR_IS_OK(result)) {
446 for (i = 0; i < returned; i++) {
447 switch (info_level) {
449 display_port_info_1(&ctr.port.info_1[i]);
452 display_port_info_2(&ctr.port.info_2[i]);
455 printf("unknown info level %d\n", info_level);
464 /****************************************************************************
465 ****************************************************************************/
467 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
469 int argc, const char **argv)
473 uint32 info_level = 2;
474 BOOL opened_hnd = False;
475 PRINTER_INFO_CTR ctr;
481 if (argc == 1 || argc > 3) {
482 printf("Usage: %s printername comment\n", argv[0]);
487 /* Open a printer handle */
489 fstrcpy(comment, argv[2]);
492 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
493 strupper_m(servername);
494 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
495 fstrcpy(user, cli->user_name);
497 /* get a printer handle */
498 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
499 PRINTER_ALL_ACCESS, servername,
502 if (!W_ERROR_IS_OK(result))
507 /* Get printer info */
508 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
510 if (!W_ERROR_IS_OK(result))
514 /* Modify the comment. */
515 init_unistr(&ctr.printers_2->comment, comment);
516 ctr.printers_2->devmode = NULL;
517 ctr.printers_2->secdesc = NULL;
519 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
520 if (W_ERROR_IS_OK(result))
521 printf("Success in setting comment.\n");
525 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
530 /****************************************************************************
531 ****************************************************************************/
533 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
535 int argc, const char **argv)
539 uint32 info_level = 2;
540 BOOL opened_hnd = False;
541 PRINTER_INFO_CTR ctr;
547 if (argc == 1 || argc > 3) {
548 printf("Usage: %s printername new_printername\n", argv[0]);
553 /* Open a printer handle */
555 fstrcpy(new_printername, argv[2]);
558 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
559 strupper_m(servername);
560 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
561 fstrcpy(user, cli->user_name);
563 /* get a printer handle */
564 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
565 PRINTER_ALL_ACCESS, servername,
568 if (!W_ERROR_IS_OK(result))
573 /* Get printer info */
574 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
576 if (!W_ERROR_IS_OK(result))
579 /* Modify the printername. */
580 init_unistr(&ctr.printers_2->printername, new_printername);
581 ctr.printers_2->devmode = NULL;
582 ctr.printers_2->secdesc = NULL;
584 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
585 if (W_ERROR_IS_OK(result))
586 printf("Success in setting printername.\n");
590 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
595 /****************************************************************************
596 ****************************************************************************/
598 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
600 int argc, const char **argv)
604 uint32 info_level = 1;
605 BOOL opened_hnd = False;
606 PRINTER_INFO_CTR ctr;
611 if (argc == 1 || argc > 3) {
612 printf("Usage: %s <printername> [level]\n", argv[0]);
616 /* Open a printer handle */
618 info_level = atoi(argv[2]);
621 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
622 strupper_m(servername);
623 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
624 fstrcpy(user, cli->user_name);
626 /* get a printer handle */
628 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
629 "", MAXIMUM_ALLOWED_ACCESS,
630 servername, user, &pol);
632 if (!W_ERROR_IS_OK(result))
637 /* Get printer info */
639 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
641 if (!W_ERROR_IS_OK(result))
644 /* Display printer info */
646 switch (info_level) {
648 display_print_info_0(ctr.printers_0);
651 display_print_info_1(ctr.printers_1);
654 display_print_info_2(ctr.printers_2);
657 display_print_info_3(ctr.printers_3);
660 display_print_info_7(ctr.printers_7);
663 printf("unknown info level %d\n", info_level);
669 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
674 /****************************************************************************
675 ****************************************************************************/
677 static void display_reg_value(REGISTRY_VALUE value)
683 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
684 *((uint32 *) value.data_p));
687 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
689 printf("%s: REG_SZ: %s\n", value.valuename, text);
692 char *hex = hex_encode(NULL, value.data_p, value.size);
694 printf("%s: REG_BINARY:", value.valuename);
696 for (i=0; i<len; i++) {
697 if (hex[i] == '\0') {
710 uint32 i, num_values;
713 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
714 value.size, &num_values,
716 d_printf("reg_pull_multi_sz failed\n");
720 for (i=0; i<num_values; i++) {
721 d_printf("%s\n", values[i]);
727 printf("%s: unknown type %d\n", value.valuename, value.type);
732 /****************************************************************************
733 ****************************************************************************/
735 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
737 int argc, const char **argv)
741 BOOL opened_hnd = False;
745 const char *valuename;
746 REGISTRY_VALUE value;
749 printf("Usage: %s <printername> <valuename>\n", argv[0]);
750 printf("<printername> of . queries print server\n");
755 /* Open a printer handle */
757 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
758 strupper_m(servername);
759 if (strncmp(argv[1], ".", sizeof(".")) == 0)
760 fstrcpy(printername, servername);
762 slprintf(printername, sizeof(servername)-1, "%s\\%s",
763 servername, argv[1]);
764 fstrcpy(user, cli->user_name);
766 /* get a printer handle */
768 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
769 "", MAXIMUM_ALLOWED_ACCESS,
770 servername, user, &pol);
772 if (!W_ERROR_IS_OK(result))
777 /* Get printer info */
779 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
781 if (!W_ERROR_IS_OK(result))
784 /* Display printer data */
786 fstrcpy(value.valuename, valuename);
787 display_reg_value(value);
792 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
797 /****************************************************************************
798 ****************************************************************************/
800 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
802 int argc, const char **argv)
806 BOOL opened_hnd = False;
810 const char *valuename, *keyname;
811 REGISTRY_VALUE value;
814 printf("Usage: %s <printername> <keyname> <valuename>\n",
816 printf("<printername> of . queries print server\n");
822 /* Open a printer handle */
824 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
825 strupper_m(servername);
826 if (strncmp(argv[1], ".", sizeof(".")) == 0)
827 fstrcpy(printername, servername);
829 slprintf(printername, sizeof(printername)-1, "%s\\%s",
830 servername, argv[1]);
831 fstrcpy(user, cli->user_name);
833 /* get a printer handle */
835 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
836 "", MAXIMUM_ALLOWED_ACCESS,
837 servername, user, &pol);
839 if (!W_ERROR_IS_OK(result))
844 /* Get printer info */
846 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
849 if (!W_ERROR_IS_OK(result))
852 /* Display printer data */
854 fstrcpy(value.valuename, valuename);
855 display_reg_value(value);
860 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
865 /****************************************************************************
866 ****************************************************************************/
868 static void display_print_driver_1(DRIVER_INFO_1 *i1)
874 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
876 printf ("Printer Driver Info 1:\n");
877 printf ("\tDriver Name: [%s]\n\n", name);
882 /****************************************************************************
883 ****************************************************************************/
885 static void display_print_driver_2(DRIVER_INFO_2 *i1)
888 fstring architecture;
895 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
896 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
897 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
898 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
899 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
901 printf ("Printer Driver Info 2:\n");
902 printf ("\tVersion: [%x]\n", i1->version);
903 printf ("\tDriver Name: [%s]\n", name);
904 printf ("\tArchitecture: [%s]\n", architecture);
905 printf ("\tDriver Path: [%s]\n", driverpath);
906 printf ("\tDatafile: [%s]\n", datafile);
907 printf ("\tConfigfile: [%s]\n\n", configfile);
912 /****************************************************************************
913 ****************************************************************************/
915 static void display_print_driver_3(DRIVER_INFO_3 *i1)
918 fstring architecture = "";
919 fstring driverpath = "";
920 fstring datafile = "";
921 fstring configfile = "";
922 fstring helpfile = "";
923 fstring dependentfiles = "";
924 fstring monitorname = "";
925 fstring defaultdatatype = "";
933 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
934 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
935 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
936 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
937 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
938 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
939 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
940 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
942 printf ("Printer Driver Info 3:\n");
943 printf ("\tVersion: [%x]\n", i1->version);
944 printf ("\tDriver Name: [%s]\n",name);
945 printf ("\tArchitecture: [%s]\n", architecture);
946 printf ("\tDriver Path: [%s]\n", driverpath);
947 printf ("\tDatafile: [%s]\n", datafile);
948 printf ("\tConfigfile: [%s]\n", configfile);
949 printf ("\tHelpfile: [%s]\n\n", helpfile);
953 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
955 length+=strlen(dependentfiles)+1;
957 if (strlen(dependentfiles) > 0)
959 printf ("\tDependentfiles: [%s]\n", dependentfiles);
969 printf ("\tMonitorname: [%s]\n", monitorname);
970 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
975 /****************************************************************************
976 ****************************************************************************/
978 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
980 int argc, const char **argv)
984 uint32 info_level = 3;
985 BOOL opened_hnd = False;
986 PRINTER_DRIVER_CTR ctr;
991 BOOL success = False;
993 if ((argc == 1) || (argc > 3))
995 printf("Usage: %s <printername> [level]\n", argv[0]);
999 /* get the arguments need to open the printer handle */
1000 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1001 strupper_m(servername);
1002 fstrcpy(user, cli->user_name);
1003 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1005 info_level = atoi(argv[2]);
1007 /* Open a printer handle */
1009 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1011 servername, user, &pol);
1013 if (!W_ERROR_IS_OK(werror)) {
1014 printf("Error opening printer handle for %s!\n", printername);
1020 /* loop through and print driver info level for each architecture */
1022 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1024 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1025 archi_table[i].long_archi, archi_table[i].version,
1028 if (!W_ERROR_IS_OK(werror))
1031 /* need at least one success */
1035 printf ("\n[%s]\n", archi_table[i].long_archi);
1037 switch (info_level) {
1039 display_print_driver_1 (ctr.info1);
1042 display_print_driver_2 (ctr.info2);
1045 display_print_driver_3 (ctr.info3);
1048 printf("unknown info level %d\n", info_level);
1056 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1064 /****************************************************************************
1065 ****************************************************************************/
1067 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1068 TALLOC_CTX *mem_ctx,
1069 int argc, const char **argv)
1071 WERROR werror = WERR_OK;
1072 uint32 info_level = 1;
1073 PRINTER_DRIVER_CTR ctr;
1078 printf("Usage: enumdrivers [level]\n");
1083 info_level = atoi(argv[1]);
1086 /* loop through and print driver info level for each architecture */
1087 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1088 /* check to see if we already asked for this architecture string */
1090 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1093 werror = rpccli_spoolss_enumprinterdrivers(
1094 cli, mem_ctx, info_level,
1095 archi_table[i].long_archi, &returned, &ctr);
1097 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1098 printf ("Server does not support environment [%s]\n",
1099 archi_table[i].long_archi);
1107 if (!W_ERROR_IS_OK(werror)) {
1108 printf ("Error getting driver for environment [%s] - %d\n",
1109 archi_table[i].long_archi, W_ERROR_V(werror));
1113 printf ("\n[%s]\n", archi_table[i].long_archi);
1118 for (j=0; j < returned; j++) {
1119 display_print_driver_1 (&ctr.info1[j]);
1123 for (j=0; j < returned; j++) {
1124 display_print_driver_2 (&ctr.info2[j]);
1128 for (j=0; j < returned; j++) {
1129 display_print_driver_3 (&ctr.info3[j]);
1133 printf("unknown info level %d\n", info_level);
1134 return WERR_UNKNOWN_LEVEL;
1141 /****************************************************************************
1142 ****************************************************************************/
1144 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1150 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1152 printf ("\tDirectory Name:[%s]\n", name);
1155 /****************************************************************************
1156 ****************************************************************************/
1158 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1159 TALLOC_CTX *mem_ctx,
1160 int argc, const char **argv)
1164 DRIVER_DIRECTORY_CTR ctr;
1167 printf("Usage: %s [environment]\n", argv[0]);
1171 /* Get the arguments need to open the printer handle */
1174 fstrcpy (env, argv[1]);
1176 fstrcpy (env, "Windows NT x86");
1178 /* Get the directory. Only use Info level 1 */
1180 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1182 if (W_ERROR_IS_OK(result))
1183 display_printdriverdir_1(ctr.info1);
1188 /****************************************************************************
1189 ****************************************************************************/
1191 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1196 for (i=0; archi_table[i].long_archi != NULL; i++)
1198 if (strcmp(arch, archi_table[i].short_archi) == 0)
1200 info->version = archi_table[i].version;
1201 init_unistr (&info->architecture, archi_table[i].long_archi);
1206 if (archi_table[i].long_archi == NULL)
1208 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1215 /**************************************************************************
1216 wrapper for strtok to get the next parameter from a delimited list.
1217 Needed to handle the empty parameter string denoted by "NULL"
1218 *************************************************************************/
1220 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1224 /* get the next token */
1225 ptr = strtok(str, delim);
1227 /* a string of 'NULL' is used to represent an empty
1228 parameter because two consecutive delimiters
1229 will not return an empty string. See man strtok(3)
1231 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1235 init_unistr(dest, ptr);
1240 /********************************************************************************
1241 fill in the members of a DRIVER_INFO_3 struct using a character
1242 string in the form of
1243 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1244 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1245 <Default Data Type>:<Comma Separated list of Files>
1246 *******************************************************************************/
1247 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1253 /* fill in the UNISTR fields */
1254 str = get_driver_3_param (args, ":", &info->name);
1255 str = get_driver_3_param (NULL, ":", &info->driverpath);
1256 str = get_driver_3_param (NULL, ":", &info->datafile);
1257 str = get_driver_3_param (NULL, ":", &info->configfile);
1258 str = get_driver_3_param (NULL, ":", &info->helpfile);
1259 str = get_driver_3_param (NULL, ":", &info->monitorname);
1260 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1262 /* <Comma Separated List of Dependent Files> */
1263 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1266 /* begin to strip out each filename */
1267 str = strtok(str, ",");
1271 /* keep a cumlative count of the str lengths */
1272 len += strlen(str)+1;
1273 str = strtok(NULL, ",");
1276 /* allocate the space; add one extra slot for a terminating NULL.
1277 Each filename is NULL terminated and the end contains a double
1279 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1281 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1284 for (i=0; i<len; i++)
1286 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1288 info->dependentfiles[len] = '\0';
1294 /****************************************************************************
1295 ****************************************************************************/
1297 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1298 TALLOC_CTX *mem_ctx,
1299 int argc, const char **argv)
1303 PRINTER_DRIVER_CTR ctr;
1304 DRIVER_INFO_3 info3;
1306 fstring driver_name;
1309 /* parse the command arguements */
1310 if (argc != 3 && argc != 4)
1312 printf ("Usage: %s <Environment> \\\n", argv[0]);
1313 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1314 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1315 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1316 printf ("\t[version]\n");
1321 /* Fill in the DRIVER_INFO_3 struct */
1323 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1325 printf ("Error Unknown architechture [%s]\n", argv[1]);
1326 return WERR_INVALID_PARAM;
1329 set_drv_info_3_env(&info3, arch);
1331 driver_args = talloc_strdup( mem_ctx, argv[2] );
1332 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1334 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1335 return WERR_INVALID_PARAM;
1338 /* if printer driver version specified, override the default version
1339 * used by the architecture. This allows installation of Windows
1340 * 2000 (version 3) printer drivers. */
1343 info3.version = atoi(argv[3]);
1348 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1350 if (W_ERROR_IS_OK(result)) {
1351 rpcstr_pull(driver_name, info3.name.buffer,
1352 sizeof(driver_name), -1, STR_TERMINATE);
1353 printf ("Printer Driver %s successfully installed.\n",
1361 /****************************************************************************
1362 ****************************************************************************/
1364 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1365 TALLOC_CTX *mem_ctx,
1366 int argc, const char **argv)
1370 PRINTER_INFO_CTR ctr;
1371 PRINTER_INFO_2 info2;
1374 /* parse the command arguements */
1377 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1381 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1382 strupper_m(servername);
1384 /* Fill in the DRIVER_INFO_2 struct */
1387 init_unistr( &info2.printername, argv[1]);
1388 init_unistr( &info2.sharename, argv[2]);
1389 init_unistr( &info2.drivername, argv[3]);
1390 init_unistr( &info2.portname, argv[4]);
1391 init_unistr( &info2.comment, "Created by rpcclient");
1392 init_unistr( &info2.printprocessor, "winprint");
1393 init_unistr( &info2.datatype, "RAW");
1394 info2.devmode = NULL;
1395 info2.secdesc = NULL;
1396 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1398 info2.defaultpriority = 0;
1399 info2.starttime = 0;
1400 info2.untiltime = 0;
1402 /* These three fields must not be used by AddPrinter()
1403 as defined in the MS Platform SDK documentation..
1407 info2.averageppm = 0;
1410 ctr.printers_2 = &info2;
1411 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1413 if (W_ERROR_IS_OK(result))
1414 printf ("Printer %s successfully installed.\n", argv[1]);
1419 /****************************************************************************
1420 ****************************************************************************/
1422 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1423 TALLOC_CTX *mem_ctx,
1424 int argc, const char **argv)
1429 BOOL opened_hnd = False;
1430 PRINTER_INFO_CTR ctr;
1431 PRINTER_INFO_2 info2;
1436 /* parse the command arguements */
1439 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1443 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1444 strupper_m(servername);
1445 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1446 fstrcpy(user, cli->user_name);
1448 /* Get a printer handle */
1450 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1452 servername, user, &pol);
1454 if (!W_ERROR_IS_OK(result))
1459 /* Get printer info */
1461 ZERO_STRUCT (info2);
1462 ctr.printers_2 = &info2;
1464 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1466 if (!W_ERROR_IS_OK(result)) {
1467 printf ("Unable to retrieve printer information!\n");
1471 /* Set the printer driver */
1473 init_unistr(&ctr.printers_2->drivername, argv[2]);
1475 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1477 if (!W_ERROR_IS_OK(result)) {
1478 printf("SetPrinter call failed!\n");
1482 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1488 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1494 /****************************************************************************
1495 ****************************************************************************/
1497 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1498 TALLOC_CTX *mem_ctx,
1499 int argc, const char **argv)
1501 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1506 const char *arch = NULL;
1508 /* parse the command arguements */
1509 if (argc < 2 || argc > 4) {
1510 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1517 vers = atoi (argv[3]);
1520 /* delete the driver for all architectures */
1521 for (i=0; archi_table[i].long_archi; i++) {
1523 if (arch && !strequal( archi_table[i].long_archi, arch))
1526 if (vers >= 0 && archi_table[i].version != vers)
1529 /* make the call to remove the driver */
1530 result = rpccli_spoolss_deleteprinterdriverex(
1531 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1533 if ( !W_ERROR_IS_OK(result) )
1535 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1536 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1537 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1542 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1543 archi_table[i].long_archi, archi_table[i].version);
1552 /****************************************************************************
1553 ****************************************************************************/
1555 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1556 TALLOC_CTX *mem_ctx,
1557 int argc, const char **argv)
1559 WERROR result = WERR_OK;
1563 /* parse the command arguements */
1565 printf ("Usage: %s <driver>\n", argv[0]);
1569 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1570 strupper_m(servername);
1572 /* delete the driver for all architectures */
1573 for (i=0; archi_table[i].long_archi; i++) {
1574 /* make the call to remove the driver */
1575 result = rpccli_spoolss_deleteprinterdriver(
1576 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1578 if ( !W_ERROR_IS_OK(result) ) {
1579 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1580 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1581 argv[1], archi_table[i].long_archi,
1585 printf ("Driver %s removed for arch [%s].\n", argv[1],
1586 archi_table[i].long_archi);
1593 /****************************************************************************
1594 ****************************************************************************/
1596 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1597 TALLOC_CTX *mem_ctx,
1598 int argc, const char **argv)
1601 char *servername = NULL, *environment = NULL;
1604 /* parse the command arguements */
1606 printf ("Usage: %s [environment]\n", argv[0]);
1610 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1612 strupper_m(servername);
1614 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1615 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1616 SAFE_FREE(servername);
1620 result = rpccli_spoolss_getprintprocessordirectory(
1621 cli, mem_ctx, servername, environment, procdir);
1623 if (W_ERROR_IS_OK(result))
1624 printf("%s\n", procdir);
1626 SAFE_FREE(servername);
1627 SAFE_FREE(environment);
1632 /****************************************************************************
1633 ****************************************************************************/
1635 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1636 int argc, const char **argv)
1640 char *servername = NULL, *printername = NULL;
1642 BOOL got_handle = False;
1644 /* Parse the command arguements */
1647 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1651 /* Get a printer handle */
1653 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1654 strupper_m(servername);
1655 asprintf(&printername, "%s\\%s", servername, argv[1]);
1657 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1659 servername, cli->user_name, &handle);
1661 if (!W_ERROR_IS_OK(werror))
1666 /* Dummy up some values for the form data */
1668 form.flags = FORM_USER;
1669 form.size_x = form.size_y = 100;
1675 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1680 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1684 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1686 SAFE_FREE(servername);
1687 SAFE_FREE(printername);
1692 /****************************************************************************
1693 ****************************************************************************/
1695 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1696 int argc, const char **argv)
1700 char *servername = NULL, *printername = NULL;
1702 BOOL got_handle = False;
1704 /* Parse the command arguements */
1707 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1711 /* Get a printer handle */
1713 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1714 strupper_m(servername);
1715 asprintf(&printername, "%s\\%s", servername, argv[1]);
1717 werror = rpccli_spoolss_open_printer_ex(
1718 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1719 servername, cli->user_name, &handle);
1721 if (!W_ERROR_IS_OK(werror))
1726 /* Dummy up some values for the form data */
1728 form.flags = FORM_PRINTER;
1729 form.size_x = form.size_y = 100;
1735 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1739 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1743 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1745 SAFE_FREE(servername);
1746 SAFE_FREE(printername);
1751 /****************************************************************************
1752 ****************************************************************************/
1754 static const char *get_form_flag(int form_flag)
1756 switch (form_flag) {
1760 return "FORM_BUILTIN";
1762 return "FORM_PRINTER";
1768 /****************************************************************************
1769 ****************************************************************************/
1771 static void display_form(FORM_1 *form)
1773 fstring form_name = "";
1775 if (form->name.buffer)
1776 rpcstr_pull(form_name, form->name.buffer,
1777 sizeof(form_name), -1, STR_TERMINATE);
1780 "\tflag: %s (%d)\n" \
1781 "\twidth: %d, length: %d\n" \
1782 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1783 form_name, get_form_flag(form->flag), form->flag,
1784 form->width, form->length,
1785 form->left, form->right,
1786 form->top, form->bottom);
1789 /****************************************************************************
1790 ****************************************************************************/
1792 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1793 int argc, const char **argv)
1797 char *servername = NULL, *printername = NULL;
1799 BOOL got_handle = False;
1801 /* Parse the command arguements */
1804 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1808 /* Get a printer handle */
1810 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1811 strupper_m(servername);
1812 asprintf(&printername, "%s\\%s", servername, argv[1]);
1814 werror = rpccli_spoolss_open_printer_ex(
1815 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1816 servername, cli->user_name, &handle);
1818 if (!W_ERROR_IS_OK(werror))
1825 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1827 if (!W_ERROR_IS_OK(werror))
1830 display_form(&form);
1834 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1836 SAFE_FREE(servername);
1837 SAFE_FREE(printername);
1842 /****************************************************************************
1843 ****************************************************************************/
1845 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1846 TALLOC_CTX *mem_ctx, int argc,
1851 char *servername = NULL, *printername = NULL;
1852 BOOL got_handle = False;
1854 /* Parse the command arguements */
1857 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1861 /* Get a printer handle */
1863 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1864 strupper_m(servername);
1865 asprintf(&printername, "%s\\%s", servername, argv[1]);
1867 werror = rpccli_spoolss_open_printer_ex(
1868 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1869 servername, cli->user_name, &handle);
1871 if (!W_ERROR_IS_OK(werror))
1876 /* Delete the form */
1878 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1882 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1884 SAFE_FREE(servername);
1885 SAFE_FREE(printername);
1890 /****************************************************************************
1891 ****************************************************************************/
1893 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1894 TALLOC_CTX *mem_ctx, int argc,
1899 char *servername = NULL, *printername = NULL;
1900 BOOL got_handle = False;
1901 uint32 num_forms, level = 1, i;
1904 /* Parse the command arguements */
1907 printf ("Usage: %s <printer>\n", argv[0]);
1911 /* Get a printer handle */
1913 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1914 strupper_m(servername);
1915 asprintf(&printername, "%s\\%s", servername, argv[1]);
1917 werror = rpccli_spoolss_open_printer_ex(
1918 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1919 servername, cli->user_name, &handle);
1921 if (!W_ERROR_IS_OK(werror))
1926 /* Enumerate forms */
1928 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1930 if (!W_ERROR_IS_OK(werror))
1933 /* Display output */
1935 for (i = 0; i < num_forms; i++) {
1937 display_form(&forms[i]);
1943 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1945 SAFE_FREE(servername);
1946 SAFE_FREE(printername);
1951 /****************************************************************************
1952 ****************************************************************************/
1954 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1955 TALLOC_CTX *mem_ctx,
1956 int argc, const char **argv)
1959 fstring servername, printername, user;
1961 BOOL opened_hnd = False;
1962 PRINTER_INFO_CTR ctr;
1963 PRINTER_INFO_0 info;
1964 REGISTRY_VALUE value;
1966 /* parse the command arguements */
1968 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1969 " <value> <data>\n",
1971 return WERR_INVALID_PARAM;
1974 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1975 strupper_m(servername);
1976 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1977 fstrcpy(user, cli->user_name);
1979 value.type = REG_NONE;
1981 if (strequal(argv[2], "string")) {
1982 value.type = REG_SZ;
1985 if (strequal(argv[2], "binary")) {
1986 value.type = REG_BINARY;
1989 if (strequal(argv[2], "dword")) {
1990 value.type = REG_DWORD;
1993 if (strequal(argv[2], "multistring")) {
1994 value.type = REG_MULTI_SZ;
1997 if (value.type == REG_NONE) {
1998 printf("Unknown data type: %s\n", argv[2]);
1999 return WERR_INVALID_PARAM;
2002 /* get a printer handle */
2003 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2004 MAXIMUM_ALLOWED_ACCESS, servername,
2006 if (!W_ERROR_IS_OK(result))
2011 ctr.printers_0 = &info;
2013 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2015 if (!W_ERROR_IS_OK(result))
2018 printf("%s\n", current_timestring(True));
2019 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2021 /* Set the printer data */
2023 fstrcpy(value.valuename, argv[3]);
2025 switch (value.type) {
2028 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2029 value.size = data.uni_str_len * 2;
2031 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2034 value.data_p = NULL;
2039 uint32 data = strtoul(argv[4], NULL, 10);
2040 value.size = sizeof(data);
2042 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2045 value.data_p = NULL;
2050 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2051 value.data_p = data.data;
2052 value.size = data.length;
2055 case REG_MULTI_SZ: {
2060 for (i=4; i<argc; i++) {
2061 if (strcmp(argv[i], "NULL") == 0) {
2064 len += strlen(argv[i])+1;
2068 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2069 if (value.data_p == NULL) {
2070 result = WERR_NOMEM;
2074 p = (char *)value.data_p;
2076 for (i=4; i<argc; i++) {
2077 size_t l = (strlen(argv[i])+1)*2;
2078 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2082 SMB_ASSERT(len == 0);
2086 printf("Unknown data type: %s\n", argv[2]);
2087 result = WERR_INVALID_PARAM;
2091 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2093 if (!W_ERROR_IS_OK(result)) {
2094 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2097 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2099 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2101 if (!W_ERROR_IS_OK(result))
2104 printf("%s\n", current_timestring(True));
2105 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2110 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2115 /****************************************************************************
2116 ****************************************************************************/
2118 static void display_job_info_1(JOB_INFO_1 *job)
2120 fstring username = "", document = "", text_status = "";
2122 rpcstr_pull(username, job->username.buffer,
2123 sizeof(username), -1, STR_TERMINATE);
2125 rpcstr_pull(document, job->document.buffer,
2126 sizeof(document), -1, STR_TERMINATE);
2128 rpcstr_pull(text_status, job->text_status.buffer,
2129 sizeof(text_status), -1, STR_TERMINATE);
2131 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2132 username, document, text_status, job->pagesprinted,
2136 /****************************************************************************
2137 ****************************************************************************/
2139 static void display_job_info_2(JOB_INFO_2 *job)
2141 fstring username = "", document = "", text_status = "";
2143 rpcstr_pull(username, job->username.buffer,
2144 sizeof(username), -1, STR_TERMINATE);
2146 rpcstr_pull(document, job->document.buffer,
2147 sizeof(document), -1, STR_TERMINATE);
2149 rpcstr_pull(text_status, job->text_status.buffer,
2150 sizeof(text_status), -1, STR_TERMINATE);
2152 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2153 username, document, text_status, job->pagesprinted,
2154 job->totalpages, job->size);
2157 /****************************************************************************
2158 ****************************************************************************/
2160 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2161 TALLOC_CTX *mem_ctx, int argc,
2165 uint32 level = 1, num_jobs, i;
2166 BOOL got_hnd = False;
2167 pstring printername;
2168 fstring servername, user;
2172 if (argc < 2 || argc > 3) {
2173 printf("Usage: %s printername [level]\n", argv[0]);
2178 level = atoi(argv[2]);
2180 /* Open printer handle */
2182 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2183 strupper_m(servername);
2184 fstrcpy(user, cli->user_name);
2185 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2186 strupper_m(printername);
2187 pstrcat(printername, argv[1]);
2189 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2190 "", MAXIMUM_ALLOWED_ACCESS,
2191 servername, user, &hnd);
2193 if (!W_ERROR_IS_OK(result))
2198 /* Enumerate ports */
2200 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2203 if (!W_ERROR_IS_OK(result))
2206 for (i = 0; i < num_jobs; i++) {
2209 display_job_info_1(&ctr.job.job_info_1[i]);
2212 display_job_info_2(&ctr.job.job_info_2[i]);
2215 d_printf("unknown info level %d\n", level);
2222 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2227 /****************************************************************************
2228 ****************************************************************************/
2230 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2231 TALLOC_CTX *mem_ctx, int argc,
2235 uint32 i=0, val_needed, data_needed;
2236 BOOL got_hnd = False;
2237 pstring printername;
2238 fstring servername, user;
2242 printf("Usage: %s printername\n", argv[0]);
2246 /* Open printer handle */
2248 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2249 strupper_m(servername);
2250 fstrcpy(user, cli->user_name);
2251 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2252 strupper_m(printername);
2253 pstrcat(printername, argv[1]);
2255 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2256 "", MAXIMUM_ALLOWED_ACCESS,
2257 servername, user, &hnd);
2259 if (!W_ERROR_IS_OK(result))
2264 /* Enumerate data */
2266 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2267 &val_needed, &data_needed,
2269 while (W_ERROR_IS_OK(result)) {
2270 REGISTRY_VALUE value;
2271 result = rpccli_spoolss_enumprinterdata(
2272 cli, mem_ctx, &hnd, i++, val_needed,
2273 data_needed, 0, 0, &value);
2274 if (W_ERROR_IS_OK(result))
2275 display_reg_value(value);
2277 if (W_ERROR_V(result) == ERRnomoreitems)
2278 result = W_ERROR(ERRsuccess);
2282 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2287 /****************************************************************************
2288 ****************************************************************************/
2290 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2291 TALLOC_CTX *mem_ctx, int argc,
2296 BOOL got_hnd = False;
2297 pstring printername;
2298 fstring servername, user;
2299 const char *keyname = NULL;
2301 REGVAL_CTR *ctr = NULL;
2304 printf("Usage: %s printername <keyname>\n", argv[0]);
2310 /* Open printer handle */
2312 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2313 strupper_m(servername);
2314 fstrcpy(user, cli->user_name);
2315 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2316 strupper_m(printername);
2317 pstrcat(printername, argv[1]);
2319 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2320 "", MAXIMUM_ALLOWED_ACCESS,
2321 servername, user, &hnd);
2323 if (!W_ERROR_IS_OK(result))
2328 /* Enumerate subkeys */
2330 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2333 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2335 if (!W_ERROR_IS_OK(result))
2338 for (i=0; i < ctr->num_values; i++) {
2339 display_reg_value(*(ctr->values[i]));
2346 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2351 /****************************************************************************
2352 ****************************************************************************/
2354 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2355 TALLOC_CTX *mem_ctx, int argc,
2359 BOOL got_hnd = False;
2360 pstring printername;
2361 fstring servername, user;
2362 const char *keyname = NULL;
2364 uint16 *keylist = NULL, *curkey;
2366 if (argc < 2 || argc > 3) {
2367 printf("Usage: %s printername [keyname]\n", argv[0]);
2376 /* Open printer handle */
2378 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2379 strupper_m(servername);
2380 fstrcpy(user, cli->user_name);
2381 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2382 strupper_m(printername);
2383 pstrcat(printername, argv[1]);
2385 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2386 "", MAXIMUM_ALLOWED_ACCESS,
2387 servername, user, &hnd);
2389 if (!W_ERROR_IS_OK(result))
2394 /* Enumerate subkeys */
2396 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2398 if (!W_ERROR_IS_OK(result))
2402 while (*curkey != 0) {
2404 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2406 printf("%s\n", subkey);
2407 curkey += strlen(subkey) + 1;
2415 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2420 /****************************************************************************
2421 ****************************************************************************/
2423 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2424 TALLOC_CTX *mem_ctx, int argc,
2427 fstring servername, printername;
2429 BOOL got_hnd = False;
2431 SPOOL_NOTIFY_OPTION option;
2434 printf("Usage: %s printername\n", argv[0]);
2441 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2442 strupper_m(servername);
2444 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2446 strupper_m(printername);
2448 result = rpccli_spoolss_open_printer_ex(
2449 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2450 servername, cli->user_name, &hnd);
2452 if (!W_ERROR_IS_OK(result)) {
2453 printf("Error opening %s\n", argv[1]);
2459 /* Create spool options */
2461 ZERO_STRUCT(option);
2464 option.option_type_ptr = 1;
2465 option.count = option.ctr.count = 2;
2467 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2468 if (option.ctr.type == NULL) {
2469 result = WERR_NOMEM;
2473 ZERO_STRUCT(option.ctr.type[0]);
2474 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2475 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2476 option.ctr.type[0].fields_ptr = 1;
2477 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2479 ZERO_STRUCT(option.ctr.type[1]);
2480 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2481 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2482 option.ctr.type[1].fields_ptr = 1;
2483 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2487 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2488 strupper_m(servername);
2490 result = rpccli_spoolss_rffpcnex(
2491 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2493 if (!W_ERROR_IS_OK(result)) {
2494 printf("Error rffpcnex %s\n", argv[1]);
2500 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2505 /****************************************************************************
2506 ****************************************************************************/
2508 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2509 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2511 PRINTER_INFO_CTR ctr1, ctr2;
2513 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2515 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2516 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2517 if ( !W_ERROR_IS_OK(werror) ) {
2518 printf("failed (%s)\n", dos_errstr(werror));
2519 talloc_destroy(mem_ctx);
2524 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2525 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2526 if ( !W_ERROR_IS_OK(werror) ) {
2527 printf("failed (%s)\n", dos_errstr(werror));
2528 talloc_destroy(mem_ctx);
2533 talloc_destroy(mem_ctx);
2538 /****************************************************************************
2539 ****************************************************************************/
2541 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2542 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2544 PRINTER_INFO_CTR ctr1, ctr2;
2546 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2547 SEC_DESC *sd1, *sd2;
2551 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2552 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2553 if ( !W_ERROR_IS_OK(werror) ) {
2554 printf("failed (%s)\n", dos_errstr(werror));
2560 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2561 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2562 if ( !W_ERROR_IS_OK(werror) ) {
2563 printf("failed (%s)\n", dos_errstr(werror));
2572 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2573 printf("NULL PRINTER_INFO_3!\n");
2578 sd1 = ctr1.printers_3->secdesc;
2579 sd2 = ctr2.printers_3->secdesc;
2581 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2582 printf("NULL secdesc!\n");
2587 if (!sec_desc_equal( sd1, sd2 ) ) {
2588 printf("Security Descriptors *not* equal!\n");
2593 printf("Security descriptors match\n");
2596 talloc_destroy(mem_ctx);
2601 /****************************************************************************
2602 ****************************************************************************/
2604 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2605 TALLOC_CTX *mem_ctx, int argc,
2608 fstring printername, servername1, servername2;
2609 pstring printername_path;
2610 struct cli_state *cli_server1 = cli->cli;
2611 struct cli_state *cli_server2 = NULL;
2612 struct rpc_pipe_client *cli2 = NULL;
2613 POLICY_HND hPrinter1, hPrinter2;
2618 printf("Usage: %s <printer> <server>\n", argv[0]);
2622 fstrcpy( printername, argv[1] );
2624 fstr_sprintf( servername1, cli->cli->desthost );
2625 fstrcpy( servername2, argv[2] );
2626 strupper_m( servername1 );
2627 strupper_m( servername2 );
2630 /* first get the connection to the remote server */
2632 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2635 cmdline_auth_info.username,
2637 cmdline_auth_info.password,
2638 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2639 cmdline_auth_info.signing_state, NULL);
2641 if ( !NT_STATUS_IS_OK(nt_status) )
2642 return WERR_GENERAL_FAILURE;
2644 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2646 printf("failed to open spoolss pipe on server %s (%s)\n",
2647 servername2, nt_errstr(nt_status));
2648 return WERR_GENERAL_FAILURE;
2651 /* now open up both printers */
2653 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2654 printf("Opening %s...", printername_path);
2655 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2656 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2657 if ( !W_ERROR_IS_OK(werror) ) {
2658 printf("failed (%s)\n", dos_errstr(werror));
2663 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2664 printf("Opening %s...", printername_path);
2665 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2666 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2667 if ( !W_ERROR_IS_OK(werror) ) {
2668 printf("failed (%s)\n", dos_errstr(werror));
2674 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2675 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2677 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2684 printf("Closing printers...");
2685 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2686 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2689 /* close the second remote connection */
2691 cli_shutdown( cli_server2 );
2696 /* List of commands exported by this module */
2697 struct cmd_set spoolss_commands[] = {
2701 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2702 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2703 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2704 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2705 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2706 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2707 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2708 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2709 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2710 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2711 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2712 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2713 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2714 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2715 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2716 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2717 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2718 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2719 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2720 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2721 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2722 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2723 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2724 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2725 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2726 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2727 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2728 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2729 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },