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 void display_printer_data(const char *v,
701 enum winreg_Type type,
702 union spoolss_PrinterData *r)
708 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
711 printf("%s: REG_SZ: %s\n", v, r->string);
714 char *hex = hex_encode_talloc(NULL,
715 r->binary.data, r->binary.length);
717 printf("%s: REG_BINARY:", v);
719 for (i=0; i<len; i++) {
720 if (hex[i] == '\0') {
733 printf("%s: REG_MULTI_SZ: ", v);
734 for (i=0; r->string_array[i] != NULL; i++) {
735 printf("%s ", r->string_array[i]);
740 printf("%s: unknown type 0x%02x:\n", v, type);
745 /****************************************************************************
746 ****************************************************************************/
748 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
750 int argc, const char **argv)
755 const char *valuename;
756 enum winreg_Type type;
757 union spoolss_PrinterData data;
760 printf("Usage: %s <printername> <valuename>\n", argv[0]);
761 printf("<printername> of . queries print server\n");
766 /* Open a printer handle */
768 if (strncmp(argv[1], ".", sizeof(".")) == 0)
769 fstrcpy(printername, cli->srv_name_slash);
771 slprintf(printername, sizeof(printername)-1, "%s\\%s",
772 cli->srv_name_slash, argv[1]);
774 /* get a printer handle */
776 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
778 SEC_FLAG_MAXIMUM_ALLOWED,
780 if (!W_ERROR_IS_OK(result))
783 /* Get printer info */
785 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
791 if (!W_ERROR_IS_OK(result))
794 /* Display printer data */
796 display_printer_data(valuename, type, &data);
799 if (is_valid_policy_hnd(&pol))
800 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
805 /****************************************************************************
806 ****************************************************************************/
808 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
810 int argc, const char **argv)
816 const char *valuename, *keyname;
817 REGISTRY_VALUE value;
819 enum winreg_Type type;
820 uint8_t *buffer = NULL;
821 uint32_t offered = 0;
825 printf("Usage: %s <printername> <keyname> <valuename>\n",
827 printf("<printername> of . queries print server\n");
833 /* Open a printer handle */
835 if (strncmp(argv[1], ".", sizeof(".")) == 0)
836 fstrcpy(printername, cli->srv_name_slash);
838 slprintf(printername, sizeof(printername)-1, "%s\\%s",
839 cli->srv_name_slash, argv[1]);
841 /* get a printer handle */
843 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
845 SEC_FLAG_MAXIMUM_ALLOWED,
847 if (!W_ERROR_IS_OK(result))
850 /* Get printer info */
852 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
861 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
863 buffer = talloc_array(mem_ctx, uint8_t, needed);
864 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
875 if (!NT_STATUS_IS_OK(status)) {
879 if (!W_ERROR_IS_OK(result)) {
884 if (!W_ERROR_IS_OK(result))
887 /* Display printer data */
889 fstrcpy(value.valuename, valuename);
892 value.data_p = buffer;
894 display_reg_value(value);
897 if (is_valid_policy_hnd(&pol))
898 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
903 /****************************************************************************
904 ****************************************************************************/
906 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
912 printf("Printer Driver Info 1:\n");
913 printf("\tDriver Name: [%s]\n\n", r->driver_name);
916 /****************************************************************************
917 ****************************************************************************/
919 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
925 printf("Printer Driver Info 2:\n");
926 printf("\tVersion: [%x]\n", r->version);
927 printf("\tDriver Name: [%s]\n", r->driver_name);
928 printf("\tArchitecture: [%s]\n", r->architecture);
929 printf("\tDriver Path: [%s]\n", r->driver_path);
930 printf("\tDatafile: [%s]\n", r->data_file);
931 printf("\tConfigfile: [%s]\n\n", r->config_file);
934 /****************************************************************************
935 ****************************************************************************/
937 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
945 printf("Printer Driver Info 3:\n");
946 printf("\tVersion: [%x]\n", r->version);
947 printf("\tDriver Name: [%s]\n", r->driver_name);
948 printf("\tArchitecture: [%s]\n", r->architecture);
949 printf("\tDriver Path: [%s]\n", r->driver_path);
950 printf("\tDatafile: [%s]\n", r->data_file);
951 printf("\tConfigfile: [%s]\n\n", r->config_file);
952 printf("\tHelpfile: [%s]\n\n", r->help_file);
954 for (i=0; r->dependent_files[i] != NULL; i++) {
955 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
960 printf("\tMonitorname: [%s]\n", r->monitor_name);
961 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
965 /****************************************************************************
966 ****************************************************************************/
968 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
970 int argc, const char **argv)
975 const char *printername;
977 bool success = false;
978 union spoolss_DriverInfo info;
979 uint32_t server_major_version;
980 uint32_t server_minor_version;
982 if ((argc == 1) || (argc > 3)) {
983 printf("Usage: %s <printername> [level]\n", argv[0]);
987 /* get the arguments need to open the printer handle */
989 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
992 level = atoi(argv[2]);
995 /* Open a printer handle */
997 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1001 if (!W_ERROR_IS_OK(werror)) {
1002 printf("Error opening printer handle for %s!\n", printername);
1006 /* loop through and print driver info level for each architecture */
1008 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1010 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1012 archi_table[i].long_archi,
1015 archi_table[i].version,
1018 &server_major_version,
1019 &server_minor_version);
1020 if (!W_ERROR_IS_OK(werror)) {
1024 /* need at least one success */
1028 printf("\n[%s]\n", archi_table[i].long_archi);
1032 display_print_driver1(&info.info1);
1035 display_print_driver2(&info.info2);
1038 display_print_driver3(&info.info3);
1041 printf("unknown info level %d\n", level);
1048 if (is_valid_policy_hnd(&pol)) {
1049 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1059 /****************************************************************************
1060 ****************************************************************************/
1062 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1063 TALLOC_CTX *mem_ctx,
1064 int argc, const char **argv)
1066 WERROR werror = WERR_OK;
1068 union spoolss_DriverInfo *info;
1069 uint32_t i, j, count;
1072 printf("Usage: enumdrivers [level]\n");
1077 level = atoi(argv[1]);
1081 /* loop through and print driver info level for each architecture */
1082 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1083 /* check to see if we already asked for this architecture string */
1085 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1089 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1090 cli->srv_name_slash,
1091 archi_table[i].long_archi,
1097 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1098 printf("Server does not support environment [%s]\n",
1099 archi_table[i].long_archi);
1108 if (!W_ERROR_IS_OK(werror)) {
1109 printf("Error getting driver for environment [%s] - %d\n",
1110 archi_table[i].long_archi, W_ERROR_V(werror));
1114 printf("\n[%s]\n", archi_table[i].long_archi);
1118 for (j=0; j < count; j++) {
1119 display_print_driver1(&info[j].info1);
1123 for (j=0; j < count; j++) {
1124 display_print_driver2(&info[j].info2);
1128 for (j=0; j < count; j++) {
1129 display_print_driver3(&info[j].info3);
1133 printf("unknown info level %d\n", level);
1134 return WERR_UNKNOWN_LEVEL;
1141 /****************************************************************************
1142 ****************************************************************************/
1144 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1146 printf("\tDirectory Name:[%s]\n", r->directory_name);
1149 /****************************************************************************
1150 ****************************************************************************/
1152 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1153 TALLOC_CTX *mem_ctx,
1154 int argc, const char **argv)
1158 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1161 union spoolss_DriverDirectoryInfo info;
1165 printf("Usage: %s [environment]\n", argv[0]);
1169 /* Get the arguments need to open the printer handle */
1175 /* Get the directory. Only use Info level 1 */
1177 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1178 cli->srv_name_slash,
1186 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1188 buffer = data_blob_talloc_zero(mem_ctx, needed);
1190 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1191 cli->srv_name_slash,
1201 if (W_ERROR_IS_OK(result)) {
1202 display_printdriverdir_1(&info.info1);
1208 /****************************************************************************
1209 ****************************************************************************/
1211 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1212 struct spoolss_AddDriverInfo3 *info,
1218 for (i=0; archi_table[i].long_archi != NULL; i++)
1220 if (strcmp(arch, archi_table[i].short_archi) == 0)
1222 info->version = archi_table[i].version;
1223 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1228 if (archi_table[i].long_archi == NULL)
1230 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1237 /**************************************************************************
1238 wrapper for strtok to get the next parameter from a delimited list.
1239 Needed to handle the empty parameter string denoted by "NULL"
1240 *************************************************************************/
1242 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1243 const char *delim, const char **dest,
1248 /* get the next token */
1249 ptr = strtok_r(str, delim, saveptr);
1251 /* a string of 'NULL' is used to represent an empty
1252 parameter because two consecutive delimiters
1253 will not return an empty string. See man strtok(3)
1255 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1260 *dest = talloc_strdup(mem_ctx, ptr);
1266 /********************************************************************************
1267 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1268 string in the form of
1269 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1270 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1271 <Default Data Type>:<Comma Separated list of Files>
1272 *******************************************************************************/
1274 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1279 char *saveptr = NULL;
1280 struct spoolss_StringArray *deps;
1281 const char **file_array = NULL;
1284 /* fill in the UNISTR fields */
1285 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1286 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1287 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1288 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1289 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1290 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1291 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1293 /* <Comma Separated List of Dependent Files> */
1294 /* save the beginning of the string */
1295 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1298 /* begin to strip out each filename */
1299 str = strtok_r(str, ",", &saveptr);
1301 /* no dependent files, we are done */
1306 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1311 while (str != NULL) {
1312 add_string_to_array(deps, str, &file_array, &count);
1313 str = strtok_r(NULL, ",", &saveptr);
1316 deps->string = talloc_zero_array(deps, const char *, count + 1);
1317 if (!deps->string) {
1321 for (i=0; i < count; i++) {
1322 deps->string[i] = file_array[i];
1325 r->dependent_files = deps;
1330 /****************************************************************************
1331 ****************************************************************************/
1333 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1334 TALLOC_CTX *mem_ctx,
1335 int argc, const char **argv)
1340 struct spoolss_AddDriverInfoCtr info_ctr;
1341 struct spoolss_AddDriverInfo3 info3;
1345 /* parse the command arguments */
1346 if (argc != 3 && argc != 4)
1348 printf ("Usage: %s <Environment> \\\n", argv[0]);
1349 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1350 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1351 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1352 printf ("\t[version]\n");
1357 /* Fill in the spoolss_AddDriverInfo3 struct */
1360 arch = cmd_spoolss_get_short_archi(argv[1]);
1362 printf ("Error Unknown architechture [%s]\n", argv[1]);
1363 return WERR_INVALID_PARAM;
1366 set_drv_info_3_env(mem_ctx, &info3, arch);
1368 driver_args = talloc_strdup( mem_ctx, argv[2] );
1369 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1371 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1372 return WERR_INVALID_PARAM;
1375 /* if printer driver version specified, override the default version
1376 * used by the architecture. This allows installation of Windows
1377 * 2000 (version 3) printer drivers. */
1380 info3.version = atoi(argv[3]);
1384 info_ctr.level = level;
1385 info_ctr.info.info3 = &info3;
1387 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1388 cli->srv_name_slash,
1391 if (!NT_STATUS_IS_OK(status)) {
1392 return ntstatus_to_werror(status);
1394 if (W_ERROR_IS_OK(result)) {
1395 printf ("Printer Driver %s successfully installed.\n",
1403 /****************************************************************************
1404 ****************************************************************************/
1406 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1407 TALLOC_CTX *mem_ctx,
1408 int argc, const char **argv)
1411 struct spoolss_SetPrinterInfoCtr info_ctr;
1412 struct spoolss_SetPrinterInfo2 info2;
1414 /* parse the command arguments */
1417 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1421 /* Fill in the DRIVER_INFO_2 struct */
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 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1452 if (W_ERROR_IS_OK(result))
1453 printf ("Printer %s successfully installed.\n", argv[1]);
1458 /****************************************************************************
1459 ****************************************************************************/
1461 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1462 TALLOC_CTX *mem_ctx,
1463 int argc, const char **argv)
1469 const char *printername;
1470 union spoolss_PrinterInfo info;
1471 struct spoolss_SetPrinterInfoCtr info_ctr;
1472 struct spoolss_DevmodeContainer devmode_ctr;
1473 struct sec_desc_buf secdesc_ctr;
1475 ZERO_STRUCT(devmode_ctr);
1476 ZERO_STRUCT(secdesc_ctr);
1478 /* parse the command arguments */
1481 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1485 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1487 /* Get a printer handle */
1489 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1493 if (!W_ERROR_IS_OK(result))
1496 /* Get printer info */
1498 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1503 if (!W_ERROR_IS_OK(result)) {
1504 printf ("Unable to retrieve printer information!\n");
1508 /* Set the printer driver */
1510 info.info2.drivername = argv[2];
1511 info.info2.devmode = NULL;
1512 info.info2.secdesc = NULL;
1515 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1517 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1524 if (!W_ERROR_IS_OK(result)) {
1525 printf("SetPrinter call failed!\n");
1529 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1534 if (is_valid_policy_hnd(&pol))
1535 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1541 /****************************************************************************
1542 ****************************************************************************/
1544 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1545 TALLOC_CTX *mem_ctx,
1546 int argc, const char **argv)
1548 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1554 const char *arch = NULL;
1555 uint32_t delete_flags = 0;
1557 /* parse the command arguments */
1558 if (argc < 2 || argc > 4) {
1559 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1566 vers = atoi (argv[3]);
1569 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1572 /* delete the driver for all architectures */
1573 for (i=0; archi_table[i].long_archi; i++) {
1575 if (arch && !strequal( archi_table[i].long_archi, arch))
1578 if (vers >= 0 && archi_table[i].version != vers)
1581 /* make the call to remove the driver */
1582 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1583 cli->srv_name_slash,
1584 archi_table[i].long_archi,
1587 archi_table[i].version,
1590 if ( !W_ERROR_IS_OK(result) )
1592 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1593 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1594 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1599 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1600 archi_table[i].long_archi, archi_table[i].version);
1609 /****************************************************************************
1610 ****************************************************************************/
1612 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1613 TALLOC_CTX *mem_ctx,
1614 int argc, const char **argv)
1616 WERROR result = WERR_OK;
1620 /* parse the command arguments */
1622 printf ("Usage: %s <driver>\n", argv[0]);
1626 /* delete the driver for all architectures */
1627 for (i=0; archi_table[i].long_archi; i++) {
1628 /* make the call to remove the driver */
1629 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1630 cli->srv_name_slash,
1631 archi_table[i].long_archi,
1634 if (!NT_STATUS_IS_OK(status)) {
1637 if ( !W_ERROR_IS_OK(result) ) {
1638 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1639 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1640 argv[1], archi_table[i].long_archi,
1644 printf ("Driver %s removed for arch [%s].\n", argv[1],
1645 archi_table[i].long_archi);
1652 /****************************************************************************
1653 ****************************************************************************/
1655 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1656 TALLOC_CTX *mem_ctx,
1657 int argc, const char **argv)
1661 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1664 union spoolss_PrintProcessorDirectoryInfo info;
1667 /* parse the command arguments */
1669 printf ("Usage: %s [environment]\n", argv[0]);
1674 environment = argv[1];
1677 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1678 cli->srv_name_slash,
1686 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1688 buffer = data_blob_talloc_zero(mem_ctx, needed);
1690 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1691 cli->srv_name_slash,
1701 if (W_ERROR_IS_OK(result)) {
1702 printf("%s\n", info.info1.directory_name);
1708 /****************************************************************************
1709 ****************************************************************************/
1711 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1712 int argc, const char **argv)
1717 const char *printername;
1718 union spoolss_AddFormInfo info;
1719 struct spoolss_AddFormInfo1 info1;
1720 struct spoolss_AddFormInfo2 info2;
1723 /* Parse the command arguments */
1725 if (argc < 3 || argc > 5) {
1726 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1730 /* Get a printer handle */
1732 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1734 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1738 if (!W_ERROR_IS_OK(werror))
1741 /* Dummy up some values for the form data */
1744 level = atoi(argv[3]);
1749 info1.flags = SPOOLSS_FORM_USER;
1750 info1.form_name = argv[2];
1751 info1.size.width = 100;
1752 info1.size.height = 100;
1753 info1.area.left = 0;
1754 info1.area.top = 10;
1755 info1.area.right = 20;
1756 info1.area.bottom = 30;
1758 info.info1 = &info1;
1762 info2.flags = SPOOLSS_FORM_USER;
1763 info2.form_name = argv[2];
1764 info2.size.width = 100;
1765 info2.size.height = 100;
1766 info2.area.left = 0;
1767 info2.area.top = 10;
1768 info2.area.right = 20;
1769 info2.area.bottom = 30;
1770 info2.keyword = argv[2];
1771 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
1772 info2.mui_dll = NULL;
1773 info2.ressource_id = 0;
1774 info2.display_name = argv[2];
1777 info.info2 = &info2;
1785 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1792 if (is_valid_policy_hnd(&handle))
1793 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1798 /****************************************************************************
1799 ****************************************************************************/
1801 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1802 int argc, const char **argv)
1807 const char *printername;
1808 union spoolss_AddFormInfo info;
1809 struct spoolss_AddFormInfo1 info1;
1811 /* Parse the command arguments */
1814 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1818 /* Get a printer handle */
1820 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1822 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1824 SEC_FLAG_MAXIMUM_ALLOWED,
1826 if (!W_ERROR_IS_OK(werror))
1829 /* Dummy up some values for the form data */
1831 info1.flags = SPOOLSS_FORM_PRINTER;
1832 info1.size.width = 100;
1833 info1.size.height = 100;
1834 info1.area.left = 0;
1835 info1.area.top = 1000;
1836 info1.area.right = 2000;
1837 info1.area.bottom = 3000;
1838 info1.form_name = argv[2];
1840 info.info1 = &info1;
1844 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1852 if (is_valid_policy_hnd(&handle))
1853 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1858 /****************************************************************************
1859 ****************************************************************************/
1861 static const char *get_form_flag(int form_flag)
1863 switch (form_flag) {
1864 case SPOOLSS_FORM_USER:
1866 case SPOOLSS_FORM_BUILTIN:
1867 return "FORM_BUILTIN";
1868 case SPOOLSS_FORM_PRINTER:
1869 return "FORM_PRINTER";
1875 /****************************************************************************
1876 ****************************************************************************/
1878 static void display_form_info1(struct spoolss_FormInfo1 *r)
1881 "\tflag: %s (%d)\n" \
1882 "\twidth: %d, length: %d\n" \
1883 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1884 r->form_name, get_form_flag(r->flags), r->flags,
1885 r->size.width, r->size.height,
1886 r->area.left, r->area.right,
1887 r->area.top, r->area.bottom);
1890 /****************************************************************************
1891 ****************************************************************************/
1893 static void display_form_info2(struct spoolss_FormInfo2 *r)
1896 "\tflag: %s (%d)\n" \
1897 "\twidth: %d, length: %d\n" \
1898 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1899 r->form_name, get_form_flag(r->flags), r->flags,
1900 r->size.width, r->size.height,
1901 r->area.left, r->area.right,
1902 r->area.top, r->area.bottom);
1903 printf("\tkeyword: %s\n", r->keyword);
1904 printf("\tstring_type: 0x%08x\n", r->string_type);
1905 printf("\tmui_dll: %s\n", r->mui_dll);
1906 printf("\tressource_id: 0x%08x\n", r->ressource_id);
1907 printf("\tdisplay_name: %s\n", r->display_name);
1908 printf("\tlang_id: %d\n", r->lang_id);
1912 /****************************************************************************
1913 ****************************************************************************/
1915 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1916 int argc, const char **argv)
1921 const char *printername;
1923 uint32_t offered = 0;
1924 union spoolss_FormInfo info;
1928 /* Parse the command arguments */
1930 if (argc < 3 || argc > 5) {
1931 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1935 /* Get a printer handle */
1937 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1939 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1941 SEC_FLAG_MAXIMUM_ALLOWED,
1943 if (!W_ERROR_IS_OK(werror))
1947 level = atoi(argv[3]);
1952 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1961 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1962 buffer = data_blob_talloc_zero(mem_ctx, needed);
1964 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1975 if (!NT_STATUS_IS_OK(status)) {
1981 display_form_info1(&info.info1);
1984 display_form_info2(&info.info2);
1989 if (is_valid_policy_hnd(&handle))
1990 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1995 /****************************************************************************
1996 ****************************************************************************/
1998 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1999 TALLOC_CTX *mem_ctx, int argc,
2005 const char *printername;
2007 /* Parse the command arguments */
2010 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2014 /* Get a printer handle */
2016 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2018 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2020 SEC_FLAG_MAXIMUM_ALLOWED,
2022 if (!W_ERROR_IS_OK(werror))
2025 /* Delete the form */
2027 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2031 if (!NT_STATUS_IS_OK(status)) {
2032 return ntstatus_to_werror(status);
2036 if (is_valid_policy_hnd(&handle))
2037 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2042 /****************************************************************************
2043 ****************************************************************************/
2045 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2046 TALLOC_CTX *mem_ctx, int argc,
2051 const char *printername;
2052 uint32 num_forms, level = 1, i;
2053 union spoolss_FormInfo *forms;
2055 /* Parse the command arguments */
2057 if (argc < 2 || argc > 4) {
2058 printf ("Usage: %s <printer> [level]\n", argv[0]);
2062 /* Get a printer handle */
2064 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2066 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2068 SEC_FLAG_MAXIMUM_ALLOWED,
2070 if (!W_ERROR_IS_OK(werror))
2074 level = atoi(argv[2]);
2077 /* Enumerate forms */
2079 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2086 if (!W_ERROR_IS_OK(werror))
2089 /* Display output */
2091 for (i = 0; i < num_forms; i++) {
2094 display_form_info1(&forms[i].info1);
2097 display_form_info2(&forms[i].info2);
2103 if (is_valid_policy_hnd(&handle))
2104 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2109 /****************************************************************************
2110 ****************************************************************************/
2112 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2113 TALLOC_CTX *mem_ctx,
2114 int argc, const char **argv)
2118 const char *printername;
2120 union spoolss_PrinterInfo info;
2121 enum winreg_Type type;
2122 union spoolss_PrinterData data;
2124 /* parse the command arguments */
2126 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2127 " <value> <data>\n",
2129 result = WERR_INVALID_PARAM;
2133 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2137 if (strequal(argv[2], "string")) {
2141 if (strequal(argv[2], "binary")) {
2145 if (strequal(argv[2], "dword")) {
2149 if (strequal(argv[2], "multistring")) {
2150 type = REG_MULTI_SZ;
2153 if (type == REG_NONE) {
2154 printf("Unknown data type: %s\n", argv[2]);
2155 result = WERR_INVALID_PARAM;
2159 /* get a printer handle */
2161 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2163 SEC_FLAG_MAXIMUM_ALLOWED,
2165 if (!W_ERROR_IS_OK(result)) {
2169 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2174 if (!W_ERROR_IS_OK(result)) {
2178 printf("%s\n", current_timestring(mem_ctx, true));
2179 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2181 /* Set the printer data */
2185 data.string = talloc_strdup(mem_ctx, argv[4]);
2186 W_ERROR_HAVE_NO_MEMORY(data.string);
2189 data.value = strtoul(argv[4], NULL, 10);
2192 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2194 case REG_MULTI_SZ: {
2196 const char **strings = NULL;
2198 for (i=4; i<argc; i++) {
2199 if (strcmp(argv[i], "NULL") == 0) {
2202 if (!add_string_to_array(mem_ctx, argv[i],
2205 result = WERR_NOMEM;
2209 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2210 if (!data.string_array) {
2211 result = WERR_NOMEM;
2214 for (i=0; i < num_strings; i++) {
2215 data.string_array[i] = strings[i];
2220 printf("Unknown data type: %s\n", argv[2]);
2221 result = WERR_INVALID_PARAM;
2225 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2227 argv[3], /* value_name */
2230 0, /* autocalculated size */
2232 if (!W_ERROR_IS_OK(result)) {
2233 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2236 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2238 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2243 if (!W_ERROR_IS_OK(result)) {
2247 printf("%s\n", current_timestring(mem_ctx, true));
2248 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2252 if (is_valid_policy_hnd(&pol)) {
2253 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2259 /****************************************************************************
2260 ****************************************************************************/
2262 static void display_job_info1(struct spoolss_JobInfo1 *r)
2264 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2265 r->user_name, r->document_name, r->text_status, r->pages_printed,
2269 /****************************************************************************
2270 ****************************************************************************/
2272 static void display_job_info2(struct spoolss_JobInfo2 *r)
2274 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2275 r->position, r->job_id,
2276 r->user_name, r->document_name, r->text_status, r->pages_printed,
2277 r->total_pages, r->size);
2280 /****************************************************************************
2281 ****************************************************************************/
2283 static void display_job_info3(struct spoolss_JobInfo3 *r)
2285 printf("jobid[%d], next_jobid[%d]\n",
2286 r->job_id, r->next_job_id);
2289 /****************************************************************************
2290 ****************************************************************************/
2292 static void display_job_info4(struct spoolss_JobInfo4 *r)
2294 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2295 r->position, r->job_id,
2296 r->user_name, r->document_name, r->text_status, r->pages_printed,
2297 r->total_pages, r->size, r->size_high);
2300 /****************************************************************************
2301 ****************************************************************************/
2303 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2304 TALLOC_CTX *mem_ctx, int argc,
2308 uint32_t level = 1, count, i;
2309 const char *printername;
2311 union spoolss_JobInfo *info;
2313 if (argc < 2 || argc > 3) {
2314 printf("Usage: %s printername [level]\n", argv[0]);
2319 level = atoi(argv[2]);
2322 /* Open printer handle */
2324 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2326 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2328 SEC_FLAG_MAXIMUM_ALLOWED,
2330 if (!W_ERROR_IS_OK(result))
2333 /* Enumerate ports */
2335 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2343 if (!W_ERROR_IS_OK(result)) {
2347 for (i = 0; i < count; i++) {
2350 display_job_info1(&info[i].info1);
2353 display_job_info2(&info[i].info2);
2356 d_printf("unknown info level %d\n", level);
2362 if (is_valid_policy_hnd(&hnd)) {
2363 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2369 /****************************************************************************
2370 ****************************************************************************/
2372 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2373 TALLOC_CTX *mem_ctx, int argc,
2377 const char *printername;
2378 struct policy_handle hnd;
2381 union spoolss_JobInfo info;
2383 if (argc < 3 || argc > 4) {
2384 printf("Usage: %s printername job_id [level]\n", argv[0]);
2388 job_id = atoi(argv[2]);
2391 level = atoi(argv[3]);
2394 /* Open printer handle */
2396 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2398 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2400 SEC_FLAG_MAXIMUM_ALLOWED,
2402 if (!W_ERROR_IS_OK(result)) {
2406 /* Enumerate ports */
2408 result = rpccli_spoolss_getjob(cli, mem_ctx,
2415 if (!W_ERROR_IS_OK(result)) {
2421 display_job_info1(&info.info1);
2424 display_job_info2(&info.info2);
2427 display_job_info3(&info.info3);
2430 display_job_info4(&info.info4);
2433 d_printf("unknown info level %d\n", level);
2438 if (is_valid_policy_hnd(&hnd)) {
2439 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2446 /****************************************************************************
2447 ****************************************************************************/
2449 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2450 TALLOC_CTX *mem_ctx, int argc,
2456 const char *printername;
2458 uint32_t value_offered = 0;
2459 const char *value_name = NULL;
2460 uint32_t value_needed;
2461 enum winreg_Type type;
2462 uint8_t *data = NULL;
2463 uint32_t data_offered = 0;
2464 uint32_t data_needed;
2467 printf("Usage: %s printername\n", argv[0]);
2471 /* Open printer handle */
2473 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2475 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2477 SEC_FLAG_MAXIMUM_ALLOWED,
2479 if (!W_ERROR_IS_OK(result)) {
2483 /* Enumerate data */
2485 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2497 data_offered = data_needed;
2498 value_offered = value_needed;
2499 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2500 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2502 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2504 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2515 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2517 fstrcpy(v.valuename, value_name);
2519 v.size = data_offered;
2521 display_reg_value(v);
2525 if (W_ERROR_V(result) == ERRnomoreitems) {
2526 result = W_ERROR(ERRsuccess);
2530 if (is_valid_policy_hnd(&hnd)) {
2531 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2537 /****************************************************************************
2538 ****************************************************************************/
2540 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2541 TALLOC_CTX *mem_ctx, int argc,
2546 const char *printername;
2547 const char *keyname = NULL;
2549 REGVAL_CTR *ctr = NULL;
2552 printf("Usage: %s printername <keyname>\n", argv[0]);
2558 /* Open printer handle */
2560 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2562 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2564 SEC_FLAG_MAXIMUM_ALLOWED,
2566 if (!W_ERROR_IS_OK(result))
2569 /* Enumerate subkeys */
2571 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2574 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2576 if (!W_ERROR_IS_OK(result))
2579 for (i=0; i < ctr->num_values; i++) {
2580 display_reg_value(*(ctr->values[i]));
2586 if (is_valid_policy_hnd(&hnd))
2587 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2592 /****************************************************************************
2593 ****************************************************************************/
2595 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2596 TALLOC_CTX *mem_ctx, int argc,
2600 const char *printername;
2601 const char *keyname = NULL;
2603 const char **key_buffer = NULL;
2606 if (argc < 2 || argc > 3) {
2607 printf("Usage: %s printername [keyname]\n", argv[0]);
2617 /* Open printer handle */
2619 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2621 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2623 SEC_FLAG_MAXIMUM_ALLOWED,
2625 if (!W_ERROR_IS_OK(result)) {
2629 /* Enumerate subkeys */
2631 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2637 if (!W_ERROR_IS_OK(result)) {
2641 for (i=0; key_buffer && key_buffer[i]; i++) {
2642 printf("%s\n", key_buffer[i]);
2647 if (is_valid_policy_hnd(&hnd)) {
2648 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2654 /****************************************************************************
2655 ****************************************************************************/
2657 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2658 TALLOC_CTX *mem_ctx, int argc,
2661 const char *printername;
2662 const char *clientname;
2666 struct spoolss_NotifyOption option;
2669 printf("Usage: %s printername\n", argv[0]);
2676 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2678 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2680 SEC_FLAG_MAXIMUM_ALLOWED,
2682 if (!W_ERROR_IS_OK(result)) {
2683 printf("Error opening %s\n", argv[1]);
2687 /* Create spool options */
2692 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2693 if (option.types == NULL) {
2694 result = WERR_NOMEM;
2698 option.types[0].type = PRINTER_NOTIFY_TYPE;
2699 option.types[0].count = 1;
2700 option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2701 if (option.types[0].fields == NULL) {
2702 result = WERR_NOMEM;
2705 option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2707 option.types[1].type = JOB_NOTIFY_TYPE;
2708 option.types[1].count = 1;
2709 option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2710 if (option.types[1].fields == NULL) {
2711 result = WERR_NOMEM;
2714 option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2716 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2718 result = WERR_NOMEM;
2724 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2732 if (!W_ERROR_IS_OK(result)) {
2733 printf("Error rffpcnex %s\n", argv[1]);
2738 if (is_valid_policy_hnd(&hnd))
2739 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2744 /****************************************************************************
2745 ****************************************************************************/
2747 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2748 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2750 union spoolss_PrinterInfo info1, info2;
2752 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2754 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2755 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2760 if ( !W_ERROR_IS_OK(werror) ) {
2761 printf("failed (%s)\n", win_errstr(werror));
2762 talloc_destroy(mem_ctx);
2767 printf("Retrieving printer properties for %s...", cli2->desthost);
2768 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2773 if ( !W_ERROR_IS_OK(werror) ) {
2774 printf("failed (%s)\n", win_errstr(werror));
2775 talloc_destroy(mem_ctx);
2780 talloc_destroy(mem_ctx);
2785 /****************************************************************************
2786 ****************************************************************************/
2788 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2789 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2791 union spoolss_PrinterInfo info1, info2;
2793 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2794 SEC_DESC *sd1, *sd2;
2798 printf("Retrieving printer security for %s...", cli1->desthost);
2799 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2804 if ( !W_ERROR_IS_OK(werror) ) {
2805 printf("failed (%s)\n", win_errstr(werror));
2811 printf("Retrieving printer security for %s...", cli2->desthost);
2812 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2817 if ( !W_ERROR_IS_OK(werror) ) {
2818 printf("failed (%s)\n", win_errstr(werror));
2827 sd1 = info1.info3.secdesc;
2828 sd2 = info2.info3.secdesc;
2830 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2831 printf("NULL secdesc!\n");
2836 if (!sec_desc_equal( sd1, sd2 ) ) {
2837 printf("Security Descriptors *not* equal!\n");
2842 printf("Security descriptors match\n");
2845 talloc_destroy(mem_ctx);
2850 /****************************************************************************
2851 ****************************************************************************/
2853 extern struct user_auth_info *rpcclient_auth_info;
2855 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2856 TALLOC_CTX *mem_ctx, int argc,
2859 const char *printername;
2860 char *printername_path = NULL;
2861 struct cli_state *cli_server2 = NULL;
2862 struct rpc_pipe_client *cli2 = NULL;
2863 POLICY_HND hPrinter1, hPrinter2;
2868 printf("Usage: %s <printer> <server>\n", argv[0]);
2872 printername = argv[1];
2874 /* first get the connection to the remote server */
2876 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2879 get_cmdline_auth_info_username(rpcclient_auth_info),
2881 get_cmdline_auth_info_password(rpcclient_auth_info),
2882 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2883 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2885 if ( !NT_STATUS_IS_OK(nt_status) )
2886 return WERR_GENERAL_FAILURE;
2888 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2890 if (!NT_STATUS_IS_OK(nt_status)) {
2891 printf("failed to open spoolss pipe on server %s (%s)\n",
2892 argv[2], nt_errstr(nt_status));
2893 return WERR_GENERAL_FAILURE;
2896 /* now open up both printers */
2898 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2900 printf("Opening %s...", printername_path);
2902 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2906 if ( !W_ERROR_IS_OK(werror) ) {
2907 printf("failed (%s)\n", win_errstr(werror));
2912 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2914 printf("Opening %s...", printername_path);
2915 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2919 if ( !W_ERROR_IS_OK(werror) ) {
2920 printf("failed (%s)\n", win_errstr(werror));
2925 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2926 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2928 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2935 printf("Closing printers...");
2936 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2937 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2940 /* close the second remote connection */
2942 cli_shutdown( cli_server2 );
2946 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
2948 printf("print_processor_name: %s\n", r->print_processor_name);
2951 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
2952 TALLOC_CTX *mem_ctx, int argc,
2956 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2957 uint32_t num_procs, level = 1, i;
2958 union spoolss_PrintProcessorInfo *procs;
2960 /* Parse the command arguments */
2962 if (argc < 1 || argc > 4) {
2963 printf ("Usage: %s [environment] [level]\n", argv[0]);
2968 environment = argv[1];
2972 level = atoi(argv[2]);
2975 /* Enumerate Print Processors */
2977 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
2978 cli->srv_name_slash,
2984 if (!W_ERROR_IS_OK(werror))
2987 /* Display output */
2989 for (i = 0; i < num_procs; i++) {
2992 display_proc_info1(&procs[i].info1);
3001 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3003 printf("name_array: %s\n", r->name_array);
3006 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3007 TALLOC_CTX *mem_ctx, int argc,
3011 const char *print_processor_name = "winprint";
3012 uint32_t num_procs, level = 1, i;
3013 union spoolss_PrintProcDataTypesInfo *procs;
3015 /* Parse the command arguments */
3017 if (argc < 1 || argc > 4) {
3018 printf ("Usage: %s [environment] [level]\n", argv[0]);
3023 print_processor_name = argv[1];
3027 level = atoi(argv[2]);
3030 /* Enumerate Print Processor Data Types */
3032 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3033 cli->srv_name_slash,
3034 print_processor_name,
3039 if (!W_ERROR_IS_OK(werror))
3042 /* Display output */
3044 for (i = 0; i < num_procs; i++) {
3047 display_proc_data_types_info1(&procs[i].info1);
3056 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3058 printf("monitor_name: %s\n", r->monitor_name);
3061 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3063 printf("monitor_name: %s\n", r->monitor_name);
3064 printf("environment: %s\n", r->environment);
3065 printf("dll_name: %s\n", r->dll_name);
3068 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3069 TALLOC_CTX *mem_ctx, int argc,
3073 uint32_t count, level = 1, i;
3074 union spoolss_MonitorInfo *info;
3076 /* Parse the command arguments */
3079 printf("Usage: %s [level]\n", argv[0]);
3084 level = atoi(argv[1]);
3087 /* Enumerate Print Monitors */
3089 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3090 cli->srv_name_slash,
3095 if (!W_ERROR_IS_OK(werror)) {
3099 /* Display output */
3101 for (i = 0; i < count; i++) {
3104 display_monitor1(&info[i].info1);
3107 display_monitor2(&info[i].info2);
3116 /* List of commands exported by this module */
3117 struct cmd_set spoolss_commands[] = {
3121 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
3122 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
3123 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
3124 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
3125 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
3126 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
3127 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
3128 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
3129 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &syntax_spoolss, NULL, "Get print job", "" },
3130 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
3131 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
3132 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
3133 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
3134 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
3135 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
3136 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
3137 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
3138 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
3139 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
3140 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
3141 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
3142 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
3143 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
3144 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
3145 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
3146 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
3147 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
3148 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
3149 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
3150 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },
3151 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &syntax_spoolss, NULL, "Enumerate Print Processors", "" },
3152 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &syntax_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3153 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &syntax_spoolss, NULL, "Enumerate Print Monitors", "" },