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 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 ****************************************************************************/
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 printf("\tflags:[0x%x]\n", i3->flags);
281 display_sec_desc(i3->secdesc);
286 /****************************************************************************
287 ****************************************************************************/
289 static void display_print_info_7(PRINTER_INFO_7 *i7)
292 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
293 printf("\tguid:[%s]\n", guid);
294 printf("\taction:[0x%x]\n", i7->action);
298 /****************************************************************************
299 ****************************************************************************/
301 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
303 int argc, const char **argv)
306 uint32 info_level = 1;
307 PRINTER_INFO_CTR ctr;
308 uint32 i = 0, num_printers;
313 printf("Usage: %s [level] [name]\n", argv[0]);
318 info_level = atoi(argv[1]);
321 fstrcpy(name, argv[2]);
323 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
329 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
330 info_level, &num_printers, &ctr);
332 if (W_ERROR_IS_OK(result)) {
335 printf ("No printers returned.\n");
339 for (i = 0; i < num_printers; i++) {
342 display_print_info_0(&ctr.printers_0[i]);
345 display_print_info_1(&ctr.printers_1[i]);
348 display_print_info_2(&ctr.printers_2[i]);
351 display_print_info_3(&ctr.printers_3[i]);
354 printf("unknown info level %d\n", info_level);
364 /****************************************************************************
365 ****************************************************************************/
367 static void display_port_info_1(PORT_INFO_1 *i1)
371 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
372 printf("\tPort Name:\t[%s]\n", buffer);
375 /****************************************************************************
376 ****************************************************************************/
378 static void display_port_info_2(PORT_INFO_2 *i2)
382 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
383 printf("\tPort Name:\t[%s]\n", buffer);
384 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
386 printf("\tMonitor Name:\t[%s]\n", buffer);
387 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
389 printf("\tDescription:\t[%s]\n", buffer);
390 printf("\tPort Type:\t" );
391 if ( i2->port_type ) {
392 int comma = 0; /* hack */
394 if ( i2->port_type & PORT_TYPE_READ ) {
398 if ( i2->port_type & PORT_TYPE_WRITE ) {
399 printf( "%sWrite", comma ? ", " : "" );
402 /* These two have slightly different interpretations
403 on 95/98/ME but I'm disregarding that for now */
404 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
405 printf( "%sRedirected", comma ? ", " : "" );
408 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
409 printf( "%sNet-Attached", comma ? ", " : "" );
413 printf( "[Unset]\n" );
415 printf("\tReserved:\t[%d]\n", i2->reserved);
419 /****************************************************************************
420 ****************************************************************************/
422 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
423 TALLOC_CTX *mem_ctx, int argc,
427 uint32 info_level = 1;
432 printf("Usage: %s [level]\n", argv[0]);
437 info_level = atoi(argv[1]);
439 /* Enumerate ports */
443 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
445 if (W_ERROR_IS_OK(result)) {
448 for (i = 0; i < returned; i++) {
449 switch (info_level) {
451 display_port_info_1(&ctr.port.info_1[i]);
454 display_port_info_2(&ctr.port.info_2[i]);
457 printf("unknown info level %d\n", info_level);
466 /****************************************************************************
467 ****************************************************************************/
469 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
471 int argc, const char **argv)
475 uint32 info_level = 2;
476 BOOL opened_hnd = False;
477 PRINTER_INFO_CTR ctr;
483 if (argc == 1 || argc > 3) {
484 printf("Usage: %s printername comment\n", argv[0]);
489 /* Open a printer handle */
491 fstrcpy(comment, argv[2]);
494 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
495 strupper_m(servername);
496 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
497 fstrcpy(user, cli->user_name);
499 /* get a printer handle */
500 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
501 PRINTER_ALL_ACCESS, servername,
504 if (!W_ERROR_IS_OK(result))
509 /* Get printer info */
510 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
512 if (!W_ERROR_IS_OK(result))
516 /* Modify the comment. */
517 init_unistr(&ctr.printers_2->comment, comment);
518 ctr.printers_2->devmode = NULL;
519 ctr.printers_2->secdesc = NULL;
521 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
522 if (W_ERROR_IS_OK(result))
523 printf("Success in setting comment.\n");
527 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
532 /****************************************************************************
533 ****************************************************************************/
535 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
537 int argc, const char **argv)
541 uint32 info_level = 2;
542 BOOL opened_hnd = False;
543 PRINTER_INFO_CTR ctr;
549 if (argc == 1 || argc > 3) {
550 printf("Usage: %s printername new_printername\n", argv[0]);
555 /* Open a printer handle */
557 fstrcpy(new_printername, argv[2]);
560 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
561 strupper_m(servername);
562 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
563 fstrcpy(user, cli->user_name);
565 /* get a printer handle */
566 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
567 PRINTER_ALL_ACCESS, servername,
570 if (!W_ERROR_IS_OK(result))
575 /* Get printer info */
576 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
578 if (!W_ERROR_IS_OK(result))
581 /* Modify the printername. */
582 init_unistr(&ctr.printers_2->printername, new_printername);
583 ctr.printers_2->devmode = NULL;
584 ctr.printers_2->secdesc = NULL;
586 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
587 if (W_ERROR_IS_OK(result))
588 printf("Success in setting printername.\n");
592 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
597 /****************************************************************************
598 ****************************************************************************/
600 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
602 int argc, const char **argv)
606 uint32 info_level = 1;
607 BOOL opened_hnd = False;
608 PRINTER_INFO_CTR ctr;
613 if (argc == 1 || argc > 3) {
614 printf("Usage: %s <printername> [level]\n", argv[0]);
618 /* Open a printer handle */
620 info_level = atoi(argv[2]);
623 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
624 strupper_m(servername);
625 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
626 fstrcpy(user, cli->user_name);
628 /* get a printer handle */
630 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
631 "", MAXIMUM_ALLOWED_ACCESS,
632 servername, user, &pol);
634 if (!W_ERROR_IS_OK(result))
639 /* Get printer info */
641 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
643 if (!W_ERROR_IS_OK(result))
646 /* Display printer info */
648 switch (info_level) {
650 display_print_info_0(ctr.printers_0);
653 display_print_info_1(ctr.printers_1);
656 display_print_info_2(ctr.printers_2);
659 display_print_info_3(ctr.printers_3);
662 display_print_info_7(ctr.printers_7);
665 printf("unknown info level %d\n", info_level);
671 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
676 /****************************************************************************
677 ****************************************************************************/
679 static void display_reg_value(REGISTRY_VALUE value)
685 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
686 *((uint32 *) value.data_p));
689 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
691 printf("%s: REG_SZ: %s\n", value.valuename, text);
694 char *hex = hex_encode(NULL, value.data_p, value.size);
696 printf("%s: REG_BINARY:", value.valuename);
698 for (i=0; i<len; i++) {
699 if (hex[i] == '\0') {
715 if (!NT_STATUS_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
719 d_printf("reg_pull_multi_sz failed\n");
723 for (i=0; i<num_values; i++) {
724 d_printf("%s\n", values[i]);
730 printf("%s: unknown type %d\n", value.valuename, value.type);
735 /****************************************************************************
736 ****************************************************************************/
738 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
740 int argc, const char **argv)
744 BOOL opened_hnd = False;
748 const char *valuename;
749 REGISTRY_VALUE value;
752 printf("Usage: %s <printername> <valuename>\n", argv[0]);
753 printf("<printername> of . queries print server\n");
758 /* Open a printer handle */
760 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
761 strupper_m(servername);
762 if (strncmp(argv[1], ".", sizeof(".")) == 0)
763 fstrcpy(printername, servername);
765 slprintf(printername, sizeof(servername)-1, "%s\\%s",
766 servername, argv[1]);
767 fstrcpy(user, cli->user_name);
769 /* get a printer handle */
771 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
772 "", MAXIMUM_ALLOWED_ACCESS,
773 servername, user, &pol);
775 if (!W_ERROR_IS_OK(result))
780 /* Get printer info */
782 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
784 if (!W_ERROR_IS_OK(result))
787 /* Display printer data */
789 fstrcpy(value.valuename, valuename);
790 display_reg_value(value);
795 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
800 /****************************************************************************
801 ****************************************************************************/
803 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
805 int argc, const char **argv)
809 BOOL opened_hnd = False;
813 const char *valuename, *keyname;
814 REGISTRY_VALUE value;
817 printf("Usage: %s <printername> <keyname> <valuename>\n",
819 printf("<printername> of . queries print server\n");
825 /* Open a printer handle */
827 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
828 strupper_m(servername);
829 if (strncmp(argv[1], ".", sizeof(".")) == 0)
830 fstrcpy(printername, servername);
832 slprintf(printername, sizeof(printername)-1, "%s\\%s",
833 servername, argv[1]);
834 fstrcpy(user, cli->user_name);
836 /* get a printer handle */
838 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
839 "", MAXIMUM_ALLOWED_ACCESS,
840 servername, user, &pol);
842 if (!W_ERROR_IS_OK(result))
847 /* Get printer info */
849 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
852 if (!W_ERROR_IS_OK(result))
855 /* Display printer data */
857 fstrcpy(value.valuename, valuename);
858 display_reg_value(value);
863 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
868 /****************************************************************************
869 ****************************************************************************/
871 static void display_print_driver_1(DRIVER_INFO_1 *i1)
877 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
879 printf ("Printer Driver Info 1:\n");
880 printf ("\tDriver Name: [%s]\n\n", name);
885 /****************************************************************************
886 ****************************************************************************/
888 static void display_print_driver_2(DRIVER_INFO_2 *i1)
891 fstring architecture;
898 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
899 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
900 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
901 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
902 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
904 printf ("Printer Driver Info 2:\n");
905 printf ("\tVersion: [%x]\n", i1->version);
906 printf ("\tDriver Name: [%s]\n", name);
907 printf ("\tArchitecture: [%s]\n", architecture);
908 printf ("\tDriver Path: [%s]\n", driverpath);
909 printf ("\tDatafile: [%s]\n", datafile);
910 printf ("\tConfigfile: [%s]\n\n", configfile);
915 /****************************************************************************
916 ****************************************************************************/
918 static void display_print_driver_3(DRIVER_INFO_3 *i1)
921 fstring architecture = "";
922 fstring driverpath = "";
923 fstring datafile = "";
924 fstring configfile = "";
925 fstring helpfile = "";
926 fstring dependentfiles = "";
927 fstring monitorname = "";
928 fstring defaultdatatype = "";
936 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
937 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
938 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
939 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
940 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
941 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
942 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
943 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
945 printf ("Printer Driver Info 3:\n");
946 printf ("\tVersion: [%x]\n", i1->version);
947 printf ("\tDriver Name: [%s]\n",name);
948 printf ("\tArchitecture: [%s]\n", architecture);
949 printf ("\tDriver Path: [%s]\n", driverpath);
950 printf ("\tDatafile: [%s]\n", datafile);
951 printf ("\tConfigfile: [%s]\n", configfile);
952 printf ("\tHelpfile: [%s]\n\n", helpfile);
956 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
958 length+=strlen(dependentfiles)+1;
960 if (strlen(dependentfiles) > 0)
962 printf ("\tDependentfiles: [%s]\n", dependentfiles);
972 printf ("\tMonitorname: [%s]\n", monitorname);
973 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
978 /****************************************************************************
979 ****************************************************************************/
981 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
983 int argc, const char **argv)
987 uint32 info_level = 3;
988 BOOL opened_hnd = False;
989 PRINTER_DRIVER_CTR ctr;
994 BOOL success = False;
996 if ((argc == 1) || (argc > 3))
998 printf("Usage: %s <printername> [level]\n", argv[0]);
1002 /* get the arguments need to open the printer handle */
1003 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1004 strupper_m(servername);
1005 fstrcpy(user, cli->user_name);
1006 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1008 info_level = atoi(argv[2]);
1010 /* Open a printer handle */
1012 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1014 servername, user, &pol);
1016 if (!W_ERROR_IS_OK(werror)) {
1017 printf("Error opening printer handle for %s!\n", printername);
1023 /* loop through and print driver info level for each architecture */
1025 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1027 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1028 archi_table[i].long_archi, archi_table[i].version,
1031 if (!W_ERROR_IS_OK(werror))
1034 /* need at least one success */
1038 printf ("\n[%s]\n", archi_table[i].long_archi);
1040 switch (info_level) {
1042 display_print_driver_1 (ctr.info1);
1045 display_print_driver_2 (ctr.info2);
1048 display_print_driver_3 (ctr.info3);
1051 printf("unknown info level %d\n", info_level);
1059 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1067 /****************************************************************************
1068 ****************************************************************************/
1070 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1071 TALLOC_CTX *mem_ctx,
1072 int argc, const char **argv)
1074 WERROR werror = WERR_OK;
1075 uint32 info_level = 1;
1076 PRINTER_DRIVER_CTR ctr;
1081 printf("Usage: enumdrivers [level]\n");
1086 info_level = atoi(argv[1]);
1089 /* loop through and print driver info level for each architecture */
1090 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1091 /* check to see if we already asked for this architecture string */
1093 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1096 werror = rpccli_spoolss_enumprinterdrivers(
1097 cli, mem_ctx, info_level,
1098 archi_table[i].long_archi, &returned, &ctr);
1100 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1101 printf ("Server does not support environment [%s]\n",
1102 archi_table[i].long_archi);
1110 if (!W_ERROR_IS_OK(werror)) {
1111 printf ("Error getting driver for environment [%s] - %d\n",
1112 archi_table[i].long_archi, W_ERROR_V(werror));
1116 printf ("\n[%s]\n", archi_table[i].long_archi);
1121 for (j=0; j < returned; j++) {
1122 display_print_driver_1 (&ctr.info1[j]);
1126 for (j=0; j < returned; j++) {
1127 display_print_driver_2 (&ctr.info2[j]);
1131 for (j=0; j < returned; j++) {
1132 display_print_driver_3 (&ctr.info3[j]);
1136 printf("unknown info level %d\n", info_level);
1137 return WERR_UNKNOWN_LEVEL;
1144 /****************************************************************************
1145 ****************************************************************************/
1147 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1153 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1155 printf ("\tDirectory Name:[%s]\n", name);
1158 /****************************************************************************
1159 ****************************************************************************/
1161 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1162 TALLOC_CTX *mem_ctx,
1163 int argc, const char **argv)
1167 DRIVER_DIRECTORY_CTR ctr;
1170 printf("Usage: %s [environment]\n", argv[0]);
1174 /* Get the arguments need to open the printer handle */
1177 fstrcpy (env, argv[1]);
1179 fstrcpy (env, "Windows NT x86");
1181 /* Get the directory. Only use Info level 1 */
1183 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1185 if (W_ERROR_IS_OK(result))
1186 display_printdriverdir_1(ctr.info1);
1191 /****************************************************************************
1192 ****************************************************************************/
1194 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1199 for (i=0; archi_table[i].long_archi != NULL; i++)
1201 if (strcmp(arch, archi_table[i].short_archi) == 0)
1203 info->version = archi_table[i].version;
1204 init_unistr (&info->architecture, archi_table[i].long_archi);
1209 if (archi_table[i].long_archi == NULL)
1211 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1218 /**************************************************************************
1219 wrapper for strtok to get the next parameter from a delimited list.
1220 Needed to handle the empty parameter string denoted by "NULL"
1221 *************************************************************************/
1223 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1227 /* get the next token */
1228 ptr = strtok(str, delim);
1230 /* a string of 'NULL' is used to represent an empty
1231 parameter because two consecutive delimiters
1232 will not return an empty string. See man strtok(3)
1234 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1238 init_unistr(dest, ptr);
1243 /********************************************************************************
1244 fill in the members of a DRIVER_INFO_3 struct using a character
1245 string in the form of
1246 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1247 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1248 <Default Data Type>:<Comma Separated list of Files>
1249 *******************************************************************************/
1250 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1256 /* fill in the UNISTR fields */
1257 str = get_driver_3_param (args, ":", &info->name);
1258 str = get_driver_3_param (NULL, ":", &info->driverpath);
1259 str = get_driver_3_param (NULL, ":", &info->datafile);
1260 str = get_driver_3_param (NULL, ":", &info->configfile);
1261 str = get_driver_3_param (NULL, ":", &info->helpfile);
1262 str = get_driver_3_param (NULL, ":", &info->monitorname);
1263 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1265 /* <Comma Separated List of Dependent Files> */
1266 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1269 /* begin to strip out each filename */
1270 str = strtok(str, ",");
1274 /* keep a cumlative count of the str lengths */
1275 len += strlen(str)+1;
1276 str = strtok(NULL, ",");
1279 /* allocate the space; add one extra slot for a terminating NULL.
1280 Each filename is NULL terminated and the end contains a double
1282 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1284 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1287 for (i=0; i<len; i++)
1289 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1291 info->dependentfiles[len] = '\0';
1297 /****************************************************************************
1298 ****************************************************************************/
1300 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1301 TALLOC_CTX *mem_ctx,
1302 int argc, const char **argv)
1306 PRINTER_DRIVER_CTR ctr;
1307 DRIVER_INFO_3 info3;
1309 fstring driver_name;
1312 /* parse the command arguements */
1313 if (argc != 3 && argc != 4)
1315 printf ("Usage: %s <Environment> \\\n", argv[0]);
1316 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1317 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1318 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1319 printf ("\t[version]\n");
1324 /* Fill in the DRIVER_INFO_3 struct */
1326 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1328 printf ("Error Unknown architechture [%s]\n", argv[1]);
1329 return WERR_INVALID_PARAM;
1332 set_drv_info_3_env(&info3, arch);
1334 driver_args = talloc_strdup( mem_ctx, argv[2] );
1335 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1337 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1338 return WERR_INVALID_PARAM;
1341 /* if printer driver version specified, override the default version
1342 * used by the architecture. This allows installation of Windows
1343 * 2000 (version 3) printer drivers. */
1346 info3.version = atoi(argv[3]);
1351 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1353 if (W_ERROR_IS_OK(result)) {
1354 rpcstr_pull(driver_name, info3.name.buffer,
1355 sizeof(driver_name), -1, STR_TERMINATE);
1356 printf ("Printer Driver %s successfully installed.\n",
1364 /****************************************************************************
1365 ****************************************************************************/
1367 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1368 TALLOC_CTX *mem_ctx,
1369 int argc, const char **argv)
1373 PRINTER_INFO_CTR ctr;
1374 PRINTER_INFO_2 info2;
1377 /* parse the command arguements */
1380 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1384 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1385 strupper_m(servername);
1387 /* Fill in the DRIVER_INFO_2 struct */
1390 init_unistr( &info2.printername, argv[1]);
1391 init_unistr( &info2.sharename, argv[2]);
1392 init_unistr( &info2.drivername, argv[3]);
1393 init_unistr( &info2.portname, argv[4]);
1394 init_unistr( &info2.comment, "Created by rpcclient");
1395 init_unistr( &info2.printprocessor, "winprint");
1396 init_unistr( &info2.datatype, "RAW");
1397 info2.devmode = NULL;
1398 info2.secdesc = NULL;
1399 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1401 info2.defaultpriority = 0;
1402 info2.starttime = 0;
1403 info2.untiltime = 0;
1405 /* These three fields must not be used by AddPrinter()
1406 as defined in the MS Platform SDK documentation..
1410 info2.averageppm = 0;
1413 ctr.printers_2 = &info2;
1414 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1416 if (W_ERROR_IS_OK(result))
1417 printf ("Printer %s successfully installed.\n", argv[1]);
1422 /****************************************************************************
1423 ****************************************************************************/
1425 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1426 TALLOC_CTX *mem_ctx,
1427 int argc, const char **argv)
1432 BOOL opened_hnd = False;
1433 PRINTER_INFO_CTR ctr;
1434 PRINTER_INFO_2 info2;
1439 /* parse the command arguements */
1442 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1446 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1447 strupper_m(servername);
1448 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1449 fstrcpy(user, cli->user_name);
1451 /* Get a printer handle */
1453 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1455 servername, user, &pol);
1457 if (!W_ERROR_IS_OK(result))
1462 /* Get printer info */
1464 ZERO_STRUCT (info2);
1465 ctr.printers_2 = &info2;
1467 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1469 if (!W_ERROR_IS_OK(result)) {
1470 printf ("Unable to retrieve printer information!\n");
1474 /* Set the printer driver */
1476 init_unistr(&ctr.printers_2->drivername, argv[2]);
1478 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1480 if (!W_ERROR_IS_OK(result)) {
1481 printf("SetPrinter call failed!\n");
1485 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1491 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1497 /****************************************************************************
1498 ****************************************************************************/
1500 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1501 TALLOC_CTX *mem_ctx,
1502 int argc, const char **argv)
1504 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1509 const char *arch = NULL;
1511 /* parse the command arguements */
1512 if (argc < 2 || argc > 4) {
1513 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1520 vers = atoi (argv[3]);
1523 /* delete the driver for all architectures */
1524 for (i=0; archi_table[i].long_archi; i++) {
1526 if (arch && !strequal( archi_table[i].long_archi, arch))
1529 if (vers >= 0 && archi_table[i].version != vers)
1532 /* make the call to remove the driver */
1533 result = rpccli_spoolss_deleteprinterdriverex(
1534 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1536 if ( !W_ERROR_IS_OK(result) )
1538 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1539 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1540 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1545 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1546 archi_table[i].long_archi, archi_table[i].version);
1555 /****************************************************************************
1556 ****************************************************************************/
1558 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1559 TALLOC_CTX *mem_ctx,
1560 int argc, const char **argv)
1562 WERROR result = WERR_OK;
1566 /* parse the command arguements */
1568 printf ("Usage: %s <driver>\n", argv[0]);
1572 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1573 strupper_m(servername);
1575 /* delete the driver for all architectures */
1576 for (i=0; archi_table[i].long_archi; i++) {
1577 /* make the call to remove the driver */
1578 result = rpccli_spoolss_deleteprinterdriver(
1579 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1581 if ( !W_ERROR_IS_OK(result) ) {
1582 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1583 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1584 argv[1], archi_table[i].long_archi,
1588 printf ("Driver %s removed for arch [%s].\n", argv[1],
1589 archi_table[i].long_archi);
1596 /****************************************************************************
1597 ****************************************************************************/
1599 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1600 TALLOC_CTX *mem_ctx,
1601 int argc, const char **argv)
1604 char *servername = NULL, *environment = NULL;
1607 /* parse the command arguements */
1609 printf ("Usage: %s [environment]\n", argv[0]);
1613 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1615 strupper_m(servername);
1617 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1618 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1619 SAFE_FREE(servername);
1623 result = rpccli_spoolss_getprintprocessordirectory(
1624 cli, mem_ctx, servername, environment, procdir);
1626 if (W_ERROR_IS_OK(result))
1627 printf("%s\n", procdir);
1629 SAFE_FREE(servername);
1630 SAFE_FREE(environment);
1635 /****************************************************************************
1636 ****************************************************************************/
1638 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1639 int argc, const char **argv)
1643 char *servername = NULL, *printername = NULL;
1645 BOOL got_handle = False;
1647 /* Parse the command arguements */
1650 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1654 /* Get a printer handle */
1656 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1657 strupper_m(servername);
1658 asprintf(&printername, "%s\\%s", servername, argv[1]);
1660 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1662 servername, cli->user_name, &handle);
1664 if (!W_ERROR_IS_OK(werror))
1669 /* Dummy up some values for the form data */
1671 form.flags = FORM_USER;
1672 form.size_x = form.size_y = 100;
1678 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1683 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1687 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1689 SAFE_FREE(servername);
1690 SAFE_FREE(printername);
1695 /****************************************************************************
1696 ****************************************************************************/
1698 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1699 int argc, const char **argv)
1703 char *servername = NULL, *printername = NULL;
1705 BOOL got_handle = False;
1707 /* Parse the command arguements */
1710 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1714 /* Get a printer handle */
1716 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1717 strupper_m(servername);
1718 asprintf(&printername, "%s\\%s", servername, argv[1]);
1720 werror = rpccli_spoolss_open_printer_ex(
1721 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1722 servername, cli->user_name, &handle);
1724 if (!W_ERROR_IS_OK(werror))
1729 /* Dummy up some values for the form data */
1731 form.flags = FORM_PRINTER;
1732 form.size_x = form.size_y = 100;
1738 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1742 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1746 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1748 SAFE_FREE(servername);
1749 SAFE_FREE(printername);
1754 /****************************************************************************
1755 ****************************************************************************/
1757 static const char *get_form_flag(int form_flag)
1759 switch (form_flag) {
1763 return "FORM_BUILTIN";
1765 return "FORM_PRINTER";
1771 /****************************************************************************
1772 ****************************************************************************/
1774 static void display_form(FORM_1 *form)
1776 fstring form_name = "";
1778 if (form->name.buffer)
1779 rpcstr_pull(form_name, form->name.buffer,
1780 sizeof(form_name), -1, STR_TERMINATE);
1783 "\tflag: %s (%d)\n" \
1784 "\twidth: %d, length: %d\n" \
1785 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1786 form_name, get_form_flag(form->flag), form->flag,
1787 form->width, form->length,
1788 form->left, form->right,
1789 form->top, form->bottom);
1792 /****************************************************************************
1793 ****************************************************************************/
1795 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1796 int argc, const char **argv)
1800 char *servername = NULL, *printername = NULL;
1802 BOOL got_handle = False;
1804 /* Parse the command arguements */
1807 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1811 /* Get a printer handle */
1813 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1814 strupper_m(servername);
1815 asprintf(&printername, "%s\\%s", servername, argv[1]);
1817 werror = rpccli_spoolss_open_printer_ex(
1818 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1819 servername, cli->user_name, &handle);
1821 if (!W_ERROR_IS_OK(werror))
1828 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1830 if (!W_ERROR_IS_OK(werror))
1833 display_form(&form);
1837 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1839 SAFE_FREE(servername);
1840 SAFE_FREE(printername);
1845 /****************************************************************************
1846 ****************************************************************************/
1848 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1849 TALLOC_CTX *mem_ctx, int argc,
1854 char *servername = NULL, *printername = NULL;
1855 BOOL got_handle = False;
1857 /* Parse the command arguements */
1860 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1864 /* Get a printer handle */
1866 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1867 strupper_m(servername);
1868 asprintf(&printername, "%s\\%s", servername, argv[1]);
1870 werror = rpccli_spoolss_open_printer_ex(
1871 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1872 servername, cli->user_name, &handle);
1874 if (!W_ERROR_IS_OK(werror))
1879 /* Delete the form */
1881 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1885 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1887 SAFE_FREE(servername);
1888 SAFE_FREE(printername);
1893 /****************************************************************************
1894 ****************************************************************************/
1896 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1897 TALLOC_CTX *mem_ctx, int argc,
1902 char *servername = NULL, *printername = NULL;
1903 BOOL got_handle = False;
1904 uint32 num_forms, level = 1, i;
1907 /* Parse the command arguements */
1910 printf ("Usage: %s <printer>\n", argv[0]);
1914 /* Get a printer handle */
1916 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1917 strupper_m(servername);
1918 asprintf(&printername, "%s\\%s", servername, argv[1]);
1920 werror = rpccli_spoolss_open_printer_ex(
1921 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1922 servername, cli->user_name, &handle);
1924 if (!W_ERROR_IS_OK(werror))
1929 /* Enumerate forms */
1931 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1933 if (!W_ERROR_IS_OK(werror))
1936 /* Display output */
1938 for (i = 0; i < num_forms; i++) {
1940 display_form(&forms[i]);
1946 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1948 SAFE_FREE(servername);
1949 SAFE_FREE(printername);
1954 /****************************************************************************
1955 ****************************************************************************/
1957 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1958 TALLOC_CTX *mem_ctx,
1959 int argc, const char **argv)
1962 fstring servername, printername, user;
1964 BOOL opened_hnd = False;
1965 PRINTER_INFO_CTR ctr;
1966 PRINTER_INFO_0 info;
1967 REGISTRY_VALUE value;
1969 /* parse the command arguements */
1971 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1972 " <value> <data>\n",
1974 return WERR_INVALID_PARAM;
1977 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1978 strupper_m(servername);
1979 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1980 fstrcpy(user, cli->user_name);
1982 value.type = REG_NONE;
1984 if (strequal(argv[2], "string")) {
1985 value.type = REG_SZ;
1988 if (strequal(argv[2], "binary")) {
1989 value.type = REG_BINARY;
1992 if (strequal(argv[2], "dword")) {
1993 value.type = REG_DWORD;
1996 if (strequal(argv[2], "multistring")) {
1997 value.type = REG_MULTI_SZ;
2000 if (value.type == REG_NONE) {
2001 printf("Unknown data type: %s\n", argv[2]);
2002 return WERR_INVALID_PARAM;
2005 /* get a printer handle */
2006 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2007 MAXIMUM_ALLOWED_ACCESS, servername,
2009 if (!W_ERROR_IS_OK(result))
2014 ctr.printers_0 = &info;
2016 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2018 if (!W_ERROR_IS_OK(result))
2021 printf("%s\n", current_timestring(True));
2022 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2024 /* Set the printer data */
2026 fstrcpy(value.valuename, argv[3]);
2028 switch (value.type) {
2031 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2032 value.size = data.uni_str_len * 2;
2033 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2037 uint32 data = strtoul(argv[4], NULL, 10);
2038 value.size = sizeof(data);
2039 value.data_p = TALLOC_MEMDUP(mem_ctx, &data, sizeof(data));
2043 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2044 value.data_p = data.data;
2045 value.size = data.length;
2048 case REG_MULTI_SZ: {
2053 for (i=4; i<argc; i++) {
2054 if (strcmp(argv[i], "NULL") == 0) {
2057 len += strlen(argv[i])+1;
2061 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2062 if (value.data_p == NULL) {
2063 result = WERR_NOMEM;
2067 p = (char *)value.data_p;
2069 for (i=4; i<argc; i++) {
2070 size_t l = (strlen(argv[i])+1)*2;
2071 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2075 SMB_ASSERT(len == 0);
2079 printf("Unknown data type: %s\n", argv[2]);
2080 result = WERR_INVALID_PARAM;
2084 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2086 if (!W_ERROR_IS_OK(result)) {
2087 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2090 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2092 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2094 if (!W_ERROR_IS_OK(result))
2097 printf("%s\n", current_timestring(True));
2098 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2103 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2108 /****************************************************************************
2109 ****************************************************************************/
2111 static void display_job_info_1(JOB_INFO_1 *job)
2113 fstring username = "", document = "", text_status = "";
2115 rpcstr_pull(username, job->username.buffer,
2116 sizeof(username), -1, STR_TERMINATE);
2118 rpcstr_pull(document, job->document.buffer,
2119 sizeof(document), -1, STR_TERMINATE);
2121 rpcstr_pull(text_status, job->text_status.buffer,
2122 sizeof(text_status), -1, STR_TERMINATE);
2124 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2125 username, document, text_status, job->pagesprinted,
2129 /****************************************************************************
2130 ****************************************************************************/
2132 static void display_job_info_2(JOB_INFO_2 *job)
2134 fstring username = "", document = "", text_status = "";
2136 rpcstr_pull(username, job->username.buffer,
2137 sizeof(username), -1, STR_TERMINATE);
2139 rpcstr_pull(document, job->document.buffer,
2140 sizeof(document), -1, STR_TERMINATE);
2142 rpcstr_pull(text_status, job->text_status.buffer,
2143 sizeof(text_status), -1, STR_TERMINATE);
2145 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2146 username, document, text_status, job->pagesprinted,
2147 job->totalpages, job->size);
2150 /****************************************************************************
2151 ****************************************************************************/
2153 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2154 TALLOC_CTX *mem_ctx, int argc,
2158 uint32 level = 1, num_jobs, i;
2159 BOOL got_hnd = False;
2160 pstring printername;
2161 fstring servername, user;
2165 if (argc < 2 || argc > 3) {
2166 printf("Usage: %s printername [level]\n", argv[0]);
2171 level = atoi(argv[2]);
2173 /* Open printer handle */
2175 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2176 strupper_m(servername);
2177 fstrcpy(user, cli->user_name);
2178 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2179 strupper_m(printername);
2180 pstrcat(printername, argv[1]);
2182 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2183 "", MAXIMUM_ALLOWED_ACCESS,
2184 servername, user, &hnd);
2186 if (!W_ERROR_IS_OK(result))
2191 /* Enumerate ports */
2193 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2196 if (!W_ERROR_IS_OK(result))
2199 for (i = 0; i < num_jobs; i++) {
2202 display_job_info_1(&ctr.job.job_info_1[i]);
2205 display_job_info_2(&ctr.job.job_info_2[i]);
2208 d_printf("unknown info level %d\n", level);
2215 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2220 /****************************************************************************
2221 ****************************************************************************/
2223 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2224 TALLOC_CTX *mem_ctx, int argc,
2228 uint32 i=0, val_needed, data_needed;
2229 BOOL got_hnd = False;
2230 pstring printername;
2231 fstring servername, user;
2235 printf("Usage: %s printername\n", argv[0]);
2239 /* Open printer handle */
2241 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2242 strupper_m(servername);
2243 fstrcpy(user, cli->user_name);
2244 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2245 strupper_m(printername);
2246 pstrcat(printername, argv[1]);
2248 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2249 "", MAXIMUM_ALLOWED_ACCESS,
2250 servername, user, &hnd);
2252 if (!W_ERROR_IS_OK(result))
2257 /* Enumerate data */
2259 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2260 &val_needed, &data_needed,
2262 while (W_ERROR_IS_OK(result)) {
2263 REGISTRY_VALUE value;
2264 result = rpccli_spoolss_enumprinterdata(
2265 cli, mem_ctx, &hnd, i++, val_needed,
2266 data_needed, 0, 0, &value);
2267 if (W_ERROR_IS_OK(result))
2268 display_reg_value(value);
2270 if (W_ERROR_V(result) == ERRnomoreitems)
2271 result = W_ERROR(ERRsuccess);
2275 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2280 /****************************************************************************
2281 ****************************************************************************/
2283 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2284 TALLOC_CTX *mem_ctx, int argc,
2289 BOOL got_hnd = False;
2290 pstring printername;
2291 fstring servername, user;
2292 const char *keyname = NULL;
2294 REGVAL_CTR *ctr = NULL;
2297 printf("Usage: %s printername <keyname>\n", argv[0]);
2303 /* Open printer handle */
2305 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2306 strupper_m(servername);
2307 fstrcpy(user, cli->user_name);
2308 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2309 strupper_m(printername);
2310 pstrcat(printername, argv[1]);
2312 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2313 "", MAXIMUM_ALLOWED_ACCESS,
2314 servername, user, &hnd);
2316 if (!W_ERROR_IS_OK(result))
2321 /* Enumerate subkeys */
2323 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2326 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2328 if (!W_ERROR_IS_OK(result))
2331 for (i=0; i < ctr->num_values; i++) {
2332 display_reg_value(*(ctr->values[i]));
2339 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2344 /****************************************************************************
2345 ****************************************************************************/
2347 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2348 TALLOC_CTX *mem_ctx, int argc,
2352 BOOL got_hnd = False;
2353 pstring printername;
2354 fstring servername, user;
2355 const char *keyname = NULL;
2357 uint16 *keylist = NULL, *curkey;
2359 if (argc < 2 || argc > 3) {
2360 printf("Usage: %s printername [keyname]\n", argv[0]);
2369 /* Open printer handle */
2371 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2372 strupper_m(servername);
2373 fstrcpy(user, cli->user_name);
2374 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2375 strupper_m(printername);
2376 pstrcat(printername, argv[1]);
2378 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2379 "", MAXIMUM_ALLOWED_ACCESS,
2380 servername, user, &hnd);
2382 if (!W_ERROR_IS_OK(result))
2387 /* Enumerate subkeys */
2389 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2391 if (!W_ERROR_IS_OK(result))
2395 while (*curkey != 0) {
2397 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2399 printf("%s\n", subkey);
2400 curkey += strlen(subkey) + 1;
2408 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2413 /****************************************************************************
2414 ****************************************************************************/
2416 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2417 TALLOC_CTX *mem_ctx, int argc,
2420 fstring servername, printername;
2422 BOOL got_hnd = False;
2424 SPOOL_NOTIFY_OPTION option;
2427 printf("Usage: %s printername\n", argv[0]);
2434 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2435 strupper_m(servername);
2437 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2439 strupper_m(printername);
2441 result = rpccli_spoolss_open_printer_ex(
2442 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2443 servername, cli->user_name, &hnd);
2445 if (!W_ERROR_IS_OK(result)) {
2446 printf("Error opening %s\n", argv[1]);
2452 /* Create spool options */
2454 ZERO_STRUCT(option);
2457 option.option_type_ptr = 1;
2458 option.count = option.ctr.count = 2;
2460 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2461 if (option.ctr.type == NULL) {
2462 result = WERR_NOMEM;
2466 ZERO_STRUCT(option.ctr.type[0]);
2467 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2468 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2469 option.ctr.type[0].fields_ptr = 1;
2470 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2472 ZERO_STRUCT(option.ctr.type[1]);
2473 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2474 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2475 option.ctr.type[1].fields_ptr = 1;
2476 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2480 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2481 strupper_m(servername);
2483 result = rpccli_spoolss_rffpcnex(
2484 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2486 if (!W_ERROR_IS_OK(result)) {
2487 printf("Error rffpcnex %s\n", argv[1]);
2493 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2498 /****************************************************************************
2499 ****************************************************************************/
2501 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2502 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2504 PRINTER_INFO_CTR ctr1, ctr2;
2506 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2508 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2509 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2510 if ( !W_ERROR_IS_OK(werror) ) {
2511 printf("failed (%s)\n", dos_errstr(werror));
2512 talloc_destroy(mem_ctx);
2517 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2518 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2519 if ( !W_ERROR_IS_OK(werror) ) {
2520 printf("failed (%s)\n", dos_errstr(werror));
2521 talloc_destroy(mem_ctx);
2526 talloc_destroy(mem_ctx);
2531 /****************************************************************************
2532 ****************************************************************************/
2534 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2535 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2537 PRINTER_INFO_CTR ctr1, ctr2;
2539 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2540 SEC_DESC *sd1, *sd2;
2544 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2545 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2546 if ( !W_ERROR_IS_OK(werror) ) {
2547 printf("failed (%s)\n", dos_errstr(werror));
2553 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2554 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2555 if ( !W_ERROR_IS_OK(werror) ) {
2556 printf("failed (%s)\n", dos_errstr(werror));
2565 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2566 printf("NULL PRINTER_INFO_3!\n");
2571 sd1 = ctr1.printers_3->secdesc;
2572 sd2 = ctr2.printers_3->secdesc;
2574 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2575 printf("NULL secdesc!\n");
2580 if ( (ctr1.printers_3->flags != ctr1.printers_3->flags ) || !sec_desc_equal( sd1, sd2 ) ) {
2581 printf("Security Descriptors *not* equal!\n");
2586 printf("Security descriptors match\n");
2589 talloc_destroy(mem_ctx);
2594 /****************************************************************************
2595 ****************************************************************************/
2597 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2598 TALLOC_CTX *mem_ctx, int argc,
2601 fstring printername, servername1, servername2;
2602 pstring printername_path;
2603 struct cli_state *cli_server1 = cli->cli;
2604 struct cli_state *cli_server2 = NULL;
2605 struct rpc_pipe_client *cli2 = NULL;
2606 POLICY_HND hPrinter1, hPrinter2;
2611 printf("Usage: %s <printer> <server>\n", argv[0]);
2615 fstrcpy( printername, argv[1] );
2617 fstr_sprintf( servername1, cli->cli->desthost );
2618 fstrcpy( servername2, argv[2] );
2619 strupper_m( servername1 );
2620 strupper_m( servername2 );
2623 /* first get the connection to the remote server */
2625 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2628 cmdline_auth_info.username,
2630 cmdline_auth_info.password,
2631 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2632 cmdline_auth_info.signing_state, NULL);
2634 if ( !NT_STATUS_IS_OK(nt_status) )
2635 return WERR_GENERAL_FAILURE;
2637 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2639 printf("failed to open spoolss pipe on server %s (%s)\n",
2640 servername2, nt_errstr(nt_status));
2641 return WERR_GENERAL_FAILURE;
2644 /* now open up both printers */
2646 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2647 printf("Opening %s...", printername_path);
2648 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2649 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2650 if ( !W_ERROR_IS_OK(werror) ) {
2651 printf("failed (%s)\n", dos_errstr(werror));
2656 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2657 printf("Opening %s...", printername_path);
2658 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2659 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2660 if ( !W_ERROR_IS_OK(werror) ) {
2661 printf("failed (%s)\n", dos_errstr(werror));
2667 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2668 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2670 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2677 printf("Closing printers...");
2678 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2679 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2682 /* close the second remote connection */
2684 cli_shutdown( cli_server2 );
2689 /* List of commands exported by this module */
2690 struct cmd_set spoolss_commands[] = {
2694 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2695 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2696 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2697 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2698 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2699 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2700 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2701 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2702 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2703 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2704 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2705 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2706 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2707 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2708 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2709 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2710 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2711 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2712 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2713 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2714 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2715 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2716 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2717 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2718 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2719 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2720 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2721 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2722 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },