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_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->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;
475 const char *printername, *comment = NULL;
477 if (argc == 1 || argc > 3) {
478 printf("Usage: %s printername comment\n", argv[0]);
483 /* Open a printer handle */
488 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
490 /* get a printer handle */
491 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
495 if (!W_ERROR_IS_OK(result))
500 /* Get printer info */
501 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
503 if (!W_ERROR_IS_OK(result))
507 /* Modify the comment. */
508 init_unistr(&ctr.printers_2->comment, comment);
509 ctr.printers_2->devmode = NULL;
510 ctr.printers_2->secdesc = NULL;
512 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
513 if (W_ERROR_IS_OK(result))
514 printf("Success in setting comment.\n");
518 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
523 /****************************************************************************
524 ****************************************************************************/
526 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
528 int argc, const char **argv)
532 uint32 info_level = 2;
533 bool opened_hnd = False;
534 PRINTER_INFO_CTR ctr;
535 const char *printername,
536 *new_printername = NULL;
538 if (argc == 1 || argc > 3) {
539 printf("Usage: %s printername new_printername\n", argv[0]);
544 /* Open a printer handle */
546 new_printername = argv[2];
549 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
551 /* get a printer handle */
552 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
556 if (!W_ERROR_IS_OK(result))
561 /* Get printer info */
562 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
564 if (!W_ERROR_IS_OK(result))
567 /* Modify the printername. */
568 init_unistr(&ctr.printers_2->printername, new_printername);
569 ctr.printers_2->devmode = NULL;
570 ctr.printers_2->secdesc = NULL;
572 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
573 if (W_ERROR_IS_OK(result))
574 printf("Success in setting printername.\n");
578 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
583 /****************************************************************************
584 ****************************************************************************/
586 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
588 int argc, const char **argv)
592 uint32 info_level = 1;
593 bool opened_hnd = False;
594 PRINTER_INFO_CTR ctr;
595 const char *printername;
597 if (argc == 1 || argc > 3) {
598 printf("Usage: %s <printername> [level]\n", argv[0]);
602 /* Open a printer handle */
604 info_level = atoi(argv[2]);
607 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
609 /* get a printer handle */
611 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
613 SEC_FLAG_MAXIMUM_ALLOWED,
615 if (!W_ERROR_IS_OK(result))
620 /* Get printer info */
622 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
624 if (!W_ERROR_IS_OK(result))
627 /* Display printer info */
629 switch (info_level) {
631 display_print_info_0(ctr.printers_0);
634 display_print_info_1(ctr.printers_1);
637 display_print_info_2(ctr.printers_2);
640 display_print_info_3(ctr.printers_3);
643 display_print_info_7(ctr.printers_7);
646 printf("unknown info level %d\n", info_level);
652 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
657 /****************************************************************************
658 ****************************************************************************/
660 static void display_reg_value(REGISTRY_VALUE value)
666 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
667 *((uint32 *) value.data_p));
670 rpcstr_pull_talloc(talloc_tos(),
675 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
678 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
680 printf("%s: REG_BINARY:", value.valuename);
682 for (i=0; i<len; i++) {
683 if (hex[i] == '\0') {
696 uint32 i, num_values;
699 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
700 value.size, &num_values,
702 d_printf("reg_pull_multi_sz failed\n");
706 for (i=0; i<num_values; i++) {
707 d_printf("%s\n", values[i]);
713 printf("%s: unknown type %d\n", value.valuename, value.type);
718 /****************************************************************************
719 ****************************************************************************/
721 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
723 int argc, const char **argv)
727 bool opened_hnd = False;
729 const char *valuename;
730 REGISTRY_VALUE value;
733 printf("Usage: %s <printername> <valuename>\n", argv[0]);
734 printf("<printername> of . queries print server\n");
739 /* Open a printer handle */
741 if (strncmp(argv[1], ".", sizeof(".")) == 0)
742 fstrcpy(printername, cli->srv_name_slash);
744 slprintf(printername, sizeof(printername)-1, "%s\\%s",
745 cli->srv_name_slash, argv[1]);
747 /* get a printer handle */
749 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
751 SEC_FLAG_MAXIMUM_ALLOWED,
753 if (!W_ERROR_IS_OK(result))
758 /* Get printer info */
760 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
762 if (!W_ERROR_IS_OK(result))
765 /* Display printer data */
767 fstrcpy(value.valuename, valuename);
768 display_reg_value(value);
773 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
778 /****************************************************************************
779 ****************************************************************************/
781 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
783 int argc, const char **argv)
788 bool opened_hnd = False;
790 const char *valuename, *keyname;
791 REGISTRY_VALUE value;
794 uint8_t *buffer = NULL;
795 uint32_t offered = 0;
799 printf("Usage: %s <printername> <keyname> <valuename>\n",
801 printf("<printername> of . queries print server\n");
807 /* Open a printer handle */
809 if (strncmp(argv[1], ".", sizeof(".")) == 0)
810 fstrcpy(printername, cli->srv_name_slash);
812 slprintf(printername, sizeof(printername)-1, "%s\\%s",
813 cli->srv_name_slash, argv[1]);
815 /* get a printer handle */
817 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
819 SEC_FLAG_MAXIMUM_ALLOWED,
821 if (!W_ERROR_IS_OK(result))
826 /* Get printer info */
828 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
837 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
839 buffer = talloc_array(mem_ctx, uint8_t, needed);
840 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
851 if (!NT_STATUS_IS_OK(status)) {
855 if (!W_ERROR_IS_OK(result)) {
860 if (!W_ERROR_IS_OK(result))
863 /* Display printer data */
865 fstrcpy(value.valuename, valuename);
868 value.data_p = buffer;
870 display_reg_value(value);
874 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
879 /****************************************************************************
880 ****************************************************************************/
882 static void display_print_driver_1(DRIVER_INFO_1 *i1)
888 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
890 printf ("Printer Driver Info 1:\n");
891 printf ("\tDriver Name: [%s]\n\n", name);
896 /****************************************************************************
897 ****************************************************************************/
899 static void display_print_driver_2(DRIVER_INFO_2 *i1)
902 fstring architecture;
909 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
910 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
911 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
912 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
913 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
915 printf ("Printer Driver Info 2:\n");
916 printf ("\tVersion: [%x]\n", i1->version);
917 printf ("\tDriver Name: [%s]\n", name);
918 printf ("\tArchitecture: [%s]\n", architecture);
919 printf ("\tDriver Path: [%s]\n", driverpath);
920 printf ("\tDatafile: [%s]\n", datafile);
921 printf ("\tConfigfile: [%s]\n\n", configfile);
926 /****************************************************************************
927 ****************************************************************************/
929 static void display_print_driver_3(DRIVER_INFO_3 *i1)
932 fstring architecture = "";
933 fstring driverpath = "";
934 fstring datafile = "";
935 fstring configfile = "";
936 fstring helpfile = "";
937 fstring dependentfiles = "";
938 fstring monitorname = "";
939 fstring defaultdatatype = "";
947 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
948 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
949 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
950 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
951 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
952 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
953 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
954 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
956 printf ("Printer Driver Info 3:\n");
957 printf ("\tVersion: [%x]\n", i1->version);
958 printf ("\tDriver Name: [%s]\n",name);
959 printf ("\tArchitecture: [%s]\n", architecture);
960 printf ("\tDriver Path: [%s]\n", driverpath);
961 printf ("\tDatafile: [%s]\n", datafile);
962 printf ("\tConfigfile: [%s]\n", configfile);
963 printf ("\tHelpfile: [%s]\n\n", helpfile);
967 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
969 length+=strlen(dependentfiles)+1;
971 if (strlen(dependentfiles) > 0)
973 printf ("\tDependentfiles: [%s]\n", dependentfiles);
983 printf ("\tMonitorname: [%s]\n", monitorname);
984 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
989 /****************************************************************************
990 ****************************************************************************/
992 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
994 int argc, const char **argv)
998 uint32 info_level = 3;
999 bool opened_hnd = False;
1000 PRINTER_DRIVER_CTR ctr;
1001 const char *printername;
1003 bool success = False;
1005 if ((argc == 1) || (argc > 3))
1007 printf("Usage: %s <printername> [level]\n", argv[0]);
1011 /* get the arguments need to open the printer handle */
1013 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1016 info_level = atoi(argv[2]);
1018 /* Open a printer handle */
1020 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1024 if (!W_ERROR_IS_OK(werror)) {
1025 printf("Error opening printer handle for %s!\n", printername);
1031 /* loop through and print driver info level for each architecture */
1033 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1035 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1036 archi_table[i].long_archi, archi_table[i].version,
1039 if (!W_ERROR_IS_OK(werror))
1042 /* need at least one success */
1046 printf ("\n[%s]\n", archi_table[i].long_archi);
1048 switch (info_level) {
1050 display_print_driver_1 (ctr.info1);
1053 display_print_driver_2 (ctr.info2);
1056 display_print_driver_3 (ctr.info3);
1059 printf("unknown info level %d\n", info_level);
1067 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1075 /****************************************************************************
1076 ****************************************************************************/
1078 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1079 TALLOC_CTX *mem_ctx,
1080 int argc, const char **argv)
1082 WERROR werror = WERR_OK;
1083 uint32 info_level = 1;
1084 PRINTER_DRIVER_CTR ctr;
1089 printf("Usage: enumdrivers [level]\n");
1094 info_level = atoi(argv[1]);
1097 /* loop through and print driver info level for each architecture */
1098 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1099 /* check to see if we already asked for this architecture string */
1101 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1104 werror = rpccli_spoolss_enumprinterdrivers(
1105 cli, mem_ctx, info_level,
1106 archi_table[i].long_archi, &returned, &ctr);
1108 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1109 printf ("Server does not support environment [%s]\n",
1110 archi_table[i].long_archi);
1118 if (!W_ERROR_IS_OK(werror)) {
1119 printf ("Error getting driver for environment [%s] - %d\n",
1120 archi_table[i].long_archi, W_ERROR_V(werror));
1124 printf ("\n[%s]\n", archi_table[i].long_archi);
1129 for (j=0; j < returned; j++) {
1130 display_print_driver_1 (&ctr.info1[j]);
1134 for (j=0; j < returned; j++) {
1135 display_print_driver_2 (&ctr.info2[j]);
1139 for (j=0; j < returned; j++) {
1140 display_print_driver_3 (&ctr.info3[j]);
1144 printf("unknown info level %d\n", info_level);
1145 return WERR_UNKNOWN_LEVEL;
1152 /****************************************************************************
1153 ****************************************************************************/
1155 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1157 printf("\tDirectory Name:[%s]\n", r->directory_name);
1160 /****************************************************************************
1161 ****************************************************************************/
1163 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1164 TALLOC_CTX *mem_ctx,
1165 int argc, const char **argv)
1169 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1172 union spoolss_DriverDirectoryInfo info;
1176 printf("Usage: %s [environment]\n", argv[0]);
1180 /* Get the arguments need to open the printer handle */
1186 /* Get the directory. Only use Info level 1 */
1188 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1189 cli->srv_name_slash,
1197 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1199 buffer = data_blob_talloc_zero(mem_ctx, needed);
1201 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1202 cli->srv_name_slash,
1212 if (W_ERROR_IS_OK(result)) {
1213 display_printdriverdir_1(&info.info1);
1219 /****************************************************************************
1220 ****************************************************************************/
1222 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1227 for (i=0; archi_table[i].long_archi != NULL; i++)
1229 if (strcmp(arch, archi_table[i].short_archi) == 0)
1231 info->version = archi_table[i].version;
1232 init_unistr (&info->architecture, archi_table[i].long_archi);
1237 if (archi_table[i].long_archi == NULL)
1239 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1246 /**************************************************************************
1247 wrapper for strtok to get the next parameter from a delimited list.
1248 Needed to handle the empty parameter string denoted by "NULL"
1249 *************************************************************************/
1251 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
1256 /* get the next token */
1257 ptr = strtok_r(str, delim, saveptr);
1259 /* a string of 'NULL' is used to represent an empty
1260 parameter because two consecutive delimiters
1261 will not return an empty string. See man strtok(3)
1263 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1267 init_unistr(dest, ptr);
1272 /********************************************************************************
1273 fill in the members of a DRIVER_INFO_3 struct using a character
1274 string in the form of
1275 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1276 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1277 <Default Data Type>:<Comma Separated list of Files>
1278 *******************************************************************************/
1279 static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1284 char *saveptr = NULL;
1286 /* fill in the UNISTR fields */
1287 str = get_driver_3_param (args, ":", &info->name, &saveptr);
1288 str = get_driver_3_param (NULL, ":", &info->driverpath, &saveptr);
1289 str = get_driver_3_param (NULL, ":", &info->datafile, &saveptr);
1290 str = get_driver_3_param (NULL, ":", &info->configfile, &saveptr);
1291 str = get_driver_3_param (NULL, ":", &info->helpfile, &saveptr);
1292 str = get_driver_3_param (NULL, ":", &info->monitorname, &saveptr);
1293 str = get_driver_3_param (NULL, ":", &info->defaultdatatype, &saveptr);
1295 /* <Comma Separated List of Dependent Files> */
1296 /* save the beginning of the string */
1297 str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
1300 /* begin to strip out each filename */
1301 str = strtok_r(str, ",", &saveptr);
1305 /* keep a cumlative count of the str lengths */
1306 len += strlen(str)+1;
1307 str = strtok_r(NULL, ",", &saveptr);
1310 /* allocate the space; add one extra slot for a terminating NULL.
1311 Each filename is NULL terminated and the end contains a double
1313 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1315 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1318 for (i=0; i<len; i++)
1320 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1322 info->dependentfiles[len] = '\0';
1328 /****************************************************************************
1329 ****************************************************************************/
1331 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1332 TALLOC_CTX *mem_ctx,
1333 int argc, const char **argv)
1337 PRINTER_DRIVER_CTR ctr;
1338 DRIVER_INFO_3 info3;
1340 fstring driver_name;
1343 /* parse the command arguments */
1344 if (argc != 3 && argc != 4)
1346 printf ("Usage: %s <Environment> \\\n", argv[0]);
1347 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1348 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1349 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1350 printf ("\t[version]\n");
1355 /* Fill in the DRIVER_INFO_3 struct */
1357 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1359 printf ("Error Unknown architechture [%s]\n", argv[1]);
1360 return WERR_INVALID_PARAM;
1363 set_drv_info_3_env(&info3, arch);
1365 driver_args = talloc_strdup( mem_ctx, argv[2] );
1366 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1368 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1369 return WERR_INVALID_PARAM;
1372 /* if printer driver version specified, override the default version
1373 * used by the architecture. This allows installation of Windows
1374 * 2000 (version 3) printer drivers. */
1377 info3.version = atoi(argv[3]);
1382 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1384 if (W_ERROR_IS_OK(result)) {
1385 rpcstr_pull(driver_name, info3.name.buffer,
1386 sizeof(driver_name), -1, STR_TERMINATE);
1387 printf ("Printer Driver %s successfully installed.\n",
1395 /****************************************************************************
1396 ****************************************************************************/
1398 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1399 TALLOC_CTX *mem_ctx,
1400 int argc, const char **argv)
1404 struct spoolss_SetPrinterInfoCtr info_ctr;
1405 struct spoolss_SetPrinterInfo2 info2;
1406 struct policy_handle handle;
1407 struct spoolss_DevmodeContainer devmode_ctr;
1408 struct sec_desc_buf sd;
1409 struct spoolss_UserLevelCtr userlevel_ctr;
1410 struct spoolss_UserLevel1 level1;
1412 /* parse the command arguments */
1415 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1419 /* Fill in the DRIVER_INFO_2 struct */
1420 ZERO_STRUCT(devmode_ctr);
1424 info2.printername = argv[1];
1425 info2.drivername = argv[3];
1426 info2.sharename = argv[2];
1427 info2.portname = argv[4];
1428 info2.comment = "Created by rpcclient";
1429 info2.printprocessor = "winprint";
1430 info2.datatype = "RAW";
1431 info2.devmode = NULL;
1432 info2.secdesc = NULL;
1433 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1435 info2.defaultpriority = 0;
1436 info2.starttime = 0;
1437 info2.untiltime = 0;
1439 /* These three fields must not be used by AddPrinter()
1440 as defined in the MS Platform SDK documentation..
1444 info2.averageppm = 0;
1448 info_ctr.info.info2 = &info2;
1450 level1.size = 28; /* wild guess */
1451 level1.build = 1381;
1454 level1.processor = 0;
1455 level1.client = global_myname();
1456 level1.user = cli->auth->user_name;
1458 userlevel_ctr.level = 1;
1459 userlevel_ctr.user_info.level1 = &level1;
1461 status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
1462 cli->srv_name_slash,
1469 if (W_ERROR_IS_OK(result))
1470 printf ("Printer %s successfully installed.\n", argv[1]);
1475 /****************************************************************************
1476 ****************************************************************************/
1478 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1479 TALLOC_CTX *mem_ctx,
1480 int argc, const char **argv)
1485 bool opened_hnd = False;
1486 PRINTER_INFO_CTR ctr;
1487 PRINTER_INFO_2 info2;
1488 const char *printername;
1490 /* parse the command arguments */
1493 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1497 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1499 /* Get a printer handle */
1501 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1505 if (!W_ERROR_IS_OK(result))
1510 /* Get printer info */
1512 ZERO_STRUCT (info2);
1513 ctr.printers_2 = &info2;
1515 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1517 if (!W_ERROR_IS_OK(result)) {
1518 printf ("Unable to retrieve printer information!\n");
1522 /* Set the printer driver */
1524 init_unistr(&ctr.printers_2->drivername, argv[2]);
1526 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1528 if (!W_ERROR_IS_OK(result)) {
1529 printf("SetPrinter call failed!\n");
1533 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1539 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1545 /****************************************************************************
1546 ****************************************************************************/
1548 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1549 TALLOC_CTX *mem_ctx,
1550 int argc, const char **argv)
1552 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1558 const char *arch = NULL;
1559 uint32_t delete_flags = 0;
1561 /* parse the command arguments */
1562 if (argc < 2 || argc > 4) {
1563 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1570 vers = atoi (argv[3]);
1573 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1576 /* delete the driver for all architectures */
1577 for (i=0; archi_table[i].long_archi; i++) {
1579 if (arch && !strequal( archi_table[i].long_archi, arch))
1582 if (vers >= 0 && archi_table[i].version != vers)
1585 /* make the call to remove the driver */
1586 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1587 cli->srv_name_slash,
1588 archi_table[i].long_archi,
1591 archi_table[i].version,
1594 if ( !W_ERROR_IS_OK(result) )
1596 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1597 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1598 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1603 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1604 archi_table[i].long_archi, archi_table[i].version);
1613 /****************************************************************************
1614 ****************************************************************************/
1616 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1617 TALLOC_CTX *mem_ctx,
1618 int argc, const char **argv)
1620 WERROR result = WERR_OK;
1624 /* parse the command arguments */
1626 printf ("Usage: %s <driver>\n", argv[0]);
1630 /* delete the driver for all architectures */
1631 for (i=0; archi_table[i].long_archi; i++) {
1632 /* make the call to remove the driver */
1633 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1634 cli->srv_name_slash,
1635 archi_table[i].long_archi,
1638 if (!NT_STATUS_IS_OK(status)) {
1641 if ( !W_ERROR_IS_OK(result) ) {
1642 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1643 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1644 argv[1], archi_table[i].long_archi,
1648 printf ("Driver %s removed for arch [%s].\n", argv[1],
1649 archi_table[i].long_archi);
1656 /****************************************************************************
1657 ****************************************************************************/
1659 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1660 TALLOC_CTX *mem_ctx,
1661 int argc, const char **argv)
1664 char *environment = NULL;
1667 /* parse the command arguments */
1669 printf ("Usage: %s [environment]\n", argv[0]);
1673 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1674 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1678 result = rpccli_spoolss_getprintprocessordirectory(
1679 cli, mem_ctx, cli->srv_name_slash, environment, procdir);
1681 if (W_ERROR_IS_OK(result))
1682 printf("%s\n", procdir);
1684 SAFE_FREE(environment);
1689 /****************************************************************************
1690 ****************************************************************************/
1692 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1693 int argc, const char **argv)
1698 const char *printername;
1699 bool got_handle = False;
1700 union spoolss_AddFormInfo info;
1701 struct spoolss_AddFormInfo1 info1;
1703 /* Parse the command arguments */
1706 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1710 /* Get a printer handle */
1712 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1714 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1718 if (!W_ERROR_IS_OK(werror))
1723 /* Dummy up some values for the form data */
1725 info1.flags = FORM_USER;
1726 info1.form_name = argv[2];
1727 info1.size.width = 100;
1728 info1.size.height = 100;
1729 info1.area.left = 0;
1730 info1.area.top = 10;
1731 info1.area.right = 20;
1732 info1.area.bottom = 30;
1734 info.info1 = &info1;
1739 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1747 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1752 /****************************************************************************
1753 ****************************************************************************/
1755 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1756 int argc, const char **argv)
1761 const char *printername;
1762 bool got_handle = False;
1763 union spoolss_AddFormInfo info;
1764 struct spoolss_AddFormInfo1 info1;
1766 /* Parse the command arguments */
1769 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1773 /* Get a printer handle */
1775 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1777 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1779 SEC_FLAG_MAXIMUM_ALLOWED,
1781 if (!W_ERROR_IS_OK(werror))
1786 /* Dummy up some values for the form data */
1788 info1.flags = FORM_PRINTER;
1789 info1.size.width = 100;
1790 info1.size.height = 100;
1791 info1.area.left = 0;
1792 info1.area.top = 1000;
1793 info1.area.right = 2000;
1794 info1.area.bottom = 3000;
1795 info1.form_name = argv[2];
1797 info.info1 = &info1;
1801 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1810 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1815 /****************************************************************************
1816 ****************************************************************************/
1818 static const char *get_form_flag(int form_flag)
1820 switch (form_flag) {
1824 return "FORM_BUILTIN";
1826 return "FORM_PRINTER";
1832 /****************************************************************************
1833 ****************************************************************************/
1835 static void display_form(FORM_1 *form)
1837 fstring form_name = "";
1839 if (form->name.buffer)
1840 rpcstr_pull(form_name, form->name.buffer,
1841 sizeof(form_name), -1, STR_TERMINATE);
1844 "\tflag: %s (%d)\n" \
1845 "\twidth: %d, length: %d\n" \
1846 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1847 form_name, get_form_flag(form->flag), form->flag,
1848 form->width, form->length,
1849 form->left, form->right,
1850 form->top, form->bottom);
1853 /****************************************************************************
1854 ****************************************************************************/
1856 static void display_form_info1(struct spoolss_FormInfo1 *r)
1859 "\tflag: %s (%d)\n" \
1860 "\twidth: %d, length: %d\n" \
1861 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1862 r->form_name, get_form_flag(r->flags), r->flags,
1863 r->size.width, r->size.height,
1864 r->area.left, r->area.right,
1865 r->area.top, r->area.bottom);
1868 /****************************************************************************
1869 ****************************************************************************/
1871 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1872 int argc, const char **argv)
1877 const char *printername;
1878 bool got_handle = False;
1880 uint32_t offered = 0;
1881 union spoolss_FormInfo info;
1884 /* Parse the command arguments */
1887 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1891 /* Get a printer handle */
1893 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1895 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1897 SEC_FLAG_MAXIMUM_ALLOWED,
1899 if (!W_ERROR_IS_OK(werror))
1906 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1915 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1916 buffer = data_blob_talloc(mem_ctx, NULL, needed);
1918 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1929 if (!NT_STATUS_IS_OK(status)) {
1933 display_form_info1(&info.info1);
1936 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1941 /****************************************************************************
1942 ****************************************************************************/
1944 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1945 TALLOC_CTX *mem_ctx, int argc,
1951 const char *printername;
1952 bool got_handle = False;
1954 /* Parse the command arguments */
1957 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1961 /* Get a printer handle */
1963 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1965 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1967 SEC_FLAG_MAXIMUM_ALLOWED,
1969 if (!W_ERROR_IS_OK(werror))
1974 /* Delete the form */
1976 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
1980 if (!NT_STATUS_IS_OK(status)) {
1981 return ntstatus_to_werror(status);
1986 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1991 /****************************************************************************
1992 ****************************************************************************/
1994 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1995 TALLOC_CTX *mem_ctx, int argc,
2000 const char *printername;
2001 bool got_handle = False;
2002 uint32 num_forms, level = 1, i;
2005 /* Parse the command arguments */
2008 printf ("Usage: %s <printer>\n", argv[0]);
2012 /* Get a printer handle */
2014 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2016 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2018 SEC_FLAG_MAXIMUM_ALLOWED,
2020 if (!W_ERROR_IS_OK(werror))
2025 /* Enumerate forms */
2027 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
2029 if (!W_ERROR_IS_OK(werror))
2032 /* Display output */
2034 for (i = 0; i < num_forms; i++) {
2036 display_form(&forms[i]);
2042 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2047 /****************************************************************************
2048 ****************************************************************************/
2050 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2051 TALLOC_CTX *mem_ctx,
2052 int argc, const char **argv)
2055 const char *printername;
2057 bool opened_hnd = False;
2058 PRINTER_INFO_CTR ctr;
2059 PRINTER_INFO_0 info;
2060 REGISTRY_VALUE value;
2061 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2063 /* parse the command arguments */
2065 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2066 " <value> <data>\n",
2068 result = WERR_INVALID_PARAM;
2072 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2074 value.type = REG_NONE;
2076 if (strequal(argv[2], "string")) {
2077 value.type = REG_SZ;
2080 if (strequal(argv[2], "binary")) {
2081 value.type = REG_BINARY;
2084 if (strequal(argv[2], "dword")) {
2085 value.type = REG_DWORD;
2088 if (strequal(argv[2], "multistring")) {
2089 value.type = REG_MULTI_SZ;
2092 if (value.type == REG_NONE) {
2093 printf("Unknown data type: %s\n", argv[2]);
2094 result = WERR_INVALID_PARAM;
2098 /* get a printer handle */
2100 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2102 SEC_FLAG_MAXIMUM_ALLOWED,
2104 if (!W_ERROR_IS_OK(result))
2109 ctr.printers_0 = &info;
2111 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2113 if (!W_ERROR_IS_OK(result))
2116 printf("%s\n", current_timestring(tmp_ctx, True));
2117 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2119 /* Set the printer data */
2121 fstrcpy(value.valuename, argv[3]);
2123 switch (value.type) {
2126 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2127 value.size = data.uni_str_len * 2;
2129 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2132 value.data_p = NULL;
2137 uint32 data = strtoul(argv[4], NULL, 10);
2138 value.size = sizeof(data);
2140 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2143 value.data_p = NULL;
2148 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2149 value.data_p = data.data;
2150 value.size = data.length;
2153 case REG_MULTI_SZ: {
2158 for (i=4; i<argc; i++) {
2159 if (strcmp(argv[i], "NULL") == 0) {
2162 len += strlen(argv[i])+1;
2166 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2167 if (value.data_p == NULL) {
2168 result = WERR_NOMEM;
2172 p = (char *)value.data_p;
2174 for (i=4; i<argc; i++) {
2175 size_t l = (strlen(argv[i])+1)*2;
2176 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2180 SMB_ASSERT(len == 0);
2184 printf("Unknown data type: %s\n", argv[2]);
2185 result = WERR_INVALID_PARAM;
2189 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2191 if (!W_ERROR_IS_OK(result)) {
2192 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2195 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2197 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2199 if (!W_ERROR_IS_OK(result))
2202 printf("%s\n", current_timestring(tmp_ctx, True));
2203 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2207 TALLOC_FREE(tmp_ctx);
2209 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2214 /****************************************************************************
2215 ****************************************************************************/
2217 static void display_job_info_1(JOB_INFO_1 *job)
2219 fstring username = "", document = "", text_status = "";
2221 rpcstr_pull(username, job->username.buffer,
2222 sizeof(username), -1, STR_TERMINATE);
2224 rpcstr_pull(document, job->document.buffer,
2225 sizeof(document), -1, STR_TERMINATE);
2227 rpcstr_pull(text_status, job->text_status.buffer,
2228 sizeof(text_status), -1, STR_TERMINATE);
2230 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2231 username, document, text_status, job->pagesprinted,
2235 /****************************************************************************
2236 ****************************************************************************/
2238 static void display_job_info_2(JOB_INFO_2 *job)
2240 fstring username = "", document = "", text_status = "";
2242 rpcstr_pull(username, job->username.buffer,
2243 sizeof(username), -1, STR_TERMINATE);
2245 rpcstr_pull(document, job->document.buffer,
2246 sizeof(document), -1, STR_TERMINATE);
2248 rpcstr_pull(text_status, job->text_status.buffer,
2249 sizeof(text_status), -1, STR_TERMINATE);
2251 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2252 username, document, text_status, job->pagesprinted,
2253 job->totalpages, job->size);
2256 /****************************************************************************
2257 ****************************************************************************/
2259 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2260 TALLOC_CTX *mem_ctx, int argc,
2264 uint32 level = 1, num_jobs, i;
2265 bool got_hnd = False;
2266 const char *printername;
2270 if (argc < 2 || argc > 3) {
2271 printf("Usage: %s printername [level]\n", argv[0]);
2276 level = atoi(argv[2]);
2278 /* Open printer handle */
2280 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2282 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2284 SEC_FLAG_MAXIMUM_ALLOWED,
2286 if (!W_ERROR_IS_OK(result))
2291 /* Enumerate ports */
2293 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2296 if (!W_ERROR_IS_OK(result))
2299 for (i = 0; i < num_jobs; i++) {
2302 display_job_info_1(&ctr.job.job_info_1[i]);
2305 display_job_info_2(&ctr.job.job_info_2[i]);
2308 d_printf("unknown info level %d\n", level);
2315 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2320 /****************************************************************************
2321 ****************************************************************************/
2323 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2324 TALLOC_CTX *mem_ctx, int argc,
2328 uint32 i=0, val_needed, data_needed;
2329 bool got_hnd = False;
2330 const char *printername;
2334 printf("Usage: %s printername\n", argv[0]);
2338 /* Open printer handle */
2340 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2342 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2344 SEC_FLAG_MAXIMUM_ALLOWED,
2346 if (!W_ERROR_IS_OK(result))
2351 /* Enumerate data */
2353 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2354 &val_needed, &data_needed,
2356 while (W_ERROR_IS_OK(result)) {
2357 REGISTRY_VALUE value;
2358 result = rpccli_spoolss_enumprinterdata(
2359 cli, mem_ctx, &hnd, i++, val_needed,
2360 data_needed, 0, 0, &value);
2361 if (W_ERROR_IS_OK(result))
2362 display_reg_value(value);
2364 if (W_ERROR_V(result) == ERRnomoreitems)
2365 result = W_ERROR(ERRsuccess);
2369 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2374 /****************************************************************************
2375 ****************************************************************************/
2377 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2378 TALLOC_CTX *mem_ctx, int argc,
2383 bool got_hnd = False;
2384 const char *printername;
2385 const char *keyname = NULL;
2387 REGVAL_CTR *ctr = NULL;
2390 printf("Usage: %s printername <keyname>\n", argv[0]);
2396 /* Open printer handle */
2398 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2400 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2402 SEC_FLAG_MAXIMUM_ALLOWED,
2404 if (!W_ERROR_IS_OK(result))
2409 /* Enumerate subkeys */
2411 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2414 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2416 if (!W_ERROR_IS_OK(result))
2419 for (i=0; i < ctr->num_values; i++) {
2420 display_reg_value(*(ctr->values[i]));
2427 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2432 /****************************************************************************
2433 ****************************************************************************/
2435 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2436 TALLOC_CTX *mem_ctx, int argc,
2440 bool got_hnd = False;
2441 const char *printername;
2442 const char *keyname = NULL;
2444 uint16 *keylist = NULL, *curkey;
2446 if (argc < 2 || argc > 3) {
2447 printf("Usage: %s printername [keyname]\n", argv[0]);
2456 /* Open printer handle */
2458 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2460 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2462 SEC_FLAG_MAXIMUM_ALLOWED,
2464 if (!W_ERROR_IS_OK(result))
2469 /* Enumerate subkeys */
2471 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2473 if (!W_ERROR_IS_OK(result))
2477 while (*curkey != 0) {
2478 char *subkey = NULL;
2479 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2484 printf("%s\n", subkey);
2485 curkey += strlen(subkey) + 1;
2493 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2498 /****************************************************************************
2499 ****************************************************************************/
2501 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2502 TALLOC_CTX *mem_ctx, int argc,
2505 const char *printername;
2507 bool got_hnd = False;
2510 struct spoolss_NotifyOption option;
2513 printf("Usage: %s printername\n", argv[0]);
2520 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2522 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2524 SEC_FLAG_MAXIMUM_ALLOWED,
2526 if (!W_ERROR_IS_OK(result)) {
2527 printf("Error opening %s\n", argv[1]);
2533 /* Create spool options */
2538 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2539 if (option.types == NULL) {
2540 result = WERR_NOMEM;
2544 option.types[0].type = PRINTER_NOTIFY_TYPE;
2545 option.types[0].count = 1;
2546 option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2547 if (option.types[0].fields == NULL) {
2548 result = WERR_NOMEM;
2551 option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2553 option.types[1].type = JOB_NOTIFY_TYPE;
2554 option.types[1].count = 1;
2555 option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2556 if (option.types[1].fields == NULL) {
2557 result = WERR_NOMEM;
2560 option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2564 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2568 cli->srv_name_slash,
2572 if (!W_ERROR_IS_OK(result)) {
2573 printf("Error rffpcnex %s\n", argv[1]);
2579 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2584 /****************************************************************************
2585 ****************************************************************************/
2587 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2588 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2590 PRINTER_INFO_CTR ctr1, ctr2;
2592 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2594 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2595 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2596 if ( !W_ERROR_IS_OK(werror) ) {
2597 printf("failed (%s)\n", win_errstr(werror));
2598 talloc_destroy(mem_ctx);
2603 printf("Retrieving printer properties for %s...", cli2->desthost);
2604 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2605 if ( !W_ERROR_IS_OK(werror) ) {
2606 printf("failed (%s)\n", win_errstr(werror));
2607 talloc_destroy(mem_ctx);
2612 talloc_destroy(mem_ctx);
2617 /****************************************************************************
2618 ****************************************************************************/
2620 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2621 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2623 PRINTER_INFO_CTR ctr1, ctr2;
2625 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2626 SEC_DESC *sd1, *sd2;
2630 printf("Retrieving printer security for %s...", cli1->desthost);
2631 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2632 if ( !W_ERROR_IS_OK(werror) ) {
2633 printf("failed (%s)\n", win_errstr(werror));
2639 printf("Retrieving printer security for %s...", cli2->desthost);
2640 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2641 if ( !W_ERROR_IS_OK(werror) ) {
2642 printf("failed (%s)\n", win_errstr(werror));
2651 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2652 printf("NULL PRINTER_INFO_3!\n");
2657 sd1 = ctr1.printers_3->secdesc;
2658 sd2 = ctr2.printers_3->secdesc;
2660 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2661 printf("NULL secdesc!\n");
2666 if (!sec_desc_equal( sd1, sd2 ) ) {
2667 printf("Security Descriptors *not* equal!\n");
2672 printf("Security descriptors match\n");
2675 talloc_destroy(mem_ctx);
2680 /****************************************************************************
2681 ****************************************************************************/
2683 extern struct user_auth_info *rpcclient_auth_info;
2685 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2686 TALLOC_CTX *mem_ctx, int argc,
2689 const char *printername;
2690 char *printername_path = NULL;
2691 struct cli_state *cli_server2 = NULL;
2692 struct rpc_pipe_client *cli2 = NULL;
2693 POLICY_HND hPrinter1, hPrinter2;
2698 printf("Usage: %s <printer> <server>\n", argv[0]);
2702 printername = argv[1];
2704 /* first get the connection to the remote server */
2706 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2709 get_cmdline_auth_info_username(rpcclient_auth_info),
2711 get_cmdline_auth_info_password(rpcclient_auth_info),
2712 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2713 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2715 if ( !NT_STATUS_IS_OK(nt_status) )
2716 return WERR_GENERAL_FAILURE;
2718 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2720 if (!NT_STATUS_IS_OK(nt_status)) {
2721 printf("failed to open spoolss pipe on server %s (%s)\n",
2722 argv[2], nt_errstr(nt_status));
2723 return WERR_GENERAL_FAILURE;
2726 /* now open up both printers */
2728 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2730 printf("Opening %s...", printername_path);
2732 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2736 if ( !W_ERROR_IS_OK(werror) ) {
2737 printf("failed (%s)\n", win_errstr(werror));
2742 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2744 printf("Opening %s...", printername_path);
2745 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2749 if ( !W_ERROR_IS_OK(werror) ) {
2750 printf("failed (%s)\n", win_errstr(werror));
2755 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2756 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2758 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2765 printf("Closing printers...");
2766 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2767 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2770 /* close the second remote connection */
2772 cli_shutdown( cli_server2 );
2776 /* List of commands exported by this module */
2777 struct cmd_set spoolss_commands[] = {
2781 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
2782 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
2783 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
2784 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
2785 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
2786 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
2787 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
2788 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
2789 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
2790 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
2791 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
2792 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
2793 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
2794 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
2795 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
2796 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
2797 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
2798 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
2799 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
2800 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
2801 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
2802 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
2803 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
2804 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
2805 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
2806 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
2807 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
2808 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
2809 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },