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_info0(struct spoolss_PrinterInfo0 *r)
145 printf("\tprintername:[%s]\n", r->printername);
146 printf("\tservername:[%s]\n", r->servername);
147 printf("\tcjobs:[0x%x]\n", r->cjobs);
148 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
149 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
150 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
151 r->time.day, r->time.day_of_week);
152 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
153 r->time.second, r->time.millisecond);
155 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
156 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
158 printf("\tversion:[0x%x]\n", r->version);
159 printf("\tfree_build:[0x%x]\n", r->free_build);
160 printf("\tspooling:[0x%x]\n", r->spooling);
161 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
162 printf("\tsession_counter:[0x%x]\n", r->session_counter);
163 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
164 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
165 printf("\tjob_error:[0x%x]\n", r->job_error);
166 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
167 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
168 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
169 printf("\tchange_id:[0x%x]\n", r->change_id);
170 printf("\tlast_error: %s\n", win_errstr(r->last_error));
171 printf("\tstatus:[0x%x]\n", r->status);
172 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
173 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
174 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
175 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
176 printf("\tref_ic:[0x%x]\n", r->ref_ic);
177 printf("\treserved2:[0x%x]\n", r->reserved2);
178 printf("\treserved3:[0x%x]\n", r->reserved3);
183 /****************************************************************************
184 ****************************************************************************/
186 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
188 printf("\tflags:[0x%x]\n", r->flags);
189 printf("\tname:[%s]\n", r->name);
190 printf("\tdescription:[%s]\n", r->description);
191 printf("\tcomment:[%s]\n", r->comment);
196 /****************************************************************************
197 ****************************************************************************/
199 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
201 printf("\tservername:[%s]\n", r->servername);
202 printf("\tprintername:[%s]\n", r->printername);
203 printf("\tsharename:[%s]\n", r->sharename);
204 printf("\tportname:[%s]\n", r->portname);
205 printf("\tdrivername:[%s]\n", r->drivername);
206 printf("\tcomment:[%s]\n", r->comment);
207 printf("\tlocation:[%s]\n", r->location);
208 printf("\tsepfile:[%s]\n", r->sepfile);
209 printf("\tprintprocessor:[%s]\n", r->printprocessor);
210 printf("\tdatatype:[%s]\n", r->datatype);
211 printf("\tparameters:[%s]\n", r->parameters);
212 printf("\tattributes:[0x%x]\n", r->attributes);
213 printf("\tpriority:[0x%x]\n", r->priority);
214 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
215 printf("\tstarttime:[0x%x]\n", r->starttime);
216 printf("\tuntiltime:[0x%x]\n", r->untiltime);
217 printf("\tstatus:[0x%x]\n", r->status);
218 printf("\tcjobs:[0x%x]\n", r->cjobs);
219 printf("\taverageppm:[0x%x]\n", r->averageppm);
222 display_sec_desc(r->secdesc);
227 /****************************************************************************
228 ****************************************************************************/
230 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
232 display_sec_desc(r->secdesc);
237 /****************************************************************************
238 ****************************************************************************/
240 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
242 printf("\tguid:[%s]\n", r->guid);
243 printf("\taction:[0x%x]\n", r->action);
247 /****************************************************************************
248 ****************************************************************************/
250 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
252 int argc, const char **argv)
256 union spoolss_PrinterInfo *info;
261 printf("Usage: %s [level] [name]\n", argv[0]);
266 level = atoi(argv[1]);
272 name = cli->srv_name_slash;
275 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
282 if (W_ERROR_IS_OK(result)) {
285 printf ("No printers returned.\n");
289 for (i = 0; i < count; i++) {
292 display_print_info0(&info[i].info0);
295 display_print_info1(&info[i].info1);
298 display_print_info2(&info[i].info2);
301 display_print_info3(&info[i].info3);
304 printf("unknown info level %d\n", level);
314 /****************************************************************************
315 ****************************************************************************/
317 static void display_port_info_1(struct spoolss_PortInfo1 *r)
319 printf("\tPort Name:\t[%s]\n", r->port_name);
322 /****************************************************************************
323 ****************************************************************************/
325 static void display_port_info_2(struct spoolss_PortInfo2 *r)
327 printf("\tPort Name:\t[%s]\n", r->port_name);
328 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
329 printf("\tDescription:\t[%s]\n", r->description);
330 printf("\tPort Type:\t" );
332 int comma = 0; /* hack */
334 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
338 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
339 printf( "%sWrite", comma ? ", " : "" );
342 /* These two have slightly different interpretations
343 on 95/98/ME but I'm disregarding that for now */
344 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
345 printf( "%sRedirected", comma ? ", " : "" );
348 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
349 printf( "%sNet-Attached", comma ? ", " : "" );
353 printf( "[Unset]\n" );
355 printf("\tReserved:\t[%d]\n", r->reserved);
359 /****************************************************************************
360 ****************************************************************************/
362 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
363 TALLOC_CTX *mem_ctx, int argc,
369 union spoolss_PortInfo *info;
372 printf("Usage: %s [level]\n", argv[0]);
377 level = atoi(argv[1]);
380 /* Enumerate ports */
382 result = rpccli_spoolss_enumports(cli, mem_ctx,
388 if (W_ERROR_IS_OK(result)) {
391 for (i = 0; i < count; i++) {
394 display_port_info_1(&info[i].info1);
397 display_port_info_2(&info[i].info2);
400 printf("unknown info level %d\n", level);
409 /****************************************************************************
410 ****************************************************************************/
412 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
414 int argc, const char **argv)
419 uint32 info_level = 2;
420 union spoolss_PrinterInfo info;
421 struct spoolss_SetPrinterInfoCtr info_ctr;
422 const char *printername, *comment = NULL;
423 struct spoolss_DevmodeContainer devmode_ctr;
424 struct sec_desc_buf secdesc_ctr;
426 if (argc == 1 || argc > 3) {
427 printf("Usage: %s printername comment\n", argv[0]);
432 /* Open a printer handle */
437 ZERO_STRUCT(devmode_ctr);
438 ZERO_STRUCT(secdesc_ctr);
440 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
442 /* get a printer handle */
443 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
447 if (!W_ERROR_IS_OK(result))
450 /* Get printer info */
451 result = rpccli_spoolss_getprinter(cli, mem_ctx,
456 if (!W_ERROR_IS_OK(result))
460 /* Modify the comment. */
461 info.info2.comment = comment;
462 info.info2.secdesc = NULL;
463 info.info2.devmode = NULL;
466 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
468 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
475 if (W_ERROR_IS_OK(result))
476 printf("Success in setting comment.\n");
479 if (is_valid_policy_hnd(&pol))
480 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
485 /****************************************************************************
486 ****************************************************************************/
488 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
490 int argc, const char **argv)
495 uint32 info_level = 2;
496 union spoolss_PrinterInfo info;
497 const char *printername,
498 *new_printername = NULL;
499 struct spoolss_SetPrinterInfoCtr info_ctr;
500 struct spoolss_DevmodeContainer devmode_ctr;
501 struct sec_desc_buf secdesc_ctr;
503 ZERO_STRUCT(devmode_ctr);
504 ZERO_STRUCT(secdesc_ctr);
506 if (argc == 1 || argc > 3) {
507 printf("Usage: %s printername new_printername\n", argv[0]);
512 /* Open a printer handle */
514 new_printername = argv[2];
517 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
519 /* get a printer handle */
520 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
524 if (!W_ERROR_IS_OK(result))
527 /* Get printer info */
528 result = rpccli_spoolss_getprinter(cli, mem_ctx,
533 if (!W_ERROR_IS_OK(result))
536 /* Modify the printername. */
537 info.info2.printername = new_printername;
538 info.info2.devmode = NULL;
539 info.info2.secdesc = NULL;
541 info_ctr.level = info_level;
542 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
544 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
551 if (W_ERROR_IS_OK(result))
552 printf("Success in setting printername.\n");
555 if (is_valid_policy_hnd(&pol))
556 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
561 /****************************************************************************
562 ****************************************************************************/
564 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
566 int argc, const char **argv)
571 const char *printername;
572 union spoolss_PrinterInfo info;
574 if (argc == 1 || argc > 3) {
575 printf("Usage: %s <printername> [level]\n", argv[0]);
579 /* Open a printer handle */
581 level = atoi(argv[2]);
584 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
586 /* get a printer handle */
588 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
590 SEC_FLAG_MAXIMUM_ALLOWED,
592 if (!W_ERROR_IS_OK(result)) {
596 /* Get printer info */
598 result = rpccli_spoolss_getprinter(cli, mem_ctx,
603 if (!W_ERROR_IS_OK(result)) {
607 /* Display printer info */
610 display_print_info0(&info.info0);
613 display_print_info1(&info.info1);
616 display_print_info2(&info.info2);
619 display_print_info3(&info.info3);
622 display_print_info7(&info.info7);
625 printf("unknown info level %d\n", level);
629 if (is_valid_policy_hnd(&pol)) {
630 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
636 /****************************************************************************
637 ****************************************************************************/
639 static void display_reg_value(REGISTRY_VALUE value)
645 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
646 *((uint32 *) value.data_p));
649 rpcstr_pull_talloc(talloc_tos(),
654 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
657 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
659 printf("%s: REG_BINARY:", value.valuename);
661 for (i=0; i<len; i++) {
662 if (hex[i] == '\0') {
675 uint32 i, num_values;
678 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
679 value.size, &num_values,
681 d_printf("reg_pull_multi_sz failed\n");
685 for (i=0; i<num_values; i++) {
686 d_printf("%s\n", values[i]);
692 printf("%s: unknown type %d\n", value.valuename, value.type);
697 /****************************************************************************
698 ****************************************************************************/
700 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
702 int argc, const char **argv)
707 const char *valuename;
708 REGISTRY_VALUE value;
711 printf("Usage: %s <printername> <valuename>\n", argv[0]);
712 printf("<printername> of . queries print server\n");
717 /* Open a printer handle */
719 if (strncmp(argv[1], ".", sizeof(".")) == 0)
720 fstrcpy(printername, cli->srv_name_slash);
722 slprintf(printername, sizeof(printername)-1, "%s\\%s",
723 cli->srv_name_slash, argv[1]);
725 /* get a printer handle */
727 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
729 SEC_FLAG_MAXIMUM_ALLOWED,
731 if (!W_ERROR_IS_OK(result))
734 /* Get printer info */
736 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
738 if (!W_ERROR_IS_OK(result))
741 /* Display printer data */
743 fstrcpy(value.valuename, valuename);
744 display_reg_value(value);
748 if (is_valid_policy_hnd(&pol))
749 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
754 /****************************************************************************
755 ****************************************************************************/
757 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
759 int argc, const char **argv)
765 const char *valuename, *keyname;
766 REGISTRY_VALUE value;
769 uint8_t *buffer = NULL;
770 uint32_t offered = 0;
774 printf("Usage: %s <printername> <keyname> <valuename>\n",
776 printf("<printername> of . queries print server\n");
782 /* Open a printer handle */
784 if (strncmp(argv[1], ".", sizeof(".")) == 0)
785 fstrcpy(printername, cli->srv_name_slash);
787 slprintf(printername, sizeof(printername)-1, "%s\\%s",
788 cli->srv_name_slash, argv[1]);
790 /* get a printer handle */
792 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
794 SEC_FLAG_MAXIMUM_ALLOWED,
796 if (!W_ERROR_IS_OK(result))
799 /* Get printer info */
801 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
810 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
812 buffer = talloc_array(mem_ctx, uint8_t, needed);
813 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
824 if (!NT_STATUS_IS_OK(status)) {
828 if (!W_ERROR_IS_OK(result)) {
833 if (!W_ERROR_IS_OK(result))
836 /* Display printer data */
838 fstrcpy(value.valuename, valuename);
841 value.data_p = buffer;
843 display_reg_value(value);
846 if (is_valid_policy_hnd(&pol))
847 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
852 /****************************************************************************
853 ****************************************************************************/
855 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
861 printf("Printer Driver Info 1:\n");
862 printf("\tDriver Name: [%s]\n\n", r->driver_name);
865 /****************************************************************************
866 ****************************************************************************/
868 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
874 printf("Printer Driver Info 2:\n");
875 printf("\tVersion: [%x]\n", r->version);
876 printf("\tDriver Name: [%s]\n", r->driver_name);
877 printf("\tArchitecture: [%s]\n", r->architecture);
878 printf("\tDriver Path: [%s]\n", r->driver_path);
879 printf("\tDatafile: [%s]\n", r->data_file);
880 printf("\tConfigfile: [%s]\n\n", r->config_file);
883 /****************************************************************************
884 ****************************************************************************/
886 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
894 printf("Printer Driver Info 3:\n");
895 printf("\tVersion: [%x]\n", r->version);
896 printf("\tDriver Name: [%s]\n", r->driver_name);
897 printf("\tArchitecture: [%s]\n", r->architecture);
898 printf("\tDriver Path: [%s]\n", r->driver_path);
899 printf("\tDatafile: [%s]\n", r->data_file);
900 printf("\tConfigfile: [%s]\n\n", r->config_file);
901 printf("\tHelpfile: [%s]\n\n", r->help_file);
903 for (i=0; r->dependent_files[i] != NULL; i++) {
904 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
909 printf("\tMonitorname: [%s]\n", r->monitor_name);
910 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
914 /****************************************************************************
915 ****************************************************************************/
917 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
919 int argc, const char **argv)
924 const char *printername;
926 bool success = false;
927 union spoolss_DriverInfo info;
928 uint32_t server_major_version;
929 uint32_t server_minor_version;
931 if ((argc == 1) || (argc > 3)) {
932 printf("Usage: %s <printername> [level]\n", argv[0]);
936 /* get the arguments need to open the printer handle */
938 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
941 level = atoi(argv[2]);
944 /* Open a printer handle */
946 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
950 if (!W_ERROR_IS_OK(werror)) {
951 printf("Error opening printer handle for %s!\n", printername);
955 /* loop through and print driver info level for each architecture */
957 for (i=0; archi_table[i].long_archi!=NULL; i++) {
959 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
961 archi_table[i].long_archi,
964 archi_table[i].version,
967 &server_major_version,
968 &server_minor_version);
969 if (!W_ERROR_IS_OK(werror)) {
973 /* need at least one success */
977 printf("\n[%s]\n", archi_table[i].long_archi);
981 display_print_driver1(&info.info1);
984 display_print_driver2(&info.info2);
987 display_print_driver3(&info.info3);
990 printf("unknown info level %d\n", level);
997 if (is_valid_policy_hnd(&pol)) {
998 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1008 /****************************************************************************
1009 ****************************************************************************/
1011 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1012 TALLOC_CTX *mem_ctx,
1013 int argc, const char **argv)
1015 WERROR werror = WERR_OK;
1017 union spoolss_DriverInfo *info;
1018 uint32_t i, j, count;
1021 printf("Usage: enumdrivers [level]\n");
1026 level = atoi(argv[1]);
1030 /* loop through and print driver info level for each architecture */
1031 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1032 /* check to see if we already asked for this architecture string */
1034 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1038 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1039 cli->srv_name_slash,
1040 archi_table[i].long_archi,
1046 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1047 printf("Server does not support environment [%s]\n",
1048 archi_table[i].long_archi);
1057 if (!W_ERROR_IS_OK(werror)) {
1058 printf("Error getting driver for environment [%s] - %d\n",
1059 archi_table[i].long_archi, W_ERROR_V(werror));
1063 printf("\n[%s]\n", archi_table[i].long_archi);
1067 for (j=0; j < count; j++) {
1068 display_print_driver1(&info[j].info1);
1072 for (j=0; j < count; j++) {
1073 display_print_driver2(&info[j].info2);
1077 for (j=0; j < count; j++) {
1078 display_print_driver3(&info[j].info3);
1082 printf("unknown info level %d\n", level);
1083 return WERR_UNKNOWN_LEVEL;
1090 /****************************************************************************
1091 ****************************************************************************/
1093 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1095 printf("\tDirectory Name:[%s]\n", r->directory_name);
1098 /****************************************************************************
1099 ****************************************************************************/
1101 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1102 TALLOC_CTX *mem_ctx,
1103 int argc, const char **argv)
1107 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1110 union spoolss_DriverDirectoryInfo info;
1114 printf("Usage: %s [environment]\n", argv[0]);
1118 /* Get the arguments need to open the printer handle */
1124 /* Get the directory. Only use Info level 1 */
1126 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1127 cli->srv_name_slash,
1135 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1137 buffer = data_blob_talloc_zero(mem_ctx, needed);
1139 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1140 cli->srv_name_slash,
1150 if (W_ERROR_IS_OK(result)) {
1151 display_printdriverdir_1(&info.info1);
1157 /****************************************************************************
1158 ****************************************************************************/
1160 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1161 struct spoolss_AddDriverInfo3 *info,
1167 for (i=0; archi_table[i].long_archi != NULL; i++)
1169 if (strcmp(arch, archi_table[i].short_archi) == 0)
1171 info->version = archi_table[i].version;
1172 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1177 if (archi_table[i].long_archi == NULL)
1179 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1186 /**************************************************************************
1187 wrapper for strtok to get the next parameter from a delimited list.
1188 Needed to handle the empty parameter string denoted by "NULL"
1189 *************************************************************************/
1191 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1192 const char *delim, const char **dest,
1197 /* get the next token */
1198 ptr = strtok_r(str, delim, saveptr);
1200 /* a string of 'NULL' is used to represent an empty
1201 parameter because two consecutive delimiters
1202 will not return an empty string. See man strtok(3)
1204 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1209 *dest = talloc_strdup(mem_ctx, ptr);
1215 /********************************************************************************
1216 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1217 string in the form of
1218 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1219 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1220 <Default Data Type>:<Comma Separated list of Files>
1221 *******************************************************************************/
1223 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1228 char *saveptr = NULL;
1229 struct spoolss_StringArray *deps;
1230 const char **file_array = NULL;
1233 /* fill in the UNISTR fields */
1234 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1235 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1236 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1237 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1238 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1239 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1240 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1242 /* <Comma Separated List of Dependent Files> */
1243 /* save the beginning of the string */
1244 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1247 /* begin to strip out each filename */
1248 str = strtok_r(str, ",", &saveptr);
1250 /* no dependent files, we are done */
1255 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1260 while (str != NULL) {
1261 add_string_to_array(deps, str, &file_array, &count);
1262 str = strtok_r(NULL, ",", &saveptr);
1265 deps->string = talloc_zero_array(deps, const char *, count + 1);
1266 if (!deps->string) {
1270 for (i=0; i < count; i++) {
1271 deps->string[i] = file_array[i];
1274 r->dependent_files = deps;
1279 /****************************************************************************
1280 ****************************************************************************/
1282 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1283 TALLOC_CTX *mem_ctx,
1284 int argc, const char **argv)
1289 struct spoolss_AddDriverInfoCtr info_ctr;
1290 struct spoolss_AddDriverInfo3 info3;
1294 /* parse the command arguments */
1295 if (argc != 3 && argc != 4)
1297 printf ("Usage: %s <Environment> \\\n", argv[0]);
1298 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1299 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1300 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1301 printf ("\t[version]\n");
1306 /* Fill in the spoolss_AddDriverInfo3 struct */
1309 arch = cmd_spoolss_get_short_archi(argv[1]);
1311 printf ("Error Unknown architechture [%s]\n", argv[1]);
1312 return WERR_INVALID_PARAM;
1315 set_drv_info_3_env(mem_ctx, &info3, arch);
1317 driver_args = talloc_strdup( mem_ctx, argv[2] );
1318 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1320 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1321 return WERR_INVALID_PARAM;
1324 /* if printer driver version specified, override the default version
1325 * used by the architecture. This allows installation of Windows
1326 * 2000 (version 3) printer drivers. */
1329 info3.version = atoi(argv[3]);
1333 info_ctr.level = level;
1334 info_ctr.info.info3 = &info3;
1336 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1337 cli->srv_name_slash,
1340 if (!NT_STATUS_IS_OK(status)) {
1341 return ntstatus_to_werror(status);
1343 if (W_ERROR_IS_OK(result)) {
1344 printf ("Printer Driver %s successfully installed.\n",
1352 /****************************************************************************
1353 ****************************************************************************/
1355 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1356 TALLOC_CTX *mem_ctx,
1357 int argc, const char **argv)
1360 struct spoolss_SetPrinterInfoCtr info_ctr;
1361 struct spoolss_SetPrinterInfo2 info2;
1363 /* parse the command arguments */
1366 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1370 /* Fill in the DRIVER_INFO_2 struct */
1373 info2.printername = argv[1];
1374 info2.drivername = argv[3];
1375 info2.sharename = argv[2];
1376 info2.portname = argv[4];
1377 info2.comment = "Created by rpcclient";
1378 info2.printprocessor = "winprint";
1379 info2.datatype = "RAW";
1380 info2.devmode = NULL;
1381 info2.secdesc = NULL;
1382 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1384 info2.defaultpriority = 0;
1385 info2.starttime = 0;
1386 info2.untiltime = 0;
1388 /* These three fields must not be used by AddPrinter()
1389 as defined in the MS Platform SDK documentation..
1393 info2.averageppm = 0;
1397 info_ctr.info.info2 = &info2;
1399 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1401 if (W_ERROR_IS_OK(result))
1402 printf ("Printer %s successfully installed.\n", argv[1]);
1407 /****************************************************************************
1408 ****************************************************************************/
1410 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1411 TALLOC_CTX *mem_ctx,
1412 int argc, const char **argv)
1418 const char *printername;
1419 union spoolss_PrinterInfo info;
1420 struct spoolss_SetPrinterInfoCtr info_ctr;
1421 struct spoolss_DevmodeContainer devmode_ctr;
1422 struct sec_desc_buf secdesc_ctr;
1424 ZERO_STRUCT(devmode_ctr);
1425 ZERO_STRUCT(secdesc_ctr);
1427 /* parse the command arguments */
1430 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1434 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1436 /* Get a printer handle */
1438 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1442 if (!W_ERROR_IS_OK(result))
1445 /* Get printer info */
1447 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1452 if (!W_ERROR_IS_OK(result)) {
1453 printf ("Unable to retrieve printer information!\n");
1457 /* Set the printer driver */
1459 info.info2.drivername = argv[2];
1460 info.info2.devmode = NULL;
1461 info.info2.secdesc = NULL;
1464 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1466 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1473 if (!W_ERROR_IS_OK(result)) {
1474 printf("SetPrinter call failed!\n");
1478 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1483 if (is_valid_policy_hnd(&pol))
1484 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1490 /****************************************************************************
1491 ****************************************************************************/
1493 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1494 TALLOC_CTX *mem_ctx,
1495 int argc, const char **argv)
1497 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1503 const char *arch = NULL;
1504 uint32_t delete_flags = 0;
1506 /* parse the command arguments */
1507 if (argc < 2 || argc > 4) {
1508 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1515 vers = atoi (argv[3]);
1518 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1521 /* delete the driver for all architectures */
1522 for (i=0; archi_table[i].long_archi; i++) {
1524 if (arch && !strequal( archi_table[i].long_archi, arch))
1527 if (vers >= 0 && archi_table[i].version != vers)
1530 /* make the call to remove the driver */
1531 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1532 cli->srv_name_slash,
1533 archi_table[i].long_archi,
1536 archi_table[i].version,
1539 if ( !W_ERROR_IS_OK(result) )
1541 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1542 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1543 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1548 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1549 archi_table[i].long_archi, archi_table[i].version);
1558 /****************************************************************************
1559 ****************************************************************************/
1561 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1562 TALLOC_CTX *mem_ctx,
1563 int argc, const char **argv)
1565 WERROR result = WERR_OK;
1569 /* parse the command arguments */
1571 printf ("Usage: %s <driver>\n", argv[0]);
1575 /* delete the driver for all architectures */
1576 for (i=0; archi_table[i].long_archi; i++) {
1577 /* make the call to remove the driver */
1578 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1579 cli->srv_name_slash,
1580 archi_table[i].long_archi,
1583 if (!NT_STATUS_IS_OK(status)) {
1586 if ( !W_ERROR_IS_OK(result) ) {
1587 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1588 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1589 argv[1], archi_table[i].long_archi,
1593 printf ("Driver %s removed for arch [%s].\n", argv[1],
1594 archi_table[i].long_archi);
1601 /****************************************************************************
1602 ****************************************************************************/
1604 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1605 TALLOC_CTX *mem_ctx,
1606 int argc, const char **argv)
1610 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1613 union spoolss_PrintProcessorDirectoryInfo info;
1616 /* parse the command arguments */
1618 printf ("Usage: %s [environment]\n", argv[0]);
1623 environment = argv[1];
1626 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1627 cli->srv_name_slash,
1635 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1637 buffer = data_blob_talloc_zero(mem_ctx, needed);
1639 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1640 cli->srv_name_slash,
1650 if (W_ERROR_IS_OK(result)) {
1651 printf("%s\n", info.info1.directory_name);
1657 /****************************************************************************
1658 ****************************************************************************/
1660 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1661 int argc, const char **argv)
1666 const char *printername;
1667 union spoolss_AddFormInfo info;
1668 struct spoolss_AddFormInfo1 info1;
1669 struct spoolss_AddFormInfo2 info2;
1672 /* Parse the command arguments */
1674 if (argc < 3 || argc > 5) {
1675 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1679 /* Get a printer handle */
1681 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1683 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1687 if (!W_ERROR_IS_OK(werror))
1690 /* Dummy up some values for the form data */
1693 level = atoi(argv[3]);
1698 info1.flags = SPOOLSS_FORM_USER;
1699 info1.form_name = argv[2];
1700 info1.size.width = 100;
1701 info1.size.height = 100;
1702 info1.area.left = 0;
1703 info1.area.top = 10;
1704 info1.area.right = 20;
1705 info1.area.bottom = 30;
1707 info.info1 = &info1;
1711 info2.flags = SPOOLSS_FORM_USER;
1712 info2.form_name = argv[2];
1713 info2.size.width = 100;
1714 info2.size.height = 100;
1715 info2.area.left = 0;
1716 info2.area.top = 10;
1717 info2.area.right = 20;
1718 info2.area.bottom = 30;
1719 info2.keyword = argv[2];
1720 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
1721 info2.mui_dll = NULL;
1722 info2.ressource_id = 0;
1723 info2.display_name = argv[2];
1726 info.info2 = &info2;
1734 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1741 if (is_valid_policy_hnd(&handle))
1742 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1747 /****************************************************************************
1748 ****************************************************************************/
1750 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1751 int argc, const char **argv)
1756 const char *printername;
1757 union spoolss_AddFormInfo info;
1758 struct spoolss_AddFormInfo1 info1;
1760 /* Parse the command arguments */
1763 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1767 /* Get a printer handle */
1769 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1771 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1773 SEC_FLAG_MAXIMUM_ALLOWED,
1775 if (!W_ERROR_IS_OK(werror))
1778 /* Dummy up some values for the form data */
1780 info1.flags = SPOOLSS_FORM_PRINTER;
1781 info1.size.width = 100;
1782 info1.size.height = 100;
1783 info1.area.left = 0;
1784 info1.area.top = 1000;
1785 info1.area.right = 2000;
1786 info1.area.bottom = 3000;
1787 info1.form_name = argv[2];
1789 info.info1 = &info1;
1793 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1801 if (is_valid_policy_hnd(&handle))
1802 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1807 /****************************************************************************
1808 ****************************************************************************/
1810 static const char *get_form_flag(int form_flag)
1812 switch (form_flag) {
1813 case SPOOLSS_FORM_USER:
1815 case SPOOLSS_FORM_BUILTIN:
1816 return "FORM_BUILTIN";
1817 case SPOOLSS_FORM_PRINTER:
1818 return "FORM_PRINTER";
1824 /****************************************************************************
1825 ****************************************************************************/
1827 static void display_form_info1(struct spoolss_FormInfo1 *r)
1830 "\tflag: %s (%d)\n" \
1831 "\twidth: %d, length: %d\n" \
1832 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1833 r->form_name, get_form_flag(r->flags), r->flags,
1834 r->size.width, r->size.height,
1835 r->area.left, r->area.right,
1836 r->area.top, r->area.bottom);
1839 /****************************************************************************
1840 ****************************************************************************/
1842 static void display_form_info2(struct spoolss_FormInfo2 *r)
1845 "\tflag: %s (%d)\n" \
1846 "\twidth: %d, length: %d\n" \
1847 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1848 r->form_name, get_form_flag(r->flags), r->flags,
1849 r->size.width, r->size.height,
1850 r->area.left, r->area.right,
1851 r->area.top, r->area.bottom);
1852 printf("\tkeyword: %s\n", r->keyword);
1853 printf("\tstring_type: 0x%08x\n", r->string_type);
1854 printf("\tmui_dll: %s\n", r->mui_dll);
1855 printf("\tressource_id: 0x%08x\n", r->ressource_id);
1856 printf("\tdisplay_name: %s\n", r->display_name);
1857 printf("\tlang_id: %d\n", r->lang_id);
1861 /****************************************************************************
1862 ****************************************************************************/
1864 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1865 int argc, const char **argv)
1870 const char *printername;
1872 uint32_t offered = 0;
1873 union spoolss_FormInfo info;
1877 /* Parse the command arguments */
1879 if (argc < 3 || argc > 5) {
1880 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1884 /* Get a printer handle */
1886 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1888 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1890 SEC_FLAG_MAXIMUM_ALLOWED,
1892 if (!W_ERROR_IS_OK(werror))
1896 level = atoi(argv[3]);
1901 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1910 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1911 buffer = data_blob_talloc_zero(mem_ctx, needed);
1913 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1924 if (!NT_STATUS_IS_OK(status)) {
1930 display_form_info1(&info.info1);
1933 display_form_info2(&info.info2);
1938 if (is_valid_policy_hnd(&handle))
1939 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1944 /****************************************************************************
1945 ****************************************************************************/
1947 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1948 TALLOC_CTX *mem_ctx, int argc,
1954 const char *printername;
1956 /* Parse the command arguments */
1959 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1963 /* Get a printer handle */
1965 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1967 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1969 SEC_FLAG_MAXIMUM_ALLOWED,
1971 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);
1985 if (is_valid_policy_hnd(&handle))
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 uint32 num_forms, level = 1, i;
2002 union spoolss_FormInfo *forms;
2004 /* Parse the command arguments */
2006 if (argc < 2 || argc > 4) {
2007 printf ("Usage: %s <printer> [level]\n", argv[0]);
2011 /* Get a printer handle */
2013 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2015 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2017 SEC_FLAG_MAXIMUM_ALLOWED,
2019 if (!W_ERROR_IS_OK(werror))
2023 level = atoi(argv[2]);
2026 /* Enumerate forms */
2028 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2035 if (!W_ERROR_IS_OK(werror))
2038 /* Display output */
2040 for (i = 0; i < num_forms; i++) {
2043 display_form_info1(&forms[i].info1);
2046 display_form_info2(&forms[i].info2);
2052 if (is_valid_policy_hnd(&handle))
2053 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2058 /****************************************************************************
2059 ****************************************************************************/
2061 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2062 TALLOC_CTX *mem_ctx,
2063 int argc, const char **argv)
2066 const char *printername;
2068 union spoolss_PrinterInfo info;
2069 REGISTRY_VALUE value;
2070 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2072 /* parse the command arguments */
2074 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2075 " <value> <data>\n",
2077 result = WERR_INVALID_PARAM;
2081 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2083 value.type = REG_NONE;
2085 if (strequal(argv[2], "string")) {
2086 value.type = REG_SZ;
2089 if (strequal(argv[2], "binary")) {
2090 value.type = REG_BINARY;
2093 if (strequal(argv[2], "dword")) {
2094 value.type = REG_DWORD;
2097 if (strequal(argv[2], "multistring")) {
2098 value.type = REG_MULTI_SZ;
2101 if (value.type == REG_NONE) {
2102 printf("Unknown data type: %s\n", argv[2]);
2103 result = WERR_INVALID_PARAM;
2107 /* get a printer handle */
2109 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2111 SEC_FLAG_MAXIMUM_ALLOWED,
2113 if (!W_ERROR_IS_OK(result))
2116 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2121 if (!W_ERROR_IS_OK(result))
2124 printf("%s\n", current_timestring(tmp_ctx, True));
2125 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2127 /* Set the printer data */
2129 fstrcpy(value.valuename, argv[3]);
2131 switch (value.type) {
2134 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2135 value.size = data.uni_str_len * 2;
2137 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2140 value.data_p = NULL;
2145 uint32 data = strtoul(argv[4], NULL, 10);
2146 value.size = sizeof(data);
2148 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2151 value.data_p = NULL;
2156 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2157 value.data_p = data.data;
2158 value.size = data.length;
2161 case REG_MULTI_SZ: {
2166 for (i=4; i<argc; i++) {
2167 if (strcmp(argv[i], "NULL") == 0) {
2170 len += strlen(argv[i])+1;
2174 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2175 if (value.data_p == NULL) {
2176 result = WERR_NOMEM;
2180 p = (char *)value.data_p;
2182 for (i=4; i<argc; i++) {
2183 size_t l = (strlen(argv[i])+1)*2;
2184 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2188 SMB_ASSERT(len == 0);
2192 printf("Unknown data type: %s\n", argv[2]);
2193 result = WERR_INVALID_PARAM;
2197 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2199 if (!W_ERROR_IS_OK(result)) {
2200 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2203 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2205 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2210 if (!W_ERROR_IS_OK(result))
2213 printf("%s\n", current_timestring(tmp_ctx, True));
2214 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2218 TALLOC_FREE(tmp_ctx);
2219 if (is_valid_policy_hnd(&pol))
2220 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2225 /****************************************************************************
2226 ****************************************************************************/
2228 static void display_job_info1(struct spoolss_JobInfo1 *r)
2230 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2231 r->user_name, r->document_name, r->text_status, r->pages_printed,
2235 /****************************************************************************
2236 ****************************************************************************/
2238 static void display_job_info2(struct spoolss_JobInfo2 *r)
2240 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2241 r->position, r->job_id,
2242 r->user_name, r->document_name, r->text_status, r->pages_printed,
2243 r->total_pages, r->size);
2246 /****************************************************************************
2247 ****************************************************************************/
2249 static void display_job_info3(struct spoolss_JobInfo3 *r)
2251 printf("jobid[%d], next_jobid[%d]\n",
2252 r->job_id, r->next_job_id);
2255 /****************************************************************************
2256 ****************************************************************************/
2258 static void display_job_info4(struct spoolss_JobInfo4 *r)
2260 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2261 r->position, r->job_id,
2262 r->user_name, r->document_name, r->text_status, r->pages_printed,
2263 r->total_pages, r->size, r->size_high);
2266 /****************************************************************************
2267 ****************************************************************************/
2269 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2270 TALLOC_CTX *mem_ctx, int argc,
2274 uint32_t level = 1, count, i;
2275 const char *printername;
2277 union spoolss_JobInfo *info;
2279 if (argc < 2 || argc > 3) {
2280 printf("Usage: %s printername [level]\n", argv[0]);
2285 level = atoi(argv[2]);
2288 /* Open printer handle */
2290 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2292 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2294 SEC_FLAG_MAXIMUM_ALLOWED,
2296 if (!W_ERROR_IS_OK(result))
2299 /* Enumerate ports */
2301 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2309 if (!W_ERROR_IS_OK(result)) {
2313 for (i = 0; i < count; i++) {
2316 display_job_info1(&info[i].info1);
2319 display_job_info2(&info[i].info2);
2322 d_printf("unknown info level %d\n", level);
2328 if (is_valid_policy_hnd(&hnd)) {
2329 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2335 /****************************************************************************
2336 ****************************************************************************/
2338 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2339 TALLOC_CTX *mem_ctx, int argc,
2343 const char *printername;
2344 struct policy_handle hnd;
2347 union spoolss_JobInfo info;
2349 if (argc < 3 || argc > 4) {
2350 printf("Usage: %s printername job_id [level]\n", argv[0]);
2354 job_id = atoi(argv[2]);
2357 level = atoi(argv[3]);
2360 /* Open printer handle */
2362 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2364 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2366 SEC_FLAG_MAXIMUM_ALLOWED,
2368 if (!W_ERROR_IS_OK(result)) {
2372 /* Enumerate ports */
2374 result = rpccli_spoolss_getjob(cli, mem_ctx,
2381 if (!W_ERROR_IS_OK(result)) {
2387 display_job_info1(&info.info1);
2390 display_job_info2(&info.info2);
2393 display_job_info3(&info.info3);
2396 display_job_info4(&info.info4);
2399 d_printf("unknown info level %d\n", level);
2404 if (is_valid_policy_hnd(&hnd)) {
2405 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2412 /****************************************************************************
2413 ****************************************************************************/
2415 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2416 TALLOC_CTX *mem_ctx, int argc,
2420 uint32 i=0, val_needed, data_needed;
2421 const char *printername;
2425 printf("Usage: %s printername\n", argv[0]);
2429 /* Open printer handle */
2431 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2433 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2435 SEC_FLAG_MAXIMUM_ALLOWED,
2437 if (!W_ERROR_IS_OK(result))
2440 /* Enumerate data */
2442 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2443 &val_needed, &data_needed,
2445 while (W_ERROR_IS_OK(result)) {
2446 REGISTRY_VALUE value;
2447 result = rpccli_spoolss_enumprinterdata(
2448 cli, mem_ctx, &hnd, i++, val_needed,
2449 data_needed, 0, 0, &value);
2450 if (W_ERROR_IS_OK(result))
2451 display_reg_value(value);
2453 if (W_ERROR_V(result) == ERRnomoreitems)
2454 result = W_ERROR(ERRsuccess);
2457 if (is_valid_policy_hnd(&hnd))
2458 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2463 /****************************************************************************
2464 ****************************************************************************/
2466 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2467 TALLOC_CTX *mem_ctx, int argc,
2472 const char *printername;
2473 const char *keyname = NULL;
2475 REGVAL_CTR *ctr = NULL;
2478 printf("Usage: %s printername <keyname>\n", argv[0]);
2484 /* Open printer handle */
2486 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2488 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2490 SEC_FLAG_MAXIMUM_ALLOWED,
2492 if (!W_ERROR_IS_OK(result))
2495 /* Enumerate subkeys */
2497 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2500 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2502 if (!W_ERROR_IS_OK(result))
2505 for (i=0; i < ctr->num_values; i++) {
2506 display_reg_value(*(ctr->values[i]));
2512 if (is_valid_policy_hnd(&hnd))
2513 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2518 /****************************************************************************
2519 ****************************************************************************/
2521 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2522 TALLOC_CTX *mem_ctx, int argc,
2526 const char *printername;
2527 const char *keyname = NULL;
2529 uint16 *keylist = NULL, *curkey;
2531 if (argc < 2 || argc > 3) {
2532 printf("Usage: %s printername [keyname]\n", argv[0]);
2541 /* Open printer handle */
2543 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2545 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2547 SEC_FLAG_MAXIMUM_ALLOWED,
2549 if (!W_ERROR_IS_OK(result))
2552 /* Enumerate subkeys */
2554 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2556 if (!W_ERROR_IS_OK(result))
2560 while (*curkey != 0) {
2561 char *subkey = NULL;
2562 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2567 printf("%s\n", subkey);
2568 curkey += strlen(subkey) + 1;
2575 if (is_valid_policy_hnd(&hnd))
2576 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2581 /****************************************************************************
2582 ****************************************************************************/
2584 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2585 TALLOC_CTX *mem_ctx, int argc,
2588 const char *printername;
2589 const char *clientname;
2593 struct spoolss_NotifyOption option;
2596 printf("Usage: %s printername\n", argv[0]);
2603 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2605 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2607 SEC_FLAG_MAXIMUM_ALLOWED,
2609 if (!W_ERROR_IS_OK(result)) {
2610 printf("Error opening %s\n", argv[1]);
2614 /* Create spool options */
2619 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2620 if (option.types == NULL) {
2621 result = WERR_NOMEM;
2625 option.types[0].type = PRINTER_NOTIFY_TYPE;
2626 option.types[0].count = 1;
2627 option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2628 if (option.types[0].fields == NULL) {
2629 result = WERR_NOMEM;
2632 option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2634 option.types[1].type = JOB_NOTIFY_TYPE;
2635 option.types[1].count = 1;
2636 option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2637 if (option.types[1].fields == NULL) {
2638 result = WERR_NOMEM;
2641 option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2643 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2645 result = WERR_NOMEM;
2651 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2659 if (!W_ERROR_IS_OK(result)) {
2660 printf("Error rffpcnex %s\n", argv[1]);
2665 if (is_valid_policy_hnd(&hnd))
2666 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2671 /****************************************************************************
2672 ****************************************************************************/
2674 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2675 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2677 union spoolss_PrinterInfo info1, info2;
2679 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2681 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2682 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2687 if ( !W_ERROR_IS_OK(werror) ) {
2688 printf("failed (%s)\n", win_errstr(werror));
2689 talloc_destroy(mem_ctx);
2694 printf("Retrieving printer properties for %s...", cli2->desthost);
2695 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2700 if ( !W_ERROR_IS_OK(werror) ) {
2701 printf("failed (%s)\n", win_errstr(werror));
2702 talloc_destroy(mem_ctx);
2707 talloc_destroy(mem_ctx);
2712 /****************************************************************************
2713 ****************************************************************************/
2715 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2716 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2718 union spoolss_PrinterInfo info1, info2;
2720 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2721 SEC_DESC *sd1, *sd2;
2725 printf("Retrieving printer security for %s...", cli1->desthost);
2726 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2731 if ( !W_ERROR_IS_OK(werror) ) {
2732 printf("failed (%s)\n", win_errstr(werror));
2738 printf("Retrieving printer security for %s...", cli2->desthost);
2739 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2744 if ( !W_ERROR_IS_OK(werror) ) {
2745 printf("failed (%s)\n", win_errstr(werror));
2754 sd1 = info1.info3.secdesc;
2755 sd2 = info2.info3.secdesc;
2757 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2758 printf("NULL secdesc!\n");
2763 if (!sec_desc_equal( sd1, sd2 ) ) {
2764 printf("Security Descriptors *not* equal!\n");
2769 printf("Security descriptors match\n");
2772 talloc_destroy(mem_ctx);
2777 /****************************************************************************
2778 ****************************************************************************/
2780 extern struct user_auth_info *rpcclient_auth_info;
2782 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2783 TALLOC_CTX *mem_ctx, int argc,
2786 const char *printername;
2787 char *printername_path = NULL;
2788 struct cli_state *cli_server2 = NULL;
2789 struct rpc_pipe_client *cli2 = NULL;
2790 POLICY_HND hPrinter1, hPrinter2;
2795 printf("Usage: %s <printer> <server>\n", argv[0]);
2799 printername = argv[1];
2801 /* first get the connection to the remote server */
2803 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2806 get_cmdline_auth_info_username(rpcclient_auth_info),
2808 get_cmdline_auth_info_password(rpcclient_auth_info),
2809 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2810 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2812 if ( !NT_STATUS_IS_OK(nt_status) )
2813 return WERR_GENERAL_FAILURE;
2815 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2817 if (!NT_STATUS_IS_OK(nt_status)) {
2818 printf("failed to open spoolss pipe on server %s (%s)\n",
2819 argv[2], nt_errstr(nt_status));
2820 return WERR_GENERAL_FAILURE;
2823 /* now open up both printers */
2825 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2827 printf("Opening %s...", printername_path);
2829 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2833 if ( !W_ERROR_IS_OK(werror) ) {
2834 printf("failed (%s)\n", win_errstr(werror));
2839 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2841 printf("Opening %s...", printername_path);
2842 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2846 if ( !W_ERROR_IS_OK(werror) ) {
2847 printf("failed (%s)\n", win_errstr(werror));
2852 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2853 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2855 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2862 printf("Closing printers...");
2863 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2864 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2867 /* close the second remote connection */
2869 cli_shutdown( cli_server2 );
2873 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
2875 printf("print_processor_name: %s\n", r->print_processor_name);
2878 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
2879 TALLOC_CTX *mem_ctx, int argc,
2883 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2884 uint32_t num_procs, level = 1, i;
2885 union spoolss_PrintProcessorInfo *procs;
2887 /* Parse the command arguments */
2889 if (argc < 1 || argc > 4) {
2890 printf ("Usage: %s [environment] [level]\n", argv[0]);
2895 environment = argv[1];
2899 level = atoi(argv[2]);
2902 /* Enumerate Print Processors */
2904 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
2905 cli->srv_name_slash,
2911 if (!W_ERROR_IS_OK(werror))
2914 /* Display output */
2916 for (i = 0; i < num_procs; i++) {
2919 display_proc_info1(&procs[i].info1);
2928 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
2930 printf("name_array: %s\n", r->name_array);
2933 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
2934 TALLOC_CTX *mem_ctx, int argc,
2938 const char *print_processor_name = "winprint";
2939 uint32_t num_procs, level = 1, i;
2940 union spoolss_PrintProcDataTypesInfo *procs;
2942 /* Parse the command arguments */
2944 if (argc < 1 || argc > 4) {
2945 printf ("Usage: %s [environment] [level]\n", argv[0]);
2950 print_processor_name = argv[1];
2954 level = atoi(argv[2]);
2957 /* Enumerate Print Processor Data Types */
2959 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
2960 cli->srv_name_slash,
2961 print_processor_name,
2966 if (!W_ERROR_IS_OK(werror))
2969 /* Display output */
2971 for (i = 0; i < num_procs; i++) {
2974 display_proc_data_types_info1(&procs[i].info1);
2983 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
2985 printf("monitor_name: %s\n", r->monitor_name);
2988 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
2990 printf("monitor_name: %s\n", r->monitor_name);
2991 printf("environment: %s\n", r->environment);
2992 printf("dll_name: %s\n", r->dll_name);
2995 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
2996 TALLOC_CTX *mem_ctx, int argc,
3000 uint32_t count, level = 1, i;
3001 union spoolss_MonitorInfo *info;
3003 /* Parse the command arguments */
3006 printf("Usage: %s [level]\n", argv[0]);
3011 level = atoi(argv[1]);
3014 /* Enumerate Print Monitors */
3016 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3017 cli->srv_name_slash,
3022 if (!W_ERROR_IS_OK(werror)) {
3026 /* Display output */
3028 for (i = 0; i < count; i++) {
3031 display_monitor1(&info[i].info1);
3034 display_monitor2(&info[i].info2);
3043 /* List of commands exported by this module */
3044 struct cmd_set spoolss_commands[] = {
3048 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
3049 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
3050 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
3051 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
3052 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
3053 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
3054 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
3055 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
3056 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &syntax_spoolss, NULL, "Get print job", "" },
3057 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
3058 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
3059 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
3060 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
3061 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
3062 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
3063 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
3064 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
3065 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
3066 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
3067 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
3068 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
3069 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
3070 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
3071 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
3072 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
3073 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
3074 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
3075 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
3076 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
3077 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },
3078 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &syntax_spoolss, NULL, "Enumerate Print Processors", "" },
3079 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &syntax_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3080 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &syntax_spoolss, NULL, "Enumerate Print Monitors", "" },