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"
27 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
29 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
30 _cli->srv_name_slash, _arg); \
31 W_ERROR_HAVE_NO_MEMORY(_printername); \
35 const char *long_archi;
36 const char *short_archi;
40 /* The version int is used by getdrivers. Note that
41 all architecture strings that support mutliple
42 versions must be grouped together since enumdrivers
43 uses this property to prevent issuing multiple
44 enumdriver calls for the same arch */
47 static const struct table_node archi_table[]= {
49 {"Windows 4.0", "WIN40", 0 },
50 {"Windows NT x86", "W32X86", 2 },
51 {"Windows NT x86", "W32X86", 3 },
52 {"Windows NT R4000", "W32MIPS", 2 },
53 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
54 {"Windows NT PowerPC", "W32PPC", 2 },
55 {"Windows IA64", "IA64", 3 },
56 {"Windows x64", "x64", 3 },
63 * rpcclient module for SPOOLSS rpc pipe.
65 * This generally just parses and checks command lines, and then calls
66 * a cli_spoolss function.
69 /****************************************************************************
70 function to do the mapping between the long architecture name and
72 ****************************************************************************/
74 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
78 DEBUG(107,("Getting architecture dependant directory\n"));
81 } while ( (archi_table[i].long_archi!=NULL ) &&
82 StrCaseCmp(long_archi, archi_table[i].long_archi) );
84 if (archi_table[i].long_archi==NULL) {
85 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
89 /* this might be client code - but shouldn't this be an fstrcpy etc? */
92 DEBUGADD(108,("index: [%d]\n", i));
93 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
94 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
96 return archi_table[i].short_archi;
99 /****************************************************************************
100 ****************************************************************************/
102 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
104 int argc, const char **argv)
110 printf("Usage: %s <printername>\n", argv[0]);
115 return WERR_GENERAL_FAILURE;
117 /* Open the printer handle */
119 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", argv[1]);
125 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
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_info7(struct spoolss_PrinterInfo7 *r)
288 printf("\tguid:[%s]\n", r->guid);
289 printf("\taction:[0x%x]\n", r->action);
293 /****************************************************************************
294 ****************************************************************************/
296 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
298 int argc, const char **argv)
301 uint32 info_level = 1;
302 PRINTER_INFO_CTR ctr;
303 uint32 i = 0, num_printers;
308 printf("Usage: %s [level] [name]\n", argv[0]);
313 info_level = atoi(argv[1]);
316 fstrcpy(name, argv[2]);
318 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
324 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
325 info_level, &num_printers, &ctr);
327 if (W_ERROR_IS_OK(result)) {
330 printf ("No printers returned.\n");
334 for (i = 0; i < num_printers; i++) {
337 display_print_info_0(&ctr.printers_0[i]);
340 display_print_info_1(&ctr.printers_1[i]);
343 display_print_info_2(&ctr.printers_2[i]);
346 display_print_info_3(&ctr.printers_3[i]);
349 printf("unknown info level %d\n", info_level);
359 /****************************************************************************
360 ****************************************************************************/
362 static void display_port_info_1(PORT_INFO_1 *i1)
366 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
367 printf("\tPort Name:\t[%s]\n", buffer);
370 /****************************************************************************
371 ****************************************************************************/
373 static void display_port_info_2(PORT_INFO_2 *i2)
377 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
378 printf("\tPort Name:\t[%s]\n", buffer);
379 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
381 printf("\tMonitor Name:\t[%s]\n", buffer);
382 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
384 printf("\tDescription:\t[%s]\n", buffer);
385 printf("\tPort Type:\t" );
386 if ( i2->port_type ) {
387 int comma = 0; /* hack */
389 if ( i2->port_type & PORT_TYPE_READ ) {
393 if ( i2->port_type & PORT_TYPE_WRITE ) {
394 printf( "%sWrite", comma ? ", " : "" );
397 /* These two have slightly different interpretations
398 on 95/98/ME but I'm disregarding that for now */
399 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
400 printf( "%sRedirected", comma ? ", " : "" );
403 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
404 printf( "%sNet-Attached", comma ? ", " : "" );
408 printf( "[Unset]\n" );
410 printf("\tReserved:\t[%d]\n", i2->reserved);
414 /****************************************************************************
415 ****************************************************************************/
417 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
418 TALLOC_CTX *mem_ctx, int argc,
422 uint32 info_level = 1;
427 printf("Usage: %s [level]\n", argv[0]);
432 info_level = atoi(argv[1]);
434 /* Enumerate ports */
438 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
440 if (W_ERROR_IS_OK(result)) {
443 for (i = 0; i < returned; i++) {
444 switch (info_level) {
446 display_port_info_1(&ctr.port.info_1[i]);
449 display_port_info_2(&ctr.port.info_2[i]);
452 printf("unknown info level %d\n", info_level);
461 /****************************************************************************
462 ****************************************************************************/
464 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
466 int argc, const char **argv)
471 uint32 info_level = 2;
472 bool opened_hnd = False;
473 union spoolss_PrinterInfo info;
474 struct spoolss_SetPrinterInfoCtr info_ctr;
475 const char *printername, *comment = NULL;
476 struct spoolss_DevmodeContainer devmode_ctr;
477 struct sec_desc_buf secdesc_ctr;
479 if (argc == 1 || argc > 3) {
480 printf("Usage: %s printername comment\n", argv[0]);
485 /* Open a printer handle */
490 ZERO_STRUCT(devmode_ctr);
491 ZERO_STRUCT(secdesc_ctr);
493 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
495 /* get a printer handle */
496 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
500 if (!W_ERROR_IS_OK(result))
505 /* Get printer info */
506 result = rpccli_spoolss_getprinter(cli, mem_ctx,
511 if (!W_ERROR_IS_OK(result))
515 /* Modify the comment. */
516 info.info2.comment = comment;
519 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
521 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
528 if (W_ERROR_IS_OK(result))
529 printf("Success in setting comment.\n");
533 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
538 /****************************************************************************
539 ****************************************************************************/
541 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
543 int argc, const char **argv)
548 uint32 info_level = 2;
549 bool opened_hnd = False;
550 union spoolss_PrinterInfo info;
551 const char *printername,
552 *new_printername = NULL;
553 struct spoolss_SetPrinterInfoCtr info_ctr;
554 struct spoolss_DevmodeContainer devmode_ctr;
555 struct sec_desc_buf secdesc_ctr;
557 ZERO_STRUCT(devmode_ctr);
558 ZERO_STRUCT(secdesc_ctr);
560 if (argc == 1 || argc > 3) {
561 printf("Usage: %s printername new_printername\n", argv[0]);
566 /* Open a printer handle */
568 new_printername = argv[2];
571 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
573 /* get a printer handle */
574 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
578 if (!W_ERROR_IS_OK(result))
583 /* Get printer info */
584 result = rpccli_spoolss_getprinter(cli, mem_ctx,
589 if (!W_ERROR_IS_OK(result))
592 /* Modify the printername. */
593 info.info2.printername = new_printername;
594 info.info2.devmode = NULL;
595 info.info2.secdesc = NULL;
597 info_ctr.level = info_level;
598 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
600 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
607 if (W_ERROR_IS_OK(result))
608 printf("Success in setting printername.\n");
612 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
617 /****************************************************************************
618 ****************************************************************************/
620 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
622 int argc, const char **argv)
626 uint32 info_level = 1;
627 bool opened_hnd = False;
628 const char *printername;
629 union spoolss_PrinterInfo info;
631 if (argc == 1 || argc > 3) {
632 printf("Usage: %s <printername> [level]\n", argv[0]);
636 /* Open a printer handle */
638 info_level = atoi(argv[2]);
641 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
643 /* get a printer handle */
645 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
647 SEC_FLAG_MAXIMUM_ALLOWED,
649 if (!W_ERROR_IS_OK(result))
654 /* Get printer info */
656 result = rpccli_spoolss_getprinter(cli, mem_ctx,
661 if (!W_ERROR_IS_OK(result))
664 /* Display printer info */
665 switch (info_level) {
668 display_print_info_0(ctr.printers_0);
671 display_print_info_1(ctr.printers_1);
674 display_print_info_2(ctr.printers_2);
677 display_print_info_3(ctr.printers_3);
681 display_print_info7(&info.info7);
684 printf("unknown info level %d\n", info_level);
689 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
694 /****************************************************************************
695 ****************************************************************************/
697 static void display_reg_value(REGISTRY_VALUE value)
703 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
704 *((uint32 *) value.data_p));
707 rpcstr_pull_talloc(talloc_tos(),
712 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
715 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
717 printf("%s: REG_BINARY:", value.valuename);
719 for (i=0; i<len; i++) {
720 if (hex[i] == '\0') {
733 uint32 i, num_values;
736 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
737 value.size, &num_values,
739 d_printf("reg_pull_multi_sz failed\n");
743 for (i=0; i<num_values; i++) {
744 d_printf("%s\n", values[i]);
750 printf("%s: unknown type %d\n", value.valuename, value.type);
755 /****************************************************************************
756 ****************************************************************************/
758 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
760 int argc, const char **argv)
764 bool opened_hnd = False;
766 const char *valuename;
767 REGISTRY_VALUE value;
770 printf("Usage: %s <printername> <valuename>\n", argv[0]);
771 printf("<printername> of . queries print server\n");
776 /* Open a printer handle */
778 if (strncmp(argv[1], ".", sizeof(".")) == 0)
779 fstrcpy(printername, cli->srv_name_slash);
781 slprintf(printername, sizeof(printername)-1, "%s\\%s",
782 cli->srv_name_slash, argv[1]);
784 /* get a printer handle */
786 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
788 SEC_FLAG_MAXIMUM_ALLOWED,
790 if (!W_ERROR_IS_OK(result))
795 /* Get printer info */
797 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
799 if (!W_ERROR_IS_OK(result))
802 /* Display printer data */
804 fstrcpy(value.valuename, valuename);
805 display_reg_value(value);
810 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
815 /****************************************************************************
816 ****************************************************************************/
818 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
820 int argc, const char **argv)
825 bool opened_hnd = False;
827 const char *valuename, *keyname;
828 REGISTRY_VALUE value;
831 uint8_t *buffer = NULL;
832 uint32_t offered = 0;
836 printf("Usage: %s <printername> <keyname> <valuename>\n",
838 printf("<printername> of . queries print server\n");
844 /* Open a printer handle */
846 if (strncmp(argv[1], ".", sizeof(".")) == 0)
847 fstrcpy(printername, cli->srv_name_slash);
849 slprintf(printername, sizeof(printername)-1, "%s\\%s",
850 cli->srv_name_slash, argv[1]);
852 /* get a printer handle */
854 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
856 SEC_FLAG_MAXIMUM_ALLOWED,
858 if (!W_ERROR_IS_OK(result))
863 /* Get printer info */
865 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
874 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
876 buffer = talloc_array(mem_ctx, uint8_t, needed);
877 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
888 if (!NT_STATUS_IS_OK(status)) {
892 if (!W_ERROR_IS_OK(result)) {
897 if (!W_ERROR_IS_OK(result))
900 /* Display printer data */
902 fstrcpy(value.valuename, valuename);
905 value.data_p = buffer;
907 display_reg_value(value);
911 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
916 /****************************************************************************
917 ****************************************************************************/
919 static void display_print_driver_1(DRIVER_INFO_1 *i1)
925 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
927 printf ("Printer Driver Info 1:\n");
928 printf ("\tDriver Name: [%s]\n\n", name);
933 /****************************************************************************
934 ****************************************************************************/
936 static void display_print_driver_2(DRIVER_INFO_2 *i1)
939 fstring architecture;
946 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
947 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
948 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
949 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
950 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
952 printf ("Printer Driver Info 2:\n");
953 printf ("\tVersion: [%x]\n", i1->version);
954 printf ("\tDriver Name: [%s]\n", name);
955 printf ("\tArchitecture: [%s]\n", architecture);
956 printf ("\tDriver Path: [%s]\n", driverpath);
957 printf ("\tDatafile: [%s]\n", datafile);
958 printf ("\tConfigfile: [%s]\n\n", configfile);
963 /****************************************************************************
964 ****************************************************************************/
966 static void display_print_driver_3(DRIVER_INFO_3 *i1)
969 fstring architecture = "";
970 fstring driverpath = "";
971 fstring datafile = "";
972 fstring configfile = "";
973 fstring helpfile = "";
974 fstring dependentfiles = "";
975 fstring monitorname = "";
976 fstring defaultdatatype = "";
984 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
985 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
986 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
987 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
988 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
989 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
990 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
991 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
993 printf ("Printer Driver Info 3:\n");
994 printf ("\tVersion: [%x]\n", i1->version);
995 printf ("\tDriver Name: [%s]\n",name);
996 printf ("\tArchitecture: [%s]\n", architecture);
997 printf ("\tDriver Path: [%s]\n", driverpath);
998 printf ("\tDatafile: [%s]\n", datafile);
999 printf ("\tConfigfile: [%s]\n", configfile);
1000 printf ("\tHelpfile: [%s]\n\n", helpfile);
1004 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
1006 length+=strlen(dependentfiles)+1;
1008 if (strlen(dependentfiles) > 0)
1010 printf ("\tDependentfiles: [%s]\n", dependentfiles);
1020 printf ("\tMonitorname: [%s]\n", monitorname);
1021 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
1026 /****************************************************************************
1027 ****************************************************************************/
1029 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1035 printf("Printer Driver Info 1:\n");
1036 printf("\tDriver Name: [%s]\n\n", r->driver_name);
1039 /****************************************************************************
1040 ****************************************************************************/
1042 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1048 printf("Printer Driver Info 2:\n");
1049 printf("\tVersion: [%x]\n", r->version);
1050 printf("\tDriver Name: [%s]\n", r->driver_name);
1051 printf("\tArchitecture: [%s]\n", r->architecture);
1052 printf("\tDriver Path: [%s]\n", r->driver_path);
1053 printf("\tDatafile: [%s]\n", r->data_file);
1054 printf("\tConfigfile: [%s]\n\n", r->config_file);
1057 /****************************************************************************
1058 ****************************************************************************/
1060 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1068 printf("Printer Driver Info 3:\n");
1069 printf("\tVersion: [%x]\n", r->version);
1070 printf("\tDriver Name: [%s]\n", r->driver_name);
1071 printf("\tArchitecture: [%s]\n", r->architecture);
1072 printf("\tDriver Path: [%s]\n", r->driver_path);
1073 printf("\tDatafile: [%s]\n", r->data_file);
1074 printf("\tConfigfile: [%s]\n\n", r->config_file);
1075 printf("\tHelpfile: [%s]\n\n", r->help_file);
1077 for (i=0; r->dependent_files[i] != NULL; i++) {
1078 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1083 printf("\tMonitorname: [%s]\n", r->monitor_name);
1084 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
1088 /****************************************************************************
1089 ****************************************************************************/
1091 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1092 TALLOC_CTX *mem_ctx,
1093 int argc, const char **argv)
1097 uint32 info_level = 3;
1098 bool opened_hnd = False;
1099 const char *printername;
1101 bool success = False;
1102 union spoolss_DriverInfo info;
1103 uint32_t server_major_version;
1104 uint32_t server_minor_version;
1106 if ((argc == 1) || (argc > 3))
1108 printf("Usage: %s <printername> [level]\n", argv[0]);
1112 /* get the arguments need to open the printer handle */
1114 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1117 info_level = atoi(argv[2]);
1119 /* Open a printer handle */
1121 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1125 if (!W_ERROR_IS_OK(werror)) {
1126 printf("Error opening printer handle for %s!\n", printername);
1132 /* loop through and print driver info level for each architecture */
1134 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1136 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1138 archi_table[i].long_archi,
1141 archi_table[i].version,
1144 &server_major_version,
1145 &server_minor_version);
1146 if (!W_ERROR_IS_OK(werror))
1149 /* need at least one success */
1153 printf ("\n[%s]\n", archi_table[i].long_archi);
1155 switch (info_level) {
1157 display_print_driver1(&info.info1);
1160 display_print_driver2(&info.info2);
1163 display_print_driver3(&info.info3);
1166 printf("unknown info level %d\n", info_level);
1174 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1182 /****************************************************************************
1183 ****************************************************************************/
1185 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1186 TALLOC_CTX *mem_ctx,
1187 int argc, const char **argv)
1189 WERROR werror = WERR_OK;
1190 uint32 info_level = 1;
1191 PRINTER_DRIVER_CTR ctr;
1196 printf("Usage: enumdrivers [level]\n");
1201 info_level = atoi(argv[1]);
1204 /* loop through and print driver info level for each architecture */
1205 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1206 /* check to see if we already asked for this architecture string */
1208 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1211 werror = rpccli_spoolss_enumprinterdrivers(
1212 cli, mem_ctx, info_level,
1213 archi_table[i].long_archi, &returned, &ctr);
1215 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1216 printf ("Server does not support environment [%s]\n",
1217 archi_table[i].long_archi);
1225 if (!W_ERROR_IS_OK(werror)) {
1226 printf ("Error getting driver for environment [%s] - %d\n",
1227 archi_table[i].long_archi, W_ERROR_V(werror));
1231 printf ("\n[%s]\n", archi_table[i].long_archi);
1236 for (j=0; j < returned; j++) {
1237 display_print_driver_1 (&ctr.info1[j]);
1241 for (j=0; j < returned; j++) {
1242 display_print_driver_2 (&ctr.info2[j]);
1246 for (j=0; j < returned; j++) {
1247 display_print_driver_3 (&ctr.info3[j]);
1251 printf("unknown info level %d\n", info_level);
1252 return WERR_UNKNOWN_LEVEL;
1259 /****************************************************************************
1260 ****************************************************************************/
1262 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1264 printf("\tDirectory Name:[%s]\n", r->directory_name);
1267 /****************************************************************************
1268 ****************************************************************************/
1270 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1271 TALLOC_CTX *mem_ctx,
1272 int argc, const char **argv)
1276 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1279 union spoolss_DriverDirectoryInfo info;
1283 printf("Usage: %s [environment]\n", argv[0]);
1287 /* Get the arguments need to open the printer handle */
1293 /* Get the directory. Only use Info level 1 */
1295 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1296 cli->srv_name_slash,
1304 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1306 buffer = data_blob_talloc_zero(mem_ctx, needed);
1308 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1309 cli->srv_name_slash,
1319 if (W_ERROR_IS_OK(result)) {
1320 display_printdriverdir_1(&info.info1);
1326 /****************************************************************************
1327 ****************************************************************************/
1329 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1330 struct spoolss_AddDriverInfo3 *info,
1336 for (i=0; archi_table[i].long_archi != NULL; i++)
1338 if (strcmp(arch, archi_table[i].short_archi) == 0)
1340 info->version = archi_table[i].version;
1341 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1346 if (archi_table[i].long_archi == NULL)
1348 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1355 /**************************************************************************
1356 wrapper for strtok to get the next parameter from a delimited list.
1357 Needed to handle the empty parameter string denoted by "NULL"
1358 *************************************************************************/
1360 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1361 const char *delim, const char **dest,
1366 /* get the next token */
1367 ptr = strtok_r(str, delim, saveptr);
1369 /* a string of 'NULL' is used to represent an empty
1370 parameter because two consecutive delimiters
1371 will not return an empty string. See man strtok(3)
1373 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1378 *dest = talloc_strdup(mem_ctx, ptr);
1384 /********************************************************************************
1385 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1386 string in the form of
1387 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1388 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1389 <Default Data Type>:<Comma Separated list of Files>
1390 *******************************************************************************/
1392 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1397 char *saveptr = NULL;
1398 struct spoolss_StringArray *deps;
1399 const char **file_array = NULL;
1402 /* fill in the UNISTR fields */
1403 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1404 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1405 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1406 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1407 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1408 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1409 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1411 /* <Comma Separated List of Dependent Files> */
1412 /* save the beginning of the string */
1413 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1416 /* begin to strip out each filename */
1417 str = strtok_r(str, ",", &saveptr);
1419 /* no dependent files, we are done */
1424 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1429 while (str != NULL) {
1430 add_string_to_array(deps, str, &file_array, &count);
1431 str = strtok_r(NULL, ",", &saveptr);
1434 deps->string = talloc_zero_array(deps, const char *, count + 1);
1435 if (!deps->string) {
1439 for (i=0; i < count; i++) {
1440 deps->string[i] = file_array[i];
1443 r->dependent_files = deps;
1448 /****************************************************************************
1449 ****************************************************************************/
1451 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1452 TALLOC_CTX *mem_ctx,
1453 int argc, const char **argv)
1458 struct spoolss_AddDriverInfoCtr info_ctr;
1459 struct spoolss_AddDriverInfo3 info3;
1463 /* parse the command arguments */
1464 if (argc != 3 && argc != 4)
1466 printf ("Usage: %s <Environment> \\\n", argv[0]);
1467 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1468 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1469 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1470 printf ("\t[version]\n");
1475 /* Fill in the spoolss_AddDriverInfo3 struct */
1478 arch = cmd_spoolss_get_short_archi(argv[1]);
1480 printf ("Error Unknown architechture [%s]\n", argv[1]);
1481 return WERR_INVALID_PARAM;
1484 set_drv_info_3_env(mem_ctx, &info3, arch);
1486 driver_args = talloc_strdup( mem_ctx, argv[2] );
1487 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1489 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1490 return WERR_INVALID_PARAM;
1493 /* if printer driver version specified, override the default version
1494 * used by the architecture. This allows installation of Windows
1495 * 2000 (version 3) printer drivers. */
1498 info3.version = atoi(argv[3]);
1502 info_ctr.level = level;
1503 info_ctr.info.info3 = &info3;
1505 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1506 cli->srv_name_slash,
1509 if (!NT_STATUS_IS_OK(status)) {
1510 return ntstatus_to_werror(status);
1512 if (W_ERROR_IS_OK(result)) {
1513 printf ("Printer Driver %s successfully installed.\n",
1521 /****************************************************************************
1522 ****************************************************************************/
1524 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1525 TALLOC_CTX *mem_ctx,
1526 int argc, const char **argv)
1529 struct spoolss_SetPrinterInfoCtr info_ctr;
1530 struct spoolss_SetPrinterInfo2 info2;
1532 /* parse the command arguments */
1535 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1539 /* Fill in the DRIVER_INFO_2 struct */
1542 info2.printername = argv[1];
1543 info2.drivername = argv[3];
1544 info2.sharename = argv[2];
1545 info2.portname = argv[4];
1546 info2.comment = "Created by rpcclient";
1547 info2.printprocessor = "winprint";
1548 info2.datatype = "RAW";
1549 info2.devmode = NULL;
1550 info2.secdesc = NULL;
1551 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1553 info2.defaultpriority = 0;
1554 info2.starttime = 0;
1555 info2.untiltime = 0;
1557 /* These three fields must not be used by AddPrinter()
1558 as defined in the MS Platform SDK documentation..
1562 info2.averageppm = 0;
1566 info_ctr.info.info2 = &info2;
1568 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1570 if (W_ERROR_IS_OK(result))
1571 printf ("Printer %s successfully installed.\n", argv[1]);
1576 /****************************************************************************
1577 ****************************************************************************/
1579 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1580 TALLOC_CTX *mem_ctx,
1581 int argc, const char **argv)
1587 bool opened_hnd = False;
1588 const char *printername;
1589 union spoolss_PrinterInfo info;
1590 struct spoolss_SetPrinterInfoCtr info_ctr;
1591 struct spoolss_DevmodeContainer devmode_ctr;
1592 struct sec_desc_buf secdesc_ctr;
1594 ZERO_STRUCT(devmode_ctr);
1595 ZERO_STRUCT(secdesc_ctr);
1597 /* parse the command arguments */
1600 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1604 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1606 /* Get a printer handle */
1608 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1612 if (!W_ERROR_IS_OK(result))
1617 /* Get printer info */
1619 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1624 if (!W_ERROR_IS_OK(result)) {
1625 printf ("Unable to retrieve printer information!\n");
1629 /* Set the printer driver */
1631 info.info2.drivername = argv[2];
1633 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1635 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1642 if (!W_ERROR_IS_OK(result)) {
1643 printf("SetPrinter call failed!\n");
1647 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1653 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1659 /****************************************************************************
1660 ****************************************************************************/
1662 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1663 TALLOC_CTX *mem_ctx,
1664 int argc, const char **argv)
1666 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1672 const char *arch = NULL;
1673 uint32_t delete_flags = 0;
1675 /* parse the command arguments */
1676 if (argc < 2 || argc > 4) {
1677 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1684 vers = atoi (argv[3]);
1687 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1690 /* delete the driver for all architectures */
1691 for (i=0; archi_table[i].long_archi; i++) {
1693 if (arch && !strequal( archi_table[i].long_archi, arch))
1696 if (vers >= 0 && archi_table[i].version != vers)
1699 /* make the call to remove the driver */
1700 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1701 cli->srv_name_slash,
1702 archi_table[i].long_archi,
1705 archi_table[i].version,
1708 if ( !W_ERROR_IS_OK(result) )
1710 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1711 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1712 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1717 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1718 archi_table[i].long_archi, archi_table[i].version);
1727 /****************************************************************************
1728 ****************************************************************************/
1730 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1731 TALLOC_CTX *mem_ctx,
1732 int argc, const char **argv)
1734 WERROR result = WERR_OK;
1738 /* parse the command arguments */
1740 printf ("Usage: %s <driver>\n", argv[0]);
1744 /* delete the driver for all architectures */
1745 for (i=0; archi_table[i].long_archi; i++) {
1746 /* make the call to remove the driver */
1747 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1748 cli->srv_name_slash,
1749 archi_table[i].long_archi,
1752 if (!NT_STATUS_IS_OK(status)) {
1755 if ( !W_ERROR_IS_OK(result) ) {
1756 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1757 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1758 argv[1], archi_table[i].long_archi,
1762 printf ("Driver %s removed for arch [%s].\n", argv[1],
1763 archi_table[i].long_archi);
1770 /****************************************************************************
1771 ****************************************************************************/
1773 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1774 TALLOC_CTX *mem_ctx,
1775 int argc, const char **argv)
1779 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1782 union spoolss_PrintProcessorDirectoryInfo info;
1785 /* parse the command arguments */
1787 printf ("Usage: %s [environment]\n", argv[0]);
1792 environment = argv[1];
1795 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1796 cli->srv_name_slash,
1804 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1806 buffer = data_blob_talloc_zero(mem_ctx, needed);
1808 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1809 cli->srv_name_slash,
1819 if (W_ERROR_IS_OK(result)) {
1820 printf("%s\n", info.info1.directory_name);
1826 /****************************************************************************
1827 ****************************************************************************/
1829 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1830 int argc, const char **argv)
1835 const char *printername;
1836 bool got_handle = False;
1837 union spoolss_AddFormInfo info;
1838 struct spoolss_AddFormInfo1 info1;
1840 /* Parse the command arguments */
1843 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1847 /* Get a printer handle */
1849 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1851 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1855 if (!W_ERROR_IS_OK(werror))
1860 /* Dummy up some values for the form data */
1862 info1.flags = FORM_USER;
1863 info1.form_name = argv[2];
1864 info1.size.width = 100;
1865 info1.size.height = 100;
1866 info1.area.left = 0;
1867 info1.area.top = 10;
1868 info1.area.right = 20;
1869 info1.area.bottom = 30;
1871 info.info1 = &info1;
1876 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1884 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1889 /****************************************************************************
1890 ****************************************************************************/
1892 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1893 int argc, const char **argv)
1898 const char *printername;
1899 bool got_handle = False;
1900 union spoolss_AddFormInfo info;
1901 struct spoolss_AddFormInfo1 info1;
1903 /* Parse the command arguments */
1906 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1910 /* Get a printer handle */
1912 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1914 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1916 SEC_FLAG_MAXIMUM_ALLOWED,
1918 if (!W_ERROR_IS_OK(werror))
1923 /* Dummy up some values for the form data */
1925 info1.flags = FORM_PRINTER;
1926 info1.size.width = 100;
1927 info1.size.height = 100;
1928 info1.area.left = 0;
1929 info1.area.top = 1000;
1930 info1.area.right = 2000;
1931 info1.area.bottom = 3000;
1932 info1.form_name = argv[2];
1934 info.info1 = &info1;
1938 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1947 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1952 /****************************************************************************
1953 ****************************************************************************/
1955 static const char *get_form_flag(int form_flag)
1957 switch (form_flag) {
1961 return "FORM_BUILTIN";
1963 return "FORM_PRINTER";
1969 /****************************************************************************
1970 ****************************************************************************/
1972 static void display_form(FORM_1 *form)
1974 fstring form_name = "";
1976 if (form->name.buffer)
1977 rpcstr_pull(form_name, form->name.buffer,
1978 sizeof(form_name), -1, STR_TERMINATE);
1981 "\tflag: %s (%d)\n" \
1982 "\twidth: %d, length: %d\n" \
1983 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1984 form_name, get_form_flag(form->flag), form->flag,
1985 form->width, form->length,
1986 form->left, form->right,
1987 form->top, form->bottom);
1990 /****************************************************************************
1991 ****************************************************************************/
1993 static void display_form_info1(struct spoolss_FormInfo1 *r)
1996 "\tflag: %s (%d)\n" \
1997 "\twidth: %d, length: %d\n" \
1998 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1999 r->form_name, get_form_flag(r->flags), r->flags,
2000 r->size.width, r->size.height,
2001 r->area.left, r->area.right,
2002 r->area.top, r->area.bottom);
2005 /****************************************************************************
2006 ****************************************************************************/
2008 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2009 int argc, const char **argv)
2014 const char *printername;
2015 bool got_handle = False;
2017 uint32_t offered = 0;
2018 union spoolss_FormInfo info;
2021 /* Parse the command arguments */
2024 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2028 /* Get a printer handle */
2030 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2032 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2034 SEC_FLAG_MAXIMUM_ALLOWED,
2036 if (!W_ERROR_IS_OK(werror))
2043 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2052 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2053 buffer = data_blob_talloc(mem_ctx, NULL, needed);
2055 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2066 if (!NT_STATUS_IS_OK(status)) {
2070 display_form_info1(&info.info1);
2073 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2078 /****************************************************************************
2079 ****************************************************************************/
2081 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2082 TALLOC_CTX *mem_ctx, int argc,
2088 const char *printername;
2089 bool got_handle = False;
2091 /* Parse the command arguments */
2094 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2098 /* Get a printer handle */
2100 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2102 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2104 SEC_FLAG_MAXIMUM_ALLOWED,
2106 if (!W_ERROR_IS_OK(werror))
2111 /* Delete the form */
2113 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2117 if (!NT_STATUS_IS_OK(status)) {
2118 return ntstatus_to_werror(status);
2123 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2128 /****************************************************************************
2129 ****************************************************************************/
2131 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2132 TALLOC_CTX *mem_ctx, int argc,
2137 const char *printername;
2138 bool got_handle = False;
2139 uint32 num_forms, level = 1, i;
2142 /* Parse the command arguments */
2145 printf ("Usage: %s <printer>\n", argv[0]);
2149 /* Get a printer handle */
2151 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2153 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2155 SEC_FLAG_MAXIMUM_ALLOWED,
2157 if (!W_ERROR_IS_OK(werror))
2162 /* Enumerate forms */
2164 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
2166 if (!W_ERROR_IS_OK(werror))
2169 /* Display output */
2171 for (i = 0; i < num_forms; i++) {
2173 display_form(&forms[i]);
2179 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2184 /****************************************************************************
2185 ****************************************************************************/
2187 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2188 TALLOC_CTX *mem_ctx,
2189 int argc, const char **argv)
2192 const char *printername;
2194 bool opened_hnd = False;
2195 union spoolss_PrinterInfo info;
2196 REGISTRY_VALUE value;
2197 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2199 /* parse the command arguments */
2201 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2202 " <value> <data>\n",
2204 result = WERR_INVALID_PARAM;
2208 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2210 value.type = REG_NONE;
2212 if (strequal(argv[2], "string")) {
2213 value.type = REG_SZ;
2216 if (strequal(argv[2], "binary")) {
2217 value.type = REG_BINARY;
2220 if (strequal(argv[2], "dword")) {
2221 value.type = REG_DWORD;
2224 if (strequal(argv[2], "multistring")) {
2225 value.type = REG_MULTI_SZ;
2228 if (value.type == REG_NONE) {
2229 printf("Unknown data type: %s\n", argv[2]);
2230 result = WERR_INVALID_PARAM;
2234 /* get a printer handle */
2236 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2238 SEC_FLAG_MAXIMUM_ALLOWED,
2240 if (!W_ERROR_IS_OK(result))
2245 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2250 if (!W_ERROR_IS_OK(result))
2253 printf("%s\n", current_timestring(tmp_ctx, True));
2254 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2256 /* Set the printer data */
2258 fstrcpy(value.valuename, argv[3]);
2260 switch (value.type) {
2263 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2264 value.size = data.uni_str_len * 2;
2266 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2269 value.data_p = NULL;
2274 uint32 data = strtoul(argv[4], NULL, 10);
2275 value.size = sizeof(data);
2277 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2280 value.data_p = NULL;
2285 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2286 value.data_p = data.data;
2287 value.size = data.length;
2290 case REG_MULTI_SZ: {
2295 for (i=4; i<argc; i++) {
2296 if (strcmp(argv[i], "NULL") == 0) {
2299 len += strlen(argv[i])+1;
2303 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2304 if (value.data_p == NULL) {
2305 result = WERR_NOMEM;
2309 p = (char *)value.data_p;
2311 for (i=4; i<argc; i++) {
2312 size_t l = (strlen(argv[i])+1)*2;
2313 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2317 SMB_ASSERT(len == 0);
2321 printf("Unknown data type: %s\n", argv[2]);
2322 result = WERR_INVALID_PARAM;
2326 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2328 if (!W_ERROR_IS_OK(result)) {
2329 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2332 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2334 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2339 if (!W_ERROR_IS_OK(result))
2342 printf("%s\n", current_timestring(tmp_ctx, True));
2343 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2347 TALLOC_FREE(tmp_ctx);
2349 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2354 /****************************************************************************
2355 ****************************************************************************/
2357 static void display_job_info_1(JOB_INFO_1 *job)
2359 fstring username = "", document = "", text_status = "";
2361 rpcstr_pull(username, job->username.buffer,
2362 sizeof(username), -1, STR_TERMINATE);
2364 rpcstr_pull(document, job->document.buffer,
2365 sizeof(document), -1, STR_TERMINATE);
2367 rpcstr_pull(text_status, job->text_status.buffer,
2368 sizeof(text_status), -1, STR_TERMINATE);
2370 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2371 username, document, text_status, job->pagesprinted,
2375 /****************************************************************************
2376 ****************************************************************************/
2378 static void display_job_info_2(JOB_INFO_2 *job)
2380 fstring username = "", document = "", text_status = "";
2382 rpcstr_pull(username, job->username.buffer,
2383 sizeof(username), -1, STR_TERMINATE);
2385 rpcstr_pull(document, job->document.buffer,
2386 sizeof(document), -1, STR_TERMINATE);
2388 rpcstr_pull(text_status, job->text_status.buffer,
2389 sizeof(text_status), -1, STR_TERMINATE);
2391 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2392 username, document, text_status, job->pagesprinted,
2393 job->totalpages, job->size);
2396 /****************************************************************************
2397 ****************************************************************************/
2399 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2400 TALLOC_CTX *mem_ctx, int argc,
2404 uint32 level = 1, num_jobs, i;
2405 bool got_hnd = False;
2406 const char *printername;
2410 if (argc < 2 || argc > 3) {
2411 printf("Usage: %s printername [level]\n", argv[0]);
2416 level = atoi(argv[2]);
2418 /* Open printer handle */
2420 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2422 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2424 SEC_FLAG_MAXIMUM_ALLOWED,
2426 if (!W_ERROR_IS_OK(result))
2431 /* Enumerate ports */
2433 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2436 if (!W_ERROR_IS_OK(result))
2439 for (i = 0; i < num_jobs; i++) {
2442 display_job_info_1(&ctr.job.job_info_1[i]);
2445 display_job_info_2(&ctr.job.job_info_2[i]);
2448 d_printf("unknown info level %d\n", level);
2455 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2460 /****************************************************************************
2461 ****************************************************************************/
2463 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2464 TALLOC_CTX *mem_ctx, int argc,
2468 uint32 i=0, val_needed, data_needed;
2469 bool got_hnd = False;
2470 const char *printername;
2474 printf("Usage: %s printername\n", argv[0]);
2478 /* Open printer handle */
2480 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2482 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2484 SEC_FLAG_MAXIMUM_ALLOWED,
2486 if (!W_ERROR_IS_OK(result))
2491 /* Enumerate data */
2493 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2494 &val_needed, &data_needed,
2496 while (W_ERROR_IS_OK(result)) {
2497 REGISTRY_VALUE value;
2498 result = rpccli_spoolss_enumprinterdata(
2499 cli, mem_ctx, &hnd, i++, val_needed,
2500 data_needed, 0, 0, &value);
2501 if (W_ERROR_IS_OK(result))
2502 display_reg_value(value);
2504 if (W_ERROR_V(result) == ERRnomoreitems)
2505 result = W_ERROR(ERRsuccess);
2509 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2514 /****************************************************************************
2515 ****************************************************************************/
2517 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2518 TALLOC_CTX *mem_ctx, int argc,
2523 bool got_hnd = False;
2524 const char *printername;
2525 const char *keyname = NULL;
2527 REGVAL_CTR *ctr = NULL;
2530 printf("Usage: %s printername <keyname>\n", argv[0]);
2536 /* Open printer handle */
2538 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2540 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2542 SEC_FLAG_MAXIMUM_ALLOWED,
2544 if (!W_ERROR_IS_OK(result))
2549 /* Enumerate subkeys */
2551 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2554 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2556 if (!W_ERROR_IS_OK(result))
2559 for (i=0; i < ctr->num_values; i++) {
2560 display_reg_value(*(ctr->values[i]));
2567 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2572 /****************************************************************************
2573 ****************************************************************************/
2575 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2576 TALLOC_CTX *mem_ctx, int argc,
2580 bool got_hnd = False;
2581 const char *printername;
2582 const char *keyname = NULL;
2584 uint16 *keylist = NULL, *curkey;
2586 if (argc < 2 || argc > 3) {
2587 printf("Usage: %s printername [keyname]\n", argv[0]);
2596 /* Open printer handle */
2598 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2600 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2602 SEC_FLAG_MAXIMUM_ALLOWED,
2604 if (!W_ERROR_IS_OK(result))
2609 /* Enumerate subkeys */
2611 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2613 if (!W_ERROR_IS_OK(result))
2617 while (*curkey != 0) {
2618 char *subkey = NULL;
2619 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2624 printf("%s\n", subkey);
2625 curkey += strlen(subkey) + 1;
2633 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2638 /****************************************************************************
2639 ****************************************************************************/
2641 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2642 TALLOC_CTX *mem_ctx, int argc,
2645 const char *printername;
2646 const char *clientname;
2648 bool got_hnd = False;
2651 struct spoolss_NotifyOption option;
2654 printf("Usage: %s printername\n", argv[0]);
2661 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2663 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2665 SEC_FLAG_MAXIMUM_ALLOWED,
2667 if (!W_ERROR_IS_OK(result)) {
2668 printf("Error opening %s\n", argv[1]);
2674 /* Create spool options */
2679 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2680 if (option.types == NULL) {
2681 result = WERR_NOMEM;
2685 option.types[0].type = PRINTER_NOTIFY_TYPE;
2686 option.types[0].count = 1;
2687 option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2688 if (option.types[0].fields == NULL) {
2689 result = WERR_NOMEM;
2692 option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2694 option.types[1].type = JOB_NOTIFY_TYPE;
2695 option.types[1].count = 1;
2696 option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2697 if (option.types[1].fields == NULL) {
2698 result = WERR_NOMEM;
2701 option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2703 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2705 result = WERR_NOMEM;
2711 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2719 if (!W_ERROR_IS_OK(result)) {
2720 printf("Error rffpcnex %s\n", argv[1]);
2726 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2731 /****************************************************************************
2732 ****************************************************************************/
2734 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2735 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2737 union spoolss_PrinterInfo info1, info2;
2739 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2741 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2742 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2747 if ( !W_ERROR_IS_OK(werror) ) {
2748 printf("failed (%s)\n", win_errstr(werror));
2749 talloc_destroy(mem_ctx);
2754 printf("Retrieving printer properties for %s...", cli2->desthost);
2755 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2760 if ( !W_ERROR_IS_OK(werror) ) {
2761 printf("failed (%s)\n", win_errstr(werror));
2762 talloc_destroy(mem_ctx);
2767 talloc_destroy(mem_ctx);
2772 /****************************************************************************
2773 ****************************************************************************/
2775 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2776 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2778 union spoolss_PrinterInfo info1, info2;
2780 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2781 SEC_DESC *sd1, *sd2;
2785 printf("Retrieving printer security for %s...", cli1->desthost);
2786 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2791 if ( !W_ERROR_IS_OK(werror) ) {
2792 printf("failed (%s)\n", win_errstr(werror));
2798 printf("Retrieving printer security for %s...", cli2->desthost);
2799 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2804 if ( !W_ERROR_IS_OK(werror) ) {
2805 printf("failed (%s)\n", win_errstr(werror));
2814 sd1 = info1.info3.secdesc;
2815 sd2 = info2.info3.secdesc;
2817 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2818 printf("NULL secdesc!\n");
2823 if (!sec_desc_equal( sd1, sd2 ) ) {
2824 printf("Security Descriptors *not* equal!\n");
2829 printf("Security descriptors match\n");
2832 talloc_destroy(mem_ctx);
2837 /****************************************************************************
2838 ****************************************************************************/
2840 extern struct user_auth_info *rpcclient_auth_info;
2842 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2843 TALLOC_CTX *mem_ctx, int argc,
2846 const char *printername;
2847 char *printername_path = NULL;
2848 struct cli_state *cli_server2 = NULL;
2849 struct rpc_pipe_client *cli2 = NULL;
2850 POLICY_HND hPrinter1, hPrinter2;
2855 printf("Usage: %s <printer> <server>\n", argv[0]);
2859 printername = argv[1];
2861 /* first get the connection to the remote server */
2863 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2866 get_cmdline_auth_info_username(rpcclient_auth_info),
2868 get_cmdline_auth_info_password(rpcclient_auth_info),
2869 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2870 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2872 if ( !NT_STATUS_IS_OK(nt_status) )
2873 return WERR_GENERAL_FAILURE;
2875 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2877 if (!NT_STATUS_IS_OK(nt_status)) {
2878 printf("failed to open spoolss pipe on server %s (%s)\n",
2879 argv[2], nt_errstr(nt_status));
2880 return WERR_GENERAL_FAILURE;
2883 /* now open up both printers */
2885 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2887 printf("Opening %s...", printername_path);
2889 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2893 if ( !W_ERROR_IS_OK(werror) ) {
2894 printf("failed (%s)\n", win_errstr(werror));
2899 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2901 printf("Opening %s...", printername_path);
2902 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2906 if ( !W_ERROR_IS_OK(werror) ) {
2907 printf("failed (%s)\n", win_errstr(werror));
2912 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2913 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2915 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2922 printf("Closing printers...");
2923 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2924 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2927 /* close the second remote connection */
2929 cli_shutdown( cli_server2 );
2933 /* List of commands exported by this module */
2934 struct cmd_set spoolss_commands[] = {
2938 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
2939 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
2940 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
2941 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
2942 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
2943 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
2944 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
2945 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
2946 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
2947 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
2948 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
2949 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
2950 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
2951 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
2952 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
2953 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
2954 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
2955 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
2956 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
2957 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
2958 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
2959 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
2960 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
2961 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
2962 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
2963 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
2964 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
2965 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
2966 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },