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, see <http://www.gnu.org/licenses/>.
25 #include "rpcclient.h"
28 const char *long_archi;
29 const char *short_archi;
33 /* The version int is used by getdrivers. Note that
34 all architecture strings that support mutliple
35 versions must be grouped together since enumdrivers
36 uses this property to prevent issuing multiple
37 enumdriver calls for the same arch */
40 static const struct table_node archi_table[]= {
42 {"Windows 4.0", "WIN40", 0 },
43 {"Windows NT x86", "W32X86", 2 },
44 {"Windows NT x86", "W32X86", 3 },
45 {"Windows NT R4000", "W32MIPS", 2 },
46 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
47 {"Windows NT PowerPC", "W32PPC", 2 },
48 {"Windows IA64", "IA64", 3 },
49 {"Windows x64", "x64", 3 },
56 * rpcclient module for SPOOLSS rpc pipe.
58 * This generally just parses and checks command lines, and then calls
59 * a cli_spoolss function.
62 /****************************************************************************
63 function to do the mapping between the long architecture name and
65 ****************************************************************************/
67 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
71 DEBUG(107,("Getting architecture dependant directory\n"));
74 } while ( (archi_table[i].long_archi!=NULL ) &&
75 StrCaseCmp(long_archi, archi_table[i].long_archi) );
77 if (archi_table[i].long_archi==NULL) {
78 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
82 /* this might be client code - but shouldn't this be an fstrcpy etc? */
85 DEBUGADD(108,("index: [%d]\n", i));
86 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
87 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
89 return archi_table[i].short_archi;
92 /****************************************************************************
93 ****************************************************************************/
95 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
97 int argc, const char **argv)
101 fstring servername, user;
105 printf("Usage: %s <printername>\n", argv[0]);
110 return WERR_GENERAL_FAILURE;
112 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
113 strupper_m(servername);
114 fstrcpy(user, cli->user_name);
115 fstrcpy(printername, argv[1]);
117 /* Open the printer handle */
119 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
120 "", PRINTER_ALL_ACCESS,
121 servername, user, &hnd);
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", printername);
125 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
127 if (!W_ERROR_IS_OK(werror)) {
128 printf("Error closing printer handle! (%s)\n",
129 get_dos_error_msg(werror));
137 /****************************************************************************
138 ****************************************************************************/
140 static void display_print_info_0(PRINTER_INFO_0 *i0)
143 fstring servername = "";
148 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
150 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
152 printf("\tprintername:[%s]\n", name);
153 printf("\tservername:[%s]\n", servername);
154 printf("\tcjobs:[0x%x]\n", i0->cjobs);
155 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
157 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
158 i0->day, i0->dayofweek);
159 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
160 i0->second, i0->milliseconds);
162 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
163 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
165 printf("\tmajorversion:[0x%x]\n", i0->major_version);
166 printf("\tbuildversion:[0x%x]\n", i0->build_version);
168 printf("\tunknown7:[0x%x]\n", i0->unknown7);
169 printf("\tunknown8:[0x%x]\n", i0->unknown8);
170 printf("\tunknown9:[0x%x]\n", i0->unknown9);
171 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
172 printf("\tunknown11:[0x%x]\n", i0->unknown11);
173 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
174 printf("\tunknown13:[0x%x]\n", i0->unknown13);
175 printf("\tunknown14:[0x%x]\n", i0->unknown14);
176 printf("\tunknown15:[0x%x]\n", i0->unknown15);
177 printf("\tunknown16:[0x%x]\n", i0->unknown16);
178 printf("\tchange_id:[0x%x]\n", i0->change_id);
179 printf("\tunknown18:[0x%x]\n", i0->unknown18);
180 printf("\tstatus:[0x%x]\n", i0->status);
181 printf("\tunknown20:[0x%x]\n", i0->unknown20);
182 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
183 printf("\tunknown22:[0x%x]\n", i0->unknown22);
184 printf("\tunknown23:[0x%x]\n", i0->unknown23);
185 printf("\tunknown24:[0x%x]\n", i0->unknown24);
186 printf("\tunknown25:[0x%x]\n", i0->unknown25);
187 printf("\tunknown26:[0x%x]\n", i0->unknown26);
188 printf("\tunknown27:[0x%x]\n", i0->unknown27);
189 printf("\tunknown28:[0x%x]\n", i0->unknown28);
190 printf("\tunknown29:[0x%x]\n", i0->unknown29);
195 /****************************************************************************
196 ****************************************************************************/
198 static void display_print_info_1(PRINTER_INFO_1 *i1)
204 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
207 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
208 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
210 printf("\tflags:[0x%x]\n", i1->flags);
211 printf("\tname:[%s]\n", name);
212 printf("\tdescription:[%s]\n", desc);
213 printf("\tcomment:[%s]\n", comm);
218 /****************************************************************************
219 ****************************************************************************/
221 static void display_print_info_2(PRINTER_INFO_2 *i2)
223 fstring servername = "";
224 fstring printername = "";
225 fstring sharename = "";
226 fstring portname = "";
227 fstring drivername = "";
228 fstring comment = "";
229 fstring location = "";
230 fstring sepfile = "";
231 fstring printprocessor = "";
232 fstring datatype = "";
233 fstring parameters = "";
235 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
236 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
237 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
238 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
239 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
240 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
241 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
242 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
243 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
244 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
245 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
247 printf("\tservername:[%s]\n", servername);
248 printf("\tprintername:[%s]\n", printername);
249 printf("\tsharename:[%s]\n", sharename);
250 printf("\tportname:[%s]\n", portname);
251 printf("\tdrivername:[%s]\n", drivername);
252 printf("\tcomment:[%s]\n", comment);
253 printf("\tlocation:[%s]\n", location);
254 printf("\tsepfile:[%s]\n", sepfile);
255 printf("\tprintprocessor:[%s]\n", printprocessor);
256 printf("\tdatatype:[%s]\n", datatype);
257 printf("\tparameters:[%s]\n", parameters);
258 printf("\tattributes:[0x%x]\n", i2->attributes);
259 printf("\tpriority:[0x%x]\n", i2->priority);
260 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
261 printf("\tstarttime:[0x%x]\n", i2->starttime);
262 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
263 printf("\tstatus:[0x%x]\n", i2->status);
264 printf("\tcjobs:[0x%x]\n", i2->cjobs);
265 printf("\taverageppm:[0x%x]\n", i2->averageppm);
268 display_sec_desc(i2->secdesc);
273 /****************************************************************************
274 ****************************************************************************/
276 static void display_print_info_3(PRINTER_INFO_3 *i3)
278 display_sec_desc(i3->secdesc);
283 /****************************************************************************
284 ****************************************************************************/
286 static void display_print_info_7(PRINTER_INFO_7 *i7)
289 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
290 printf("\tguid:[%s]\n", guid);
291 printf("\taction:[0x%x]\n", i7->action);
295 /****************************************************************************
296 ****************************************************************************/
298 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
300 int argc, const char **argv)
303 uint32 info_level = 1;
304 PRINTER_INFO_CTR ctr;
305 uint32 i = 0, num_printers;
310 printf("Usage: %s [level] [name]\n", argv[0]);
315 info_level = atoi(argv[1]);
318 fstrcpy(name, argv[2]);
320 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
326 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
327 info_level, &num_printers, &ctr);
329 if (W_ERROR_IS_OK(result)) {
332 printf ("No printers returned.\n");
336 for (i = 0; i < num_printers; i++) {
339 display_print_info_0(&ctr.printers_0[i]);
342 display_print_info_1(&ctr.printers_1[i]);
345 display_print_info_2(&ctr.printers_2[i]);
348 display_print_info_3(&ctr.printers_3[i]);
351 printf("unknown info level %d\n", info_level);
361 /****************************************************************************
362 ****************************************************************************/
364 static void display_port_info_1(PORT_INFO_1 *i1)
368 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
369 printf("\tPort Name:\t[%s]\n", buffer);
372 /****************************************************************************
373 ****************************************************************************/
375 static void display_port_info_2(PORT_INFO_2 *i2)
379 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
380 printf("\tPort Name:\t[%s]\n", buffer);
381 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
383 printf("\tMonitor Name:\t[%s]\n", buffer);
384 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
386 printf("\tDescription:\t[%s]\n", buffer);
387 printf("\tPort Type:\t" );
388 if ( i2->port_type ) {
389 int comma = 0; /* hack */
391 if ( i2->port_type & PORT_TYPE_READ ) {
395 if ( i2->port_type & PORT_TYPE_WRITE ) {
396 printf( "%sWrite", comma ? ", " : "" );
399 /* These two have slightly different interpretations
400 on 95/98/ME but I'm disregarding that for now */
401 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
402 printf( "%sRedirected", comma ? ", " : "" );
405 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
406 printf( "%sNet-Attached", comma ? ", " : "" );
410 printf( "[Unset]\n" );
412 printf("\tReserved:\t[%d]\n", i2->reserved);
416 /****************************************************************************
417 ****************************************************************************/
419 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
420 TALLOC_CTX *mem_ctx, int argc,
424 uint32 info_level = 1;
429 printf("Usage: %s [level]\n", argv[0]);
434 info_level = atoi(argv[1]);
436 /* Enumerate ports */
440 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
442 if (W_ERROR_IS_OK(result)) {
445 for (i = 0; i < returned; i++) {
446 switch (info_level) {
448 display_port_info_1(&ctr.port.info_1[i]);
451 display_port_info_2(&ctr.port.info_2[i]);
454 printf("unknown info level %d\n", info_level);
463 /****************************************************************************
464 ****************************************************************************/
466 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
468 int argc, const char **argv)
472 uint32 info_level = 2;
473 bool opened_hnd = False;
474 PRINTER_INFO_CTR ctr;
480 if (argc == 1 || argc > 3) {
481 printf("Usage: %s printername comment\n", argv[0]);
486 /* Open a printer handle */
488 fstrcpy(comment, argv[2]);
491 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
492 strupper_m(servername);
493 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
494 fstrcpy(user, cli->user_name);
496 /* get a printer handle */
497 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
498 PRINTER_ALL_ACCESS, servername,
501 if (!W_ERROR_IS_OK(result))
506 /* Get printer info */
507 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
509 if (!W_ERROR_IS_OK(result))
513 /* Modify the comment. */
514 init_unistr(&ctr.printers_2->comment, comment);
515 ctr.printers_2->devmode = NULL;
516 ctr.printers_2->secdesc = NULL;
518 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
519 if (W_ERROR_IS_OK(result))
520 printf("Success in setting comment.\n");
524 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
529 /****************************************************************************
530 ****************************************************************************/
532 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
534 int argc, const char **argv)
538 uint32 info_level = 2;
539 bool opened_hnd = False;
540 PRINTER_INFO_CTR ctr;
546 if (argc == 1 || argc > 3) {
547 printf("Usage: %s printername new_printername\n", argv[0]);
552 /* Open a printer handle */
554 fstrcpy(new_printername, argv[2]);
557 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
558 strupper_m(servername);
559 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
560 fstrcpy(user, cli->user_name);
562 /* get a printer handle */
563 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
564 PRINTER_ALL_ACCESS, servername,
567 if (!W_ERROR_IS_OK(result))
572 /* Get printer info */
573 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
575 if (!W_ERROR_IS_OK(result))
578 /* Modify the printername. */
579 init_unistr(&ctr.printers_2->printername, new_printername);
580 ctr.printers_2->devmode = NULL;
581 ctr.printers_2->secdesc = NULL;
583 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
584 if (W_ERROR_IS_OK(result))
585 printf("Success in setting printername.\n");
589 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
594 /****************************************************************************
595 ****************************************************************************/
597 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
599 int argc, const char **argv)
603 uint32 info_level = 1;
604 bool opened_hnd = False;
605 PRINTER_INFO_CTR ctr;
610 if (argc == 1 || argc > 3) {
611 printf("Usage: %s <printername> [level]\n", argv[0]);
615 /* Open a printer handle */
617 info_level = atoi(argv[2]);
620 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
621 strupper_m(servername);
622 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
623 fstrcpy(user, cli->user_name);
625 /* get a printer handle */
627 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
628 "", MAXIMUM_ALLOWED_ACCESS,
629 servername, user, &pol);
631 if (!W_ERROR_IS_OK(result))
636 /* Get printer info */
638 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
640 if (!W_ERROR_IS_OK(result))
643 /* Display printer info */
645 switch (info_level) {
647 display_print_info_0(ctr.printers_0);
650 display_print_info_1(ctr.printers_1);
653 display_print_info_2(ctr.printers_2);
656 display_print_info_3(ctr.printers_3);
659 display_print_info_7(ctr.printers_7);
662 printf("unknown info level %d\n", info_level);
668 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
673 /****************************************************************************
674 ****************************************************************************/
676 static void display_reg_value(REGISTRY_VALUE value)
682 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
683 *((uint32 *) value.data_p));
686 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
688 printf("%s: REG_SZ: %s\n", value.valuename, text);
691 char *hex = hex_encode(NULL, value.data_p, value.size);
693 printf("%s: REG_BINARY:", value.valuename);
695 for (i=0; i<len; i++) {
696 if (hex[i] == '\0') {
709 uint32 i, num_values;
712 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
713 value.size, &num_values,
715 d_printf("reg_pull_multi_sz failed\n");
719 for (i=0; i<num_values; i++) {
720 d_printf("%s\n", values[i]);
726 printf("%s: unknown type %d\n", value.valuename, value.type);
731 /****************************************************************************
732 ****************************************************************************/
734 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
736 int argc, const char **argv)
740 bool opened_hnd = False;
744 const char *valuename;
745 REGISTRY_VALUE value;
748 printf("Usage: %s <printername> <valuename>\n", argv[0]);
749 printf("<printername> of . queries print server\n");
754 /* Open a printer handle */
756 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
757 strupper_m(servername);
758 if (strncmp(argv[1], ".", sizeof(".")) == 0)
759 fstrcpy(printername, servername);
761 slprintf(printername, sizeof(servername)-1, "%s\\%s",
762 servername, argv[1]);
763 fstrcpy(user, cli->user_name);
765 /* get a printer handle */
767 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
768 "", MAXIMUM_ALLOWED_ACCESS,
769 servername, user, &pol);
771 if (!W_ERROR_IS_OK(result))
776 /* Get printer info */
778 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
780 if (!W_ERROR_IS_OK(result))
783 /* Display printer data */
785 fstrcpy(value.valuename, valuename);
786 display_reg_value(value);
791 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
796 /****************************************************************************
797 ****************************************************************************/
799 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
801 int argc, const char **argv)
805 bool opened_hnd = False;
809 const char *valuename, *keyname;
810 REGISTRY_VALUE value;
813 printf("Usage: %s <printername> <keyname> <valuename>\n",
815 printf("<printername> of . queries print server\n");
821 /* Open a printer handle */
823 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
824 strupper_m(servername);
825 if (strncmp(argv[1], ".", sizeof(".")) == 0)
826 fstrcpy(printername, servername);
828 slprintf(printername, sizeof(printername)-1, "%s\\%s",
829 servername, argv[1]);
830 fstrcpy(user, cli->user_name);
832 /* get a printer handle */
834 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
835 "", MAXIMUM_ALLOWED_ACCESS,
836 servername, user, &pol);
838 if (!W_ERROR_IS_OK(result))
843 /* Get printer info */
845 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
848 if (!W_ERROR_IS_OK(result))
851 /* Display printer data */
853 fstrcpy(value.valuename, valuename);
854 display_reg_value(value);
859 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
864 /****************************************************************************
865 ****************************************************************************/
867 static void display_print_driver_1(DRIVER_INFO_1 *i1)
873 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
875 printf ("Printer Driver Info 1:\n");
876 printf ("\tDriver Name: [%s]\n\n", name);
881 /****************************************************************************
882 ****************************************************************************/
884 static void display_print_driver_2(DRIVER_INFO_2 *i1)
887 fstring architecture;
894 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
895 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
896 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
897 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
898 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
900 printf ("Printer Driver Info 2:\n");
901 printf ("\tVersion: [%x]\n", i1->version);
902 printf ("\tDriver Name: [%s]\n", name);
903 printf ("\tArchitecture: [%s]\n", architecture);
904 printf ("\tDriver Path: [%s]\n", driverpath);
905 printf ("\tDatafile: [%s]\n", datafile);
906 printf ("\tConfigfile: [%s]\n\n", configfile);
911 /****************************************************************************
912 ****************************************************************************/
914 static void display_print_driver_3(DRIVER_INFO_3 *i1)
917 fstring architecture = "";
918 fstring driverpath = "";
919 fstring datafile = "";
920 fstring configfile = "";
921 fstring helpfile = "";
922 fstring dependentfiles = "";
923 fstring monitorname = "";
924 fstring defaultdatatype = "";
932 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
933 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
934 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
935 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
936 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
937 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
938 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
939 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
941 printf ("Printer Driver Info 3:\n");
942 printf ("\tVersion: [%x]\n", i1->version);
943 printf ("\tDriver Name: [%s]\n",name);
944 printf ("\tArchitecture: [%s]\n", architecture);
945 printf ("\tDriver Path: [%s]\n", driverpath);
946 printf ("\tDatafile: [%s]\n", datafile);
947 printf ("\tConfigfile: [%s]\n", configfile);
948 printf ("\tHelpfile: [%s]\n\n", helpfile);
952 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
954 length+=strlen(dependentfiles)+1;
956 if (strlen(dependentfiles) > 0)
958 printf ("\tDependentfiles: [%s]\n", dependentfiles);
968 printf ("\tMonitorname: [%s]\n", monitorname);
969 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
974 /****************************************************************************
975 ****************************************************************************/
977 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
979 int argc, const char **argv)
983 uint32 info_level = 3;
984 bool opened_hnd = False;
985 PRINTER_DRIVER_CTR ctr;
990 bool success = False;
992 if ((argc == 1) || (argc > 3))
994 printf("Usage: %s <printername> [level]\n", argv[0]);
998 /* get the arguments need to open the printer handle */
999 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1000 strupper_m(servername);
1001 fstrcpy(user, cli->user_name);
1002 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1004 info_level = atoi(argv[2]);
1006 /* Open a printer handle */
1008 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1010 servername, user, &pol);
1012 if (!W_ERROR_IS_OK(werror)) {
1013 printf("Error opening printer handle for %s!\n", printername);
1019 /* loop through and print driver info level for each architecture */
1021 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1023 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1024 archi_table[i].long_archi, archi_table[i].version,
1027 if (!W_ERROR_IS_OK(werror))
1030 /* need at least one success */
1034 printf ("\n[%s]\n", archi_table[i].long_archi);
1036 switch (info_level) {
1038 display_print_driver_1 (ctr.info1);
1041 display_print_driver_2 (ctr.info2);
1044 display_print_driver_3 (ctr.info3);
1047 printf("unknown info level %d\n", info_level);
1055 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1063 /****************************************************************************
1064 ****************************************************************************/
1066 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1067 TALLOC_CTX *mem_ctx,
1068 int argc, const char **argv)
1070 WERROR werror = WERR_OK;
1071 uint32 info_level = 1;
1072 PRINTER_DRIVER_CTR ctr;
1077 printf("Usage: enumdrivers [level]\n");
1082 info_level = atoi(argv[1]);
1085 /* loop through and print driver info level for each architecture */
1086 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1087 /* check to see if we already asked for this architecture string */
1089 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1092 werror = rpccli_spoolss_enumprinterdrivers(
1093 cli, mem_ctx, info_level,
1094 archi_table[i].long_archi, &returned, &ctr);
1096 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1097 printf ("Server does not support environment [%s]\n",
1098 archi_table[i].long_archi);
1106 if (!W_ERROR_IS_OK(werror)) {
1107 printf ("Error getting driver for environment [%s] - %d\n",
1108 archi_table[i].long_archi, W_ERROR_V(werror));
1112 printf ("\n[%s]\n", archi_table[i].long_archi);
1117 for (j=0; j < returned; j++) {
1118 display_print_driver_1 (&ctr.info1[j]);
1122 for (j=0; j < returned; j++) {
1123 display_print_driver_2 (&ctr.info2[j]);
1127 for (j=0; j < returned; j++) {
1128 display_print_driver_3 (&ctr.info3[j]);
1132 printf("unknown info level %d\n", info_level);
1133 return WERR_UNKNOWN_LEVEL;
1140 /****************************************************************************
1141 ****************************************************************************/
1143 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1149 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1151 printf ("\tDirectory Name:[%s]\n", name);
1154 /****************************************************************************
1155 ****************************************************************************/
1157 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1158 TALLOC_CTX *mem_ctx,
1159 int argc, const char **argv)
1163 DRIVER_DIRECTORY_CTR ctr;
1166 printf("Usage: %s [environment]\n", argv[0]);
1170 /* Get the arguments need to open the printer handle */
1173 fstrcpy (env, argv[1]);
1175 fstrcpy (env, "Windows NT x86");
1177 /* Get the directory. Only use Info level 1 */
1179 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1181 if (W_ERROR_IS_OK(result))
1182 display_printdriverdir_1(ctr.info1);
1187 /****************************************************************************
1188 ****************************************************************************/
1190 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1195 for (i=0; archi_table[i].long_archi != NULL; i++)
1197 if (strcmp(arch, archi_table[i].short_archi) == 0)
1199 info->version = archi_table[i].version;
1200 init_unistr (&info->architecture, archi_table[i].long_archi);
1205 if (archi_table[i].long_archi == NULL)
1207 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1214 /**************************************************************************
1215 wrapper for strtok to get the next parameter from a delimited list.
1216 Needed to handle the empty parameter string denoted by "NULL"
1217 *************************************************************************/
1219 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
1223 /* get the next token */
1224 ptr = strtok(str, delim);
1226 /* a string of 'NULL' is used to represent an empty
1227 parameter because two consecutive delimiters
1228 will not return an empty string. See man strtok(3)
1230 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1234 init_unistr(dest, ptr);
1239 /********************************************************************************
1240 fill in the members of a DRIVER_INFO_3 struct using a character
1241 string in the form of
1242 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1243 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1244 <Default Data Type>:<Comma Separated list of Files>
1245 *******************************************************************************/
1246 static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1252 /* fill in the UNISTR fields */
1253 str = get_driver_3_param (args, ":", &info->name);
1254 str = get_driver_3_param (NULL, ":", &info->driverpath);
1255 str = get_driver_3_param (NULL, ":", &info->datafile);
1256 str = get_driver_3_param (NULL, ":", &info->configfile);
1257 str = get_driver_3_param (NULL, ":", &info->helpfile);
1258 str = get_driver_3_param (NULL, ":", &info->monitorname);
1259 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1261 /* <Comma Separated List of Dependent Files> */
1262 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1265 /* begin to strip out each filename */
1266 str = strtok(str, ",");
1270 /* keep a cumlative count of the str lengths */
1271 len += strlen(str)+1;
1272 str = strtok(NULL, ",");
1275 /* allocate the space; add one extra slot for a terminating NULL.
1276 Each filename is NULL terminated and the end contains a double
1278 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1280 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1283 for (i=0; i<len; i++)
1285 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1287 info->dependentfiles[len] = '\0';
1293 /****************************************************************************
1294 ****************************************************************************/
1296 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1297 TALLOC_CTX *mem_ctx,
1298 int argc, const char **argv)
1302 PRINTER_DRIVER_CTR ctr;
1303 DRIVER_INFO_3 info3;
1305 fstring driver_name;
1308 /* parse the command arguements */
1309 if (argc != 3 && argc != 4)
1311 printf ("Usage: %s <Environment> \\\n", argv[0]);
1312 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1313 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1314 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1315 printf ("\t[version]\n");
1320 /* Fill in the DRIVER_INFO_3 struct */
1322 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1324 printf ("Error Unknown architechture [%s]\n", argv[1]);
1325 return WERR_INVALID_PARAM;
1328 set_drv_info_3_env(&info3, arch);
1330 driver_args = talloc_strdup( mem_ctx, argv[2] );
1331 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1333 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1334 return WERR_INVALID_PARAM;
1337 /* if printer driver version specified, override the default version
1338 * used by the architecture. This allows installation of Windows
1339 * 2000 (version 3) printer drivers. */
1342 info3.version = atoi(argv[3]);
1347 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1349 if (W_ERROR_IS_OK(result)) {
1350 rpcstr_pull(driver_name, info3.name.buffer,
1351 sizeof(driver_name), -1, STR_TERMINATE);
1352 printf ("Printer Driver %s successfully installed.\n",
1360 /****************************************************************************
1361 ****************************************************************************/
1363 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1364 TALLOC_CTX *mem_ctx,
1365 int argc, const char **argv)
1369 PRINTER_INFO_CTR ctr;
1370 PRINTER_INFO_2 info2;
1373 /* parse the command arguements */
1376 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1380 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1381 strupper_m(servername);
1383 /* Fill in the DRIVER_INFO_2 struct */
1386 init_unistr( &info2.printername, argv[1]);
1387 init_unistr( &info2.sharename, argv[2]);
1388 init_unistr( &info2.drivername, argv[3]);
1389 init_unistr( &info2.portname, argv[4]);
1390 init_unistr( &info2.comment, "Created by rpcclient");
1391 init_unistr( &info2.printprocessor, "winprint");
1392 init_unistr( &info2.datatype, "RAW");
1393 info2.devmode = NULL;
1394 info2.secdesc = NULL;
1395 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1397 info2.defaultpriority = 0;
1398 info2.starttime = 0;
1399 info2.untiltime = 0;
1401 /* These three fields must not be used by AddPrinter()
1402 as defined in the MS Platform SDK documentation..
1406 info2.averageppm = 0;
1409 ctr.printers_2 = &info2;
1410 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1412 if (W_ERROR_IS_OK(result))
1413 printf ("Printer %s successfully installed.\n", argv[1]);
1418 /****************************************************************************
1419 ****************************************************************************/
1421 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1422 TALLOC_CTX *mem_ctx,
1423 int argc, const char **argv)
1428 bool opened_hnd = False;
1429 PRINTER_INFO_CTR ctr;
1430 PRINTER_INFO_2 info2;
1435 /* parse the command arguements */
1438 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1442 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1443 strupper_m(servername);
1444 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1445 fstrcpy(user, cli->user_name);
1447 /* Get a printer handle */
1449 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1451 servername, user, &pol);
1453 if (!W_ERROR_IS_OK(result))
1458 /* Get printer info */
1460 ZERO_STRUCT (info2);
1461 ctr.printers_2 = &info2;
1463 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1465 if (!W_ERROR_IS_OK(result)) {
1466 printf ("Unable to retrieve printer information!\n");
1470 /* Set the printer driver */
1472 init_unistr(&ctr.printers_2->drivername, argv[2]);
1474 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1476 if (!W_ERROR_IS_OK(result)) {
1477 printf("SetPrinter call failed!\n");
1481 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1487 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1493 /****************************************************************************
1494 ****************************************************************************/
1496 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1497 TALLOC_CTX *mem_ctx,
1498 int argc, const char **argv)
1500 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1505 const char *arch = NULL;
1507 /* parse the command arguements */
1508 if (argc < 2 || argc > 4) {
1509 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1516 vers = atoi (argv[3]);
1519 /* delete the driver for all architectures */
1520 for (i=0; archi_table[i].long_archi; i++) {
1522 if (arch && !strequal( archi_table[i].long_archi, arch))
1525 if (vers >= 0 && archi_table[i].version != vers)
1528 /* make the call to remove the driver */
1529 result = rpccli_spoolss_deleteprinterdriverex(
1530 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1532 if ( !W_ERROR_IS_OK(result) )
1534 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1535 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1536 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1541 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1542 archi_table[i].long_archi, archi_table[i].version);
1551 /****************************************************************************
1552 ****************************************************************************/
1554 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1555 TALLOC_CTX *mem_ctx,
1556 int argc, const char **argv)
1558 WERROR result = WERR_OK;
1562 /* parse the command arguements */
1564 printf ("Usage: %s <driver>\n", argv[0]);
1568 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1569 strupper_m(servername);
1571 /* delete the driver for all architectures */
1572 for (i=0; archi_table[i].long_archi; i++) {
1573 /* make the call to remove the driver */
1574 result = rpccli_spoolss_deleteprinterdriver(
1575 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1577 if ( !W_ERROR_IS_OK(result) ) {
1578 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1579 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1580 argv[1], archi_table[i].long_archi,
1584 printf ("Driver %s removed for arch [%s].\n", argv[1],
1585 archi_table[i].long_archi);
1592 /****************************************************************************
1593 ****************************************************************************/
1595 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1596 TALLOC_CTX *mem_ctx,
1597 int argc, const char **argv)
1600 char *servername = NULL, *environment = NULL;
1603 /* parse the command arguements */
1605 printf ("Usage: %s [environment]\n", argv[0]);
1609 if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
1611 strupper_m(servername);
1613 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1614 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1615 SAFE_FREE(servername);
1619 result = rpccli_spoolss_getprintprocessordirectory(
1620 cli, mem_ctx, servername, environment, procdir);
1622 if (W_ERROR_IS_OK(result))
1623 printf("%s\n", procdir);
1625 SAFE_FREE(servername);
1626 SAFE_FREE(environment);
1631 /****************************************************************************
1632 ****************************************************************************/
1634 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1635 int argc, const char **argv)
1639 char *servername = NULL, *printername = NULL;
1641 bool got_handle = False;
1643 /* Parse the command arguements */
1646 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1650 /* Get a printer handle */
1652 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1653 strupper_m(servername);
1654 asprintf(&printername, "%s\\%s", servername, argv[1]);
1656 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1658 servername, cli->user_name, &handle);
1660 if (!W_ERROR_IS_OK(werror))
1665 /* Dummy up some values for the form data */
1667 form.flags = FORM_USER;
1668 form.size_x = form.size_y = 100;
1674 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1679 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1683 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1685 SAFE_FREE(servername);
1686 SAFE_FREE(printername);
1691 /****************************************************************************
1692 ****************************************************************************/
1694 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1695 int argc, const char **argv)
1699 char *servername = NULL, *printername = NULL;
1701 bool got_handle = False;
1703 /* Parse the command arguements */
1706 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1710 /* Get a printer handle */
1712 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1713 strupper_m(servername);
1714 asprintf(&printername, "%s\\%s", servername, argv[1]);
1716 werror = rpccli_spoolss_open_printer_ex(
1717 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1718 servername, cli->user_name, &handle);
1720 if (!W_ERROR_IS_OK(werror))
1725 /* Dummy up some values for the form data */
1727 form.flags = FORM_PRINTER;
1728 form.size_x = form.size_y = 100;
1734 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1738 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1742 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1744 SAFE_FREE(servername);
1745 SAFE_FREE(printername);
1750 /****************************************************************************
1751 ****************************************************************************/
1753 static const char *get_form_flag(int form_flag)
1755 switch (form_flag) {
1759 return "FORM_BUILTIN";
1761 return "FORM_PRINTER";
1767 /****************************************************************************
1768 ****************************************************************************/
1770 static void display_form(FORM_1 *form)
1772 fstring form_name = "";
1774 if (form->name.buffer)
1775 rpcstr_pull(form_name, form->name.buffer,
1776 sizeof(form_name), -1, STR_TERMINATE);
1779 "\tflag: %s (%d)\n" \
1780 "\twidth: %d, length: %d\n" \
1781 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1782 form_name, get_form_flag(form->flag), form->flag,
1783 form->width, form->length,
1784 form->left, form->right,
1785 form->top, form->bottom);
1788 /****************************************************************************
1789 ****************************************************************************/
1791 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1792 int argc, const char **argv)
1796 char *servername = NULL, *printername = NULL;
1798 bool got_handle = False;
1800 /* Parse the command arguements */
1803 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1807 /* Get a printer handle */
1809 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1810 strupper_m(servername);
1811 asprintf(&printername, "%s\\%s", servername, argv[1]);
1813 werror = rpccli_spoolss_open_printer_ex(
1814 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1815 servername, cli->user_name, &handle);
1817 if (!W_ERROR_IS_OK(werror))
1824 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1826 if (!W_ERROR_IS_OK(werror))
1829 display_form(&form);
1833 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1835 SAFE_FREE(servername);
1836 SAFE_FREE(printername);
1841 /****************************************************************************
1842 ****************************************************************************/
1844 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1845 TALLOC_CTX *mem_ctx, int argc,
1850 char *servername = NULL, *printername = NULL;
1851 bool got_handle = False;
1853 /* Parse the command arguements */
1856 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1860 /* Get a printer handle */
1862 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1863 strupper_m(servername);
1864 asprintf(&printername, "%s\\%s", servername, argv[1]);
1866 werror = rpccli_spoolss_open_printer_ex(
1867 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1868 servername, cli->user_name, &handle);
1870 if (!W_ERROR_IS_OK(werror))
1875 /* Delete the form */
1877 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1881 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1883 SAFE_FREE(servername);
1884 SAFE_FREE(printername);
1889 /****************************************************************************
1890 ****************************************************************************/
1892 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1893 TALLOC_CTX *mem_ctx, int argc,
1898 char *servername = NULL, *printername = NULL;
1899 bool got_handle = False;
1900 uint32 num_forms, level = 1, i;
1903 /* Parse the command arguements */
1906 printf ("Usage: %s <printer>\n", argv[0]);
1910 /* Get a printer handle */
1912 asprintf(&servername, "\\\\%s", cli->cli->desthost);
1913 strupper_m(servername);
1914 asprintf(&printername, "%s\\%s", servername, argv[1]);
1916 werror = rpccli_spoolss_open_printer_ex(
1917 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1918 servername, cli->user_name, &handle);
1920 if (!W_ERROR_IS_OK(werror))
1925 /* Enumerate forms */
1927 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1929 if (!W_ERROR_IS_OK(werror))
1932 /* Display output */
1934 for (i = 0; i < num_forms; i++) {
1936 display_form(&forms[i]);
1942 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1944 SAFE_FREE(servername);
1945 SAFE_FREE(printername);
1950 /****************************************************************************
1951 ****************************************************************************/
1953 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1954 TALLOC_CTX *mem_ctx,
1955 int argc, const char **argv)
1958 fstring servername, printername, user;
1960 bool opened_hnd = False;
1961 PRINTER_INFO_CTR ctr;
1962 PRINTER_INFO_0 info;
1963 REGISTRY_VALUE value;
1965 /* parse the command arguements */
1967 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
1968 " <value> <data>\n",
1970 return WERR_INVALID_PARAM;
1973 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
1974 strupper_m(servername);
1975 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1976 fstrcpy(user, cli->user_name);
1978 value.type = REG_NONE;
1980 if (strequal(argv[2], "string")) {
1981 value.type = REG_SZ;
1984 if (strequal(argv[2], "binary")) {
1985 value.type = REG_BINARY;
1988 if (strequal(argv[2], "dword")) {
1989 value.type = REG_DWORD;
1992 if (strequal(argv[2], "multistring")) {
1993 value.type = REG_MULTI_SZ;
1996 if (value.type == REG_NONE) {
1997 printf("Unknown data type: %s\n", argv[2]);
1998 return WERR_INVALID_PARAM;
2001 /* get a printer handle */
2002 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2003 MAXIMUM_ALLOWED_ACCESS, servername,
2005 if (!W_ERROR_IS_OK(result))
2010 ctr.printers_0 = &info;
2012 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2014 if (!W_ERROR_IS_OK(result))
2017 printf("%s\n", current_timestring(True));
2018 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2020 /* Set the printer data */
2022 fstrcpy(value.valuename, argv[3]);
2024 switch (value.type) {
2027 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2028 value.size = data.uni_str_len * 2;
2030 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2033 value.data_p = NULL;
2038 uint32 data = strtoul(argv[4], NULL, 10);
2039 value.size = sizeof(data);
2041 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2044 value.data_p = NULL;
2049 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2050 value.data_p = data.data;
2051 value.size = data.length;
2054 case REG_MULTI_SZ: {
2059 for (i=4; i<argc; i++) {
2060 if (strcmp(argv[i], "NULL") == 0) {
2063 len += strlen(argv[i])+1;
2067 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2068 if (value.data_p == NULL) {
2069 result = WERR_NOMEM;
2073 p = (char *)value.data_p;
2075 for (i=4; i<argc; i++) {
2076 size_t l = (strlen(argv[i])+1)*2;
2077 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2081 SMB_ASSERT(len == 0);
2085 printf("Unknown data type: %s\n", argv[2]);
2086 result = WERR_INVALID_PARAM;
2090 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2092 if (!W_ERROR_IS_OK(result)) {
2093 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2096 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2098 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2100 if (!W_ERROR_IS_OK(result))
2103 printf("%s\n", current_timestring(True));
2104 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2109 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2114 /****************************************************************************
2115 ****************************************************************************/
2117 static void display_job_info_1(JOB_INFO_1 *job)
2119 fstring username = "", document = "", text_status = "";
2121 rpcstr_pull(username, job->username.buffer,
2122 sizeof(username), -1, STR_TERMINATE);
2124 rpcstr_pull(document, job->document.buffer,
2125 sizeof(document), -1, STR_TERMINATE);
2127 rpcstr_pull(text_status, job->text_status.buffer,
2128 sizeof(text_status), -1, STR_TERMINATE);
2130 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2131 username, document, text_status, job->pagesprinted,
2135 /****************************************************************************
2136 ****************************************************************************/
2138 static void display_job_info_2(JOB_INFO_2 *job)
2140 fstring username = "", document = "", text_status = "";
2142 rpcstr_pull(username, job->username.buffer,
2143 sizeof(username), -1, STR_TERMINATE);
2145 rpcstr_pull(document, job->document.buffer,
2146 sizeof(document), -1, STR_TERMINATE);
2148 rpcstr_pull(text_status, job->text_status.buffer,
2149 sizeof(text_status), -1, STR_TERMINATE);
2151 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2152 username, document, text_status, job->pagesprinted,
2153 job->totalpages, job->size);
2156 /****************************************************************************
2157 ****************************************************************************/
2159 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2160 TALLOC_CTX *mem_ctx, int argc,
2164 uint32 level = 1, num_jobs, i;
2165 bool got_hnd = False;
2166 pstring printername;
2167 fstring servername, user;
2171 if (argc < 2 || argc > 3) {
2172 printf("Usage: %s printername [level]\n", argv[0]);
2177 level = atoi(argv[2]);
2179 /* Open printer handle */
2181 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2182 strupper_m(servername);
2183 fstrcpy(user, cli->user_name);
2184 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
2185 strupper_m(printername);
2186 pstrcat(printername, argv[1]);
2188 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2189 "", MAXIMUM_ALLOWED_ACCESS,
2190 servername, user, &hnd);
2192 if (!W_ERROR_IS_OK(result))
2197 /* Enumerate ports */
2199 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2202 if (!W_ERROR_IS_OK(result))
2205 for (i = 0; i < num_jobs; i++) {
2208 display_job_info_1(&ctr.job.job_info_1[i]);
2211 display_job_info_2(&ctr.job.job_info_2[i]);
2214 d_printf("unknown info level %d\n", level);
2221 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2226 /****************************************************************************
2227 ****************************************************************************/
2229 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2230 TALLOC_CTX *mem_ctx, int argc,
2234 uint32 i=0, val_needed, data_needed;
2235 bool got_hnd = False;
2236 pstring printername;
2237 fstring servername, user;
2241 printf("Usage: %s printername\n", argv[0]);
2245 /* Open printer handle */
2247 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2248 strupper_m(servername);
2249 fstrcpy(user, cli->user_name);
2250 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2251 strupper_m(printername);
2252 pstrcat(printername, argv[1]);
2254 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2255 "", MAXIMUM_ALLOWED_ACCESS,
2256 servername, user, &hnd);
2258 if (!W_ERROR_IS_OK(result))
2263 /* Enumerate data */
2265 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2266 &val_needed, &data_needed,
2268 while (W_ERROR_IS_OK(result)) {
2269 REGISTRY_VALUE value;
2270 result = rpccli_spoolss_enumprinterdata(
2271 cli, mem_ctx, &hnd, i++, val_needed,
2272 data_needed, 0, 0, &value);
2273 if (W_ERROR_IS_OK(result))
2274 display_reg_value(value);
2276 if (W_ERROR_V(result) == ERRnomoreitems)
2277 result = W_ERROR(ERRsuccess);
2281 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2286 /****************************************************************************
2287 ****************************************************************************/
2289 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2290 TALLOC_CTX *mem_ctx, int argc,
2295 bool got_hnd = False;
2296 pstring printername;
2297 fstring servername, user;
2298 const char *keyname = NULL;
2300 REGVAL_CTR *ctr = NULL;
2303 printf("Usage: %s printername <keyname>\n", argv[0]);
2309 /* Open printer handle */
2311 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2312 strupper_m(servername);
2313 fstrcpy(user, cli->user_name);
2314 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2315 strupper_m(printername);
2316 pstrcat(printername, argv[1]);
2318 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2319 "", MAXIMUM_ALLOWED_ACCESS,
2320 servername, user, &hnd);
2322 if (!W_ERROR_IS_OK(result))
2327 /* Enumerate subkeys */
2329 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2332 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2334 if (!W_ERROR_IS_OK(result))
2337 for (i=0; i < ctr->num_values; i++) {
2338 display_reg_value(*(ctr->values[i]));
2345 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2350 /****************************************************************************
2351 ****************************************************************************/
2353 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2354 TALLOC_CTX *mem_ctx, int argc,
2358 bool got_hnd = False;
2359 pstring printername;
2360 fstring servername, user;
2361 const char *keyname = NULL;
2363 uint16 *keylist = NULL, *curkey;
2365 if (argc < 2 || argc > 3) {
2366 printf("Usage: %s printername [keyname]\n", argv[0]);
2375 /* Open printer handle */
2377 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
2378 strupper_m(servername);
2379 fstrcpy(user, cli->user_name);
2380 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
2381 strupper_m(printername);
2382 pstrcat(printername, argv[1]);
2384 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2385 "", MAXIMUM_ALLOWED_ACCESS,
2386 servername, user, &hnd);
2388 if (!W_ERROR_IS_OK(result))
2393 /* Enumerate subkeys */
2395 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2397 if (!W_ERROR_IS_OK(result))
2401 while (*curkey != 0) {
2403 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2405 printf("%s\n", subkey);
2406 curkey += strlen(subkey) + 1;
2414 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2419 /****************************************************************************
2420 ****************************************************************************/
2422 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2423 TALLOC_CTX *mem_ctx, int argc,
2426 fstring servername, printername;
2428 bool got_hnd = False;
2430 SPOOL_NOTIFY_OPTION option;
2433 printf("Usage: %s printername\n", argv[0]);
2440 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
2441 strupper_m(servername);
2443 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
2445 strupper_m(printername);
2447 result = rpccli_spoolss_open_printer_ex(
2448 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2449 servername, cli->user_name, &hnd);
2451 if (!W_ERROR_IS_OK(result)) {
2452 printf("Error opening %s\n", argv[1]);
2458 /* Create spool options */
2460 ZERO_STRUCT(option);
2463 option.option_type_ptr = 1;
2464 option.count = option.ctr.count = 2;
2466 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2467 if (option.ctr.type == NULL) {
2468 result = WERR_NOMEM;
2472 ZERO_STRUCT(option.ctr.type[0]);
2473 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2474 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2475 option.ctr.type[0].fields_ptr = 1;
2476 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2478 ZERO_STRUCT(option.ctr.type[1]);
2479 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2480 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2481 option.ctr.type[1].fields_ptr = 1;
2482 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2486 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2487 strupper_m(servername);
2489 result = rpccli_spoolss_rffpcnex(
2490 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2492 if (!W_ERROR_IS_OK(result)) {
2493 printf("Error rffpcnex %s\n", argv[1]);
2499 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2504 /****************************************************************************
2505 ****************************************************************************/
2507 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2508 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2510 PRINTER_INFO_CTR ctr1, ctr2;
2512 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2514 printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
2515 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2516 if ( !W_ERROR_IS_OK(werror) ) {
2517 printf("failed (%s)\n", dos_errstr(werror));
2518 talloc_destroy(mem_ctx);
2523 printf("Retrieving printer properties for %s...", cli2->cli->desthost);
2524 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2525 if ( !W_ERROR_IS_OK(werror) ) {
2526 printf("failed (%s)\n", dos_errstr(werror));
2527 talloc_destroy(mem_ctx);
2532 talloc_destroy(mem_ctx);
2537 /****************************************************************************
2538 ****************************************************************************/
2540 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2541 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2543 PRINTER_INFO_CTR ctr1, ctr2;
2545 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2546 SEC_DESC *sd1, *sd2;
2550 printf("Retreiving printer security for %s...", cli1->cli->desthost);
2551 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2552 if ( !W_ERROR_IS_OK(werror) ) {
2553 printf("failed (%s)\n", dos_errstr(werror));
2559 printf("Retrieving printer security for %s...", cli2->cli->desthost);
2560 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2561 if ( !W_ERROR_IS_OK(werror) ) {
2562 printf("failed (%s)\n", dos_errstr(werror));
2571 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2572 printf("NULL PRINTER_INFO_3!\n");
2577 sd1 = ctr1.printers_3->secdesc;
2578 sd2 = ctr2.printers_3->secdesc;
2580 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2581 printf("NULL secdesc!\n");
2586 if (!sec_desc_equal( sd1, sd2 ) ) {
2587 printf("Security Descriptors *not* equal!\n");
2592 printf("Security descriptors match\n");
2595 talloc_destroy(mem_ctx);
2600 /****************************************************************************
2601 ****************************************************************************/
2603 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2604 TALLOC_CTX *mem_ctx, int argc,
2607 fstring printername, servername1, servername2;
2608 pstring printername_path;
2609 struct cli_state *cli_server1 = cli->cli;
2610 struct cli_state *cli_server2 = NULL;
2611 struct rpc_pipe_client *cli2 = NULL;
2612 POLICY_HND hPrinter1, hPrinter2;
2617 printf("Usage: %s <printer> <server>\n", argv[0]);
2621 fstrcpy( printername, argv[1] );
2623 fstr_sprintf( servername1, cli->cli->desthost );
2624 fstrcpy( servername2, argv[2] );
2625 strupper_m( servername1 );
2626 strupper_m( servername2 );
2629 /* first get the connection to the remote server */
2631 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2634 cmdline_auth_info.username,
2636 cmdline_auth_info.password,
2637 cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2638 cmdline_auth_info.signing_state, NULL);
2640 if ( !NT_STATUS_IS_OK(nt_status) )
2641 return WERR_GENERAL_FAILURE;
2643 cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
2645 printf("failed to open spoolss pipe on server %s (%s)\n",
2646 servername2, nt_errstr(nt_status));
2647 return WERR_GENERAL_FAILURE;
2650 /* now open up both printers */
2652 pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
2653 printf("Opening %s...", printername_path);
2654 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2655 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2656 if ( !W_ERROR_IS_OK(werror) ) {
2657 printf("failed (%s)\n", dos_errstr(werror));
2662 pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
2663 printf("Opening %s...", printername_path);
2664 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2665 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2666 if ( !W_ERROR_IS_OK(werror) ) {
2667 printf("failed (%s)\n", dos_errstr(werror));
2673 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2674 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2676 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2683 printf("Closing printers...");
2684 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2685 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2688 /* close the second remote connection */
2690 cli_shutdown( cli_server2 );
2695 /* List of commands exported by this module */
2696 struct cmd_set spoolss_commands[] = {
2700 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" },
2701 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" },
2702 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" },
2703 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" },
2704 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" },
2705 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" },
2706 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" },
2707 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" },
2708 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" },
2709 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
2710 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" },
2711 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" },
2712 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
2713 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" },
2714 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" },
2715 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" },
2716 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" },
2717 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" },
2718 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" },
2719 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" },
2720 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" },
2721 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" },
2722 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" },
2723 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" },
2724 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" },
2725 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" },
2726 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" },
2727 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" },
2728 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" },