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
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "rpcclient.h"
28 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
30 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
31 _cli->srv_name_slash, _arg); \
32 W_ERROR_HAVE_NO_MEMORY(_printername); \
36 const char *long_archi;
37 const char *short_archi;
41 /* The version int is used by getdrivers. Note that
42 all architecture strings that support mutliple
43 versions must be grouped together since enumdrivers
44 uses this property to prevent issuing multiple
45 enumdriver calls for the same arch */
48 static const struct table_node archi_table[]= {
50 {"Windows 4.0", "WIN40", 0 },
51 {"Windows NT x86", "W32X86", 2 },
52 {"Windows NT x86", "W32X86", 3 },
53 {"Windows NT R4000", "W32MIPS", 2 },
54 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
55 {"Windows NT PowerPC", "W32PPC", 2 },
56 {"Windows IA64", "IA64", 3 },
57 {"Windows x64", "x64", 3 },
64 * rpcclient module for SPOOLSS rpc pipe.
66 * This generally just parses and checks command lines, and then calls
67 * a cli_spoolss function.
70 /****************************************************************************
71 function to do the mapping between the long architecture name and
73 ****************************************************************************/
75 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
79 DEBUG(107,("Getting architecture dependant directory\n"));
82 } while ( (archi_table[i].long_archi!=NULL ) &&
83 StrCaseCmp(long_archi, archi_table[i].long_archi) );
85 if (archi_table[i].long_archi==NULL) {
86 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
90 /* this might be client code - but shouldn't this be an fstrcpy etc? */
93 DEBUGADD(108,("index: [%d]\n", i));
94 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
95 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
97 return archi_table[i].short_archi;
100 /****************************************************************************
101 ****************************************************************************/
103 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
105 int argc, const char **argv)
111 printf("Usage: %s <printername>\n", argv[0]);
116 return WERR_GENERAL_FAILURE;
118 /* Open the printer handle */
120 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
124 if (W_ERROR_IS_OK(werror)) {
125 printf("Printer %s opened successfully\n", argv[1]);
126 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
128 if (!W_ERROR_IS_OK(werror)) {
129 printf("Error closing printer handle! (%s)\n",
130 get_dos_error_msg(werror));
138 /****************************************************************************
139 ****************************************************************************/
141 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
146 printf("\tprintername:[%s]\n", r->printername);
147 printf("\tservername:[%s]\n", r->servername);
148 printf("\tcjobs:[0x%x]\n", r->cjobs);
149 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
150 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
151 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
152 r->time.day, r->time.day_of_week);
153 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
154 r->time.second, r->time.millisecond);
156 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
157 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
159 printf("\tversion:[0x%x]\n", r->version);
160 printf("\tfree_build:[0x%x]\n", r->free_build);
161 printf("\tspooling:[0x%x]\n", r->spooling);
162 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
163 printf("\tsession_counter:[0x%x]\n", r->session_counter);
164 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
165 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
166 printf("\tjob_error:[0x%x]\n", r->job_error);
167 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
168 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
169 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
170 printf("\tchange_id:[0x%x]\n", r->change_id);
171 printf("\tlast_error: %s\n", win_errstr(r->last_error));
172 printf("\tstatus:[0x%x]\n", r->status);
173 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
174 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
175 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
176 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
177 printf("\tref_ic:[0x%x]\n", r->ref_ic);
178 printf("\treserved2:[0x%x]\n", r->reserved2);
179 printf("\treserved3:[0x%x]\n", r->reserved3);
184 /****************************************************************************
185 ****************************************************************************/
187 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
189 printf("\tflags:[0x%x]\n", r->flags);
190 printf("\tname:[%s]\n", r->name);
191 printf("\tdescription:[%s]\n", r->description);
192 printf("\tcomment:[%s]\n", r->comment);
197 /****************************************************************************
198 ****************************************************************************/
200 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
202 printf("\tservername:[%s]\n", r->servername);
203 printf("\tprintername:[%s]\n", r->printername);
204 printf("\tsharename:[%s]\n", r->sharename);
205 printf("\tportname:[%s]\n", r->portname);
206 printf("\tdrivername:[%s]\n", r->drivername);
207 printf("\tcomment:[%s]\n", r->comment);
208 printf("\tlocation:[%s]\n", r->location);
209 printf("\tsepfile:[%s]\n", r->sepfile);
210 printf("\tprintprocessor:[%s]\n", r->printprocessor);
211 printf("\tdatatype:[%s]\n", r->datatype);
212 printf("\tparameters:[%s]\n", r->parameters);
213 printf("\tattributes:[0x%x]\n", r->attributes);
214 printf("\tpriority:[0x%x]\n", r->priority);
215 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
216 printf("\tstarttime:[0x%x]\n", r->starttime);
217 printf("\tuntiltime:[0x%x]\n", r->untiltime);
218 printf("\tstatus:[0x%x]\n", r->status);
219 printf("\tcjobs:[0x%x]\n", r->cjobs);
220 printf("\taverageppm:[0x%x]\n", r->averageppm);
223 display_sec_desc(r->secdesc);
228 /****************************************************************************
229 ****************************************************************************/
231 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
233 display_sec_desc(r->secdesc);
238 /****************************************************************************
239 ****************************************************************************/
241 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
243 printf("\tguid:[%s]\n", r->guid);
244 printf("\taction:[0x%x]\n", r->action);
248 /****************************************************************************
249 ****************************************************************************/
251 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
253 int argc, const char **argv)
257 union spoolss_PrinterInfo *info;
262 printf("Usage: %s [level] [name]\n", argv[0]);
267 level = atoi(argv[1]);
273 name = cli->srv_name_slash;
276 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
283 if (W_ERROR_IS_OK(result)) {
286 printf ("No printers returned.\n");
290 for (i = 0; i < count; i++) {
293 display_print_info0(&info[i].info0);
296 display_print_info1(&info[i].info1);
299 display_print_info2(&info[i].info2);
302 display_print_info3(&info[i].info3);
305 printf("unknown info level %d\n", level);
315 /****************************************************************************
316 ****************************************************************************/
318 static void display_port_info_1(struct spoolss_PortInfo1 *r)
320 printf("\tPort Name:\t[%s]\n", r->port_name);
323 /****************************************************************************
324 ****************************************************************************/
326 static void display_port_info_2(struct spoolss_PortInfo2 *r)
328 printf("\tPort Name:\t[%s]\n", r->port_name);
329 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
330 printf("\tDescription:\t[%s]\n", r->description);
331 printf("\tPort Type:\t" );
333 int comma = 0; /* hack */
335 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
339 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
340 printf( "%sWrite", comma ? ", " : "" );
343 /* These two have slightly different interpretations
344 on 95/98/ME but I'm disregarding that for now */
345 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
346 printf( "%sRedirected", comma ? ", " : "" );
349 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
350 printf( "%sNet-Attached", comma ? ", " : "" );
354 printf( "[Unset]\n" );
356 printf("\tReserved:\t[%d]\n", r->reserved);
360 /****************************************************************************
361 ****************************************************************************/
363 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
364 TALLOC_CTX *mem_ctx, int argc,
370 union spoolss_PortInfo *info;
373 printf("Usage: %s [level]\n", argv[0]);
378 level = atoi(argv[1]);
381 /* Enumerate ports */
383 result = rpccli_spoolss_enumports(cli, mem_ctx,
389 if (W_ERROR_IS_OK(result)) {
392 for (i = 0; i < count; i++) {
395 display_port_info_1(&info[i].info1);
398 display_port_info_2(&info[i].info2);
401 printf("unknown info level %d\n", level);
410 /****************************************************************************
411 ****************************************************************************/
413 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
415 int argc, const char **argv)
420 uint32 info_level = 2;
421 union spoolss_PrinterInfo info;
422 struct spoolss_SetPrinterInfoCtr info_ctr;
423 const char *printername, *comment = NULL;
424 struct spoolss_DevmodeContainer devmode_ctr;
425 struct sec_desc_buf secdesc_ctr;
427 if (argc == 1 || argc > 3) {
428 printf("Usage: %s printername comment\n", argv[0]);
433 /* Open a printer handle */
438 ZERO_STRUCT(devmode_ctr);
439 ZERO_STRUCT(secdesc_ctr);
441 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
443 /* get a printer handle */
444 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
448 if (!W_ERROR_IS_OK(result))
451 /* Get printer info */
452 result = rpccli_spoolss_getprinter(cli, mem_ctx,
457 if (!W_ERROR_IS_OK(result))
461 /* Modify the comment. */
462 info.info2.comment = comment;
463 info.info2.secdesc = NULL;
464 info.info2.devmode = NULL;
467 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
469 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
476 if (W_ERROR_IS_OK(result))
477 printf("Success in setting comment.\n");
480 if (is_valid_policy_hnd(&pol))
481 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
486 /****************************************************************************
487 ****************************************************************************/
489 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
491 int argc, const char **argv)
496 uint32 info_level = 2;
497 union spoolss_PrinterInfo info;
498 const char *printername,
499 *new_printername = NULL;
500 struct spoolss_SetPrinterInfoCtr info_ctr;
501 struct spoolss_DevmodeContainer devmode_ctr;
502 struct sec_desc_buf secdesc_ctr;
504 ZERO_STRUCT(devmode_ctr);
505 ZERO_STRUCT(secdesc_ctr);
507 if (argc == 1 || argc > 3) {
508 printf("Usage: %s printername new_printername\n", argv[0]);
513 /* Open a printer handle */
515 new_printername = argv[2];
518 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
520 /* get a printer handle */
521 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
525 if (!W_ERROR_IS_OK(result))
528 /* Get printer info */
529 result = rpccli_spoolss_getprinter(cli, mem_ctx,
534 if (!W_ERROR_IS_OK(result))
537 /* Modify the printername. */
538 info.info2.printername = new_printername;
539 info.info2.devmode = NULL;
540 info.info2.secdesc = NULL;
542 info_ctr.level = info_level;
543 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
545 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
552 if (W_ERROR_IS_OK(result))
553 printf("Success in setting printername.\n");
556 if (is_valid_policy_hnd(&pol))
557 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
562 /****************************************************************************
563 ****************************************************************************/
565 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
567 int argc, const char **argv)
572 const char *printername;
573 union spoolss_PrinterInfo info;
575 if (argc == 1 || argc > 3) {
576 printf("Usage: %s <printername> [level]\n", argv[0]);
580 /* Open a printer handle */
582 level = atoi(argv[2]);
585 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
587 /* get a printer handle */
589 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
591 SEC_FLAG_MAXIMUM_ALLOWED,
593 if (!W_ERROR_IS_OK(result)) {
597 /* Get printer info */
599 result = rpccli_spoolss_getprinter(cli, mem_ctx,
604 if (!W_ERROR_IS_OK(result)) {
608 /* Display printer info */
611 display_print_info0(&info.info0);
614 display_print_info1(&info.info1);
617 display_print_info2(&info.info2);
620 display_print_info3(&info.info3);
623 display_print_info7(&info.info7);
626 printf("unknown info level %d\n", level);
630 if (is_valid_policy_hnd(&pol)) {
631 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
637 /****************************************************************************
638 ****************************************************************************/
640 static void display_reg_value(REGISTRY_VALUE value)
646 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
647 *((uint32 *) value.data_p));
650 rpcstr_pull_talloc(talloc_tos(),
655 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
658 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
660 printf("%s: REG_BINARY:", value.valuename);
662 for (i=0; i<len; i++) {
663 if (hex[i] == '\0') {
676 uint32 i, num_values;
679 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
680 value.size, &num_values,
682 d_printf("reg_pull_multi_sz failed\n");
686 printf("%s: REG_MULTI_SZ: \n", value.valuename);
687 for (i=0; i<num_values; i++) {
688 d_printf("%s\n", values[i]);
694 printf("%s: unknown type %d\n", value.valuename, value.type);
699 /****************************************************************************
700 ****************************************************************************/
702 static void display_printer_data(const char *v,
703 enum winreg_Type type,
704 union spoolss_PrinterData *r)
710 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
713 printf("%s: REG_SZ: %s\n", v, r->string);
716 char *hex = hex_encode_talloc(NULL,
717 r->binary.data, r->binary.length);
719 printf("%s: REG_BINARY:", v);
721 for (i=0; i<len; i++) {
722 if (hex[i] == '\0') {
735 printf("%s: REG_MULTI_SZ: ", v);
736 for (i=0; r->string_array[i] != NULL; i++) {
737 printf("%s ", r->string_array[i]);
742 printf("%s: unknown type 0x%02x:\n", v, type);
747 /****************************************************************************
748 ****************************************************************************/
750 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
752 int argc, const char **argv)
757 const char *valuename;
758 enum winreg_Type type;
759 union spoolss_PrinterData data;
762 printf("Usage: %s <printername> <valuename>\n", argv[0]);
763 printf("<printername> of . queries print server\n");
768 /* Open a printer handle */
770 if (strncmp(argv[1], ".", sizeof(".")) == 0)
771 fstrcpy(printername, cli->srv_name_slash);
773 slprintf(printername, sizeof(printername)-1, "%s\\%s",
774 cli->srv_name_slash, argv[1]);
776 /* get a printer handle */
778 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
780 SEC_FLAG_MAXIMUM_ALLOWED,
782 if (!W_ERROR_IS_OK(result))
785 /* Get printer info */
787 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
793 if (!W_ERROR_IS_OK(result))
796 /* Display printer data */
798 display_printer_data(valuename, type, &data);
801 if (is_valid_policy_hnd(&pol))
802 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
807 /****************************************************************************
808 ****************************************************************************/
810 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
812 int argc, const char **argv)
818 const char *valuename, *keyname;
819 REGISTRY_VALUE value;
821 enum winreg_Type type;
822 uint8_t *buffer = NULL;
823 uint32_t offered = 0;
827 printf("Usage: %s <printername> <keyname> <valuename>\n",
829 printf("<printername> of . queries print server\n");
835 /* Open a printer handle */
837 if (strncmp(argv[1], ".", sizeof(".")) == 0)
838 fstrcpy(printername, cli->srv_name_slash);
840 slprintf(printername, sizeof(printername)-1, "%s\\%s",
841 cli->srv_name_slash, argv[1]);
843 /* get a printer handle */
845 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
847 SEC_FLAG_MAXIMUM_ALLOWED,
849 if (!W_ERROR_IS_OK(result))
852 /* Get printer info */
854 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
863 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
865 buffer = talloc_array(mem_ctx, uint8_t, needed);
866 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
877 if (!NT_STATUS_IS_OK(status)) {
881 if (!W_ERROR_IS_OK(result)) {
886 if (!W_ERROR_IS_OK(result))
889 /* Display printer data */
891 fstrcpy(value.valuename, valuename);
894 value.data_p = buffer;
896 display_reg_value(value);
899 if (is_valid_policy_hnd(&pol))
900 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
905 /****************************************************************************
906 ****************************************************************************/
908 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
914 printf("Printer Driver Info 1:\n");
915 printf("\tDriver Name: [%s]\n\n", r->driver_name);
918 /****************************************************************************
919 ****************************************************************************/
921 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
927 printf("Printer Driver Info 2:\n");
928 printf("\tVersion: [%x]\n", r->version);
929 printf("\tDriver Name: [%s]\n", r->driver_name);
930 printf("\tArchitecture: [%s]\n", r->architecture);
931 printf("\tDriver Path: [%s]\n", r->driver_path);
932 printf("\tDatafile: [%s]\n", r->data_file);
933 printf("\tConfigfile: [%s]\n\n", r->config_file);
936 /****************************************************************************
937 ****************************************************************************/
939 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
947 printf("Printer Driver Info 3:\n");
948 printf("\tVersion: [%x]\n", r->version);
949 printf("\tDriver Name: [%s]\n", r->driver_name);
950 printf("\tArchitecture: [%s]\n", r->architecture);
951 printf("\tDriver Path: [%s]\n", r->driver_path);
952 printf("\tDatafile: [%s]\n", r->data_file);
953 printf("\tConfigfile: [%s]\n\n", r->config_file);
954 printf("\tHelpfile: [%s]\n\n", r->help_file);
956 for (i=0; r->dependent_files[i] != NULL; i++) {
957 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
962 printf("\tMonitorname: [%s]\n", r->monitor_name);
963 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
967 /****************************************************************************
968 ****************************************************************************/
970 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
972 int argc, const char **argv)
977 const char *printername;
979 bool success = false;
980 union spoolss_DriverInfo info;
981 uint32_t server_major_version;
982 uint32_t server_minor_version;
984 if ((argc == 1) || (argc > 3)) {
985 printf("Usage: %s <printername> [level]\n", argv[0]);
989 /* get the arguments need to open the printer handle */
991 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
994 level = atoi(argv[2]);
997 /* Open a printer handle */
999 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1003 if (!W_ERROR_IS_OK(werror)) {
1004 printf("Error opening printer handle for %s!\n", printername);
1008 /* loop through and print driver info level for each architecture */
1010 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1012 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1014 archi_table[i].long_archi,
1017 archi_table[i].version,
1020 &server_major_version,
1021 &server_minor_version);
1022 if (!W_ERROR_IS_OK(werror)) {
1026 /* need at least one success */
1030 printf("\n[%s]\n", archi_table[i].long_archi);
1034 display_print_driver1(&info.info1);
1037 display_print_driver2(&info.info2);
1040 display_print_driver3(&info.info3);
1043 printf("unknown info level %d\n", level);
1050 if (is_valid_policy_hnd(&pol)) {
1051 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1065 TALLOC_CTX *mem_ctx,
1066 int argc, const char **argv)
1068 WERROR werror = WERR_OK;
1070 union spoolss_DriverInfo *info;
1071 uint32_t i, j, count;
1074 printf("Usage: enumdrivers [level]\n");
1079 level = atoi(argv[1]);
1083 /* loop through and print driver info level for each architecture */
1084 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1085 /* check to see if we already asked for this architecture string */
1087 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1091 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1092 cli->srv_name_slash,
1093 archi_table[i].long_archi,
1099 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1100 printf("Server does not support environment [%s]\n",
1101 archi_table[i].long_archi);
1110 if (!W_ERROR_IS_OK(werror)) {
1111 printf("Error getting driver for environment [%s] - %d\n",
1112 archi_table[i].long_archi, W_ERROR_V(werror));
1116 printf("\n[%s]\n", archi_table[i].long_archi);
1120 for (j=0; j < count; j++) {
1121 display_print_driver1(&info[j].info1);
1125 for (j=0; j < count; j++) {
1126 display_print_driver2(&info[j].info2);
1130 for (j=0; j < count; j++) {
1131 display_print_driver3(&info[j].info3);
1135 printf("unknown info level %d\n", level);
1136 return WERR_UNKNOWN_LEVEL;
1143 /****************************************************************************
1144 ****************************************************************************/
1146 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1148 printf("\tDirectory Name:[%s]\n", r->directory_name);
1151 /****************************************************************************
1152 ****************************************************************************/
1154 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1155 TALLOC_CTX *mem_ctx,
1156 int argc, const char **argv)
1160 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1163 union spoolss_DriverDirectoryInfo info;
1167 printf("Usage: %s [environment]\n", argv[0]);
1171 /* Get the arguments need to open the printer handle */
1177 /* Get the directory. Only use Info level 1 */
1179 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1180 cli->srv_name_slash,
1188 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1190 buffer = data_blob_talloc_zero(mem_ctx, needed);
1192 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1193 cli->srv_name_slash,
1203 if (W_ERROR_IS_OK(result)) {
1204 display_printdriverdir_1(&info.info1);
1210 /****************************************************************************
1211 ****************************************************************************/
1213 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1214 struct spoolss_AddDriverInfo3 *info,
1220 for (i=0; archi_table[i].long_archi != NULL; i++)
1222 if (strcmp(arch, archi_table[i].short_archi) == 0)
1224 info->version = archi_table[i].version;
1225 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1230 if (archi_table[i].long_archi == NULL)
1232 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1239 /**************************************************************************
1240 wrapper for strtok to get the next parameter from a delimited list.
1241 Needed to handle the empty parameter string denoted by "NULL"
1242 *************************************************************************/
1244 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1245 const char *delim, const char **dest,
1250 /* get the next token */
1251 ptr = strtok_r(str, delim, saveptr);
1253 /* a string of 'NULL' is used to represent an empty
1254 parameter because two consecutive delimiters
1255 will not return an empty string. See man strtok(3)
1257 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1262 *dest = talloc_strdup(mem_ctx, ptr);
1268 /********************************************************************************
1269 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1270 string in the form of
1271 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1272 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1273 <Default Data Type>:<Comma Separated list of Files>
1274 *******************************************************************************/
1276 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1281 char *saveptr = NULL;
1282 struct spoolss_StringArray *deps;
1283 const char **file_array = NULL;
1286 /* fill in the UNISTR fields */
1287 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1288 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1289 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1290 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1291 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1292 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1293 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1295 /* <Comma Separated List of Dependent Files> */
1296 /* save the beginning of the string */
1297 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1300 /* begin to strip out each filename */
1301 str = strtok_r(str, ",", &saveptr);
1303 /* no dependent files, we are done */
1308 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1313 while (str != NULL) {
1314 add_string_to_array(deps, str, &file_array, &count);
1315 str = strtok_r(NULL, ",", &saveptr);
1318 deps->string = talloc_zero_array(deps, const char *, count + 1);
1319 if (!deps->string) {
1323 for (i=0; i < count; i++) {
1324 deps->string[i] = file_array[i];
1327 r->dependent_files = deps;
1332 /****************************************************************************
1333 ****************************************************************************/
1335 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1336 TALLOC_CTX *mem_ctx,
1337 int argc, const char **argv)
1342 struct spoolss_AddDriverInfoCtr info_ctr;
1343 struct spoolss_AddDriverInfo3 info3;
1347 /* parse the command arguments */
1348 if (argc != 3 && argc != 4)
1350 printf ("Usage: %s <Environment> \\\n", argv[0]);
1351 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1352 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1353 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1354 printf ("\t[version]\n");
1359 /* Fill in the spoolss_AddDriverInfo3 struct */
1362 arch = cmd_spoolss_get_short_archi(argv[1]);
1364 printf ("Error Unknown architechture [%s]\n", argv[1]);
1365 return WERR_INVALID_PARAM;
1368 set_drv_info_3_env(mem_ctx, &info3, arch);
1370 driver_args = talloc_strdup( mem_ctx, argv[2] );
1371 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1373 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1374 return WERR_INVALID_PARAM;
1377 /* if printer driver version specified, override the default version
1378 * used by the architecture. This allows installation of Windows
1379 * 2000 (version 3) printer drivers. */
1382 info3.version = atoi(argv[3]);
1386 info_ctr.level = level;
1387 info_ctr.info.info3 = &info3;
1389 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1390 cli->srv_name_slash,
1393 if (!NT_STATUS_IS_OK(status)) {
1394 return ntstatus_to_werror(status);
1396 if (W_ERROR_IS_OK(result)) {
1397 printf ("Printer Driver %s successfully installed.\n",
1405 /****************************************************************************
1406 ****************************************************************************/
1408 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1409 TALLOC_CTX *mem_ctx,
1410 int argc, const char **argv)
1413 struct spoolss_SetPrinterInfoCtr info_ctr;
1414 struct spoolss_SetPrinterInfo2 info2;
1416 /* parse the command arguments */
1419 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1423 /* Fill in the DRIVER_INFO_2 struct */
1426 info2.printername = argv[1];
1427 info2.drivername = argv[3];
1428 info2.sharename = argv[2];
1429 info2.portname = argv[4];
1430 info2.comment = "Created by rpcclient";
1431 info2.printprocessor = "winprint";
1432 info2.datatype = "RAW";
1433 info2.devmode = NULL;
1434 info2.secdesc = NULL;
1435 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1437 info2.defaultpriority = 0;
1438 info2.starttime = 0;
1439 info2.untiltime = 0;
1441 /* These three fields must not be used by AddPrinter()
1442 as defined in the MS Platform SDK documentation..
1446 info2.averageppm = 0;
1450 info_ctr.info.info2 = &info2;
1452 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1454 if (W_ERROR_IS_OK(result))
1455 printf ("Printer %s successfully installed.\n", argv[1]);
1460 /****************************************************************************
1461 ****************************************************************************/
1463 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1464 TALLOC_CTX *mem_ctx,
1465 int argc, const char **argv)
1471 const char *printername;
1472 union spoolss_PrinterInfo info;
1473 struct spoolss_SetPrinterInfoCtr info_ctr;
1474 struct spoolss_DevmodeContainer devmode_ctr;
1475 struct sec_desc_buf secdesc_ctr;
1477 ZERO_STRUCT(devmode_ctr);
1478 ZERO_STRUCT(secdesc_ctr);
1480 /* parse the command arguments */
1483 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1487 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1489 /* Get a printer handle */
1491 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1495 if (!W_ERROR_IS_OK(result))
1498 /* Get printer info */
1500 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1505 if (!W_ERROR_IS_OK(result)) {
1506 printf ("Unable to retrieve printer information!\n");
1510 /* Set the printer driver */
1512 info.info2.drivername = argv[2];
1513 info.info2.devmode = NULL;
1514 info.info2.secdesc = NULL;
1517 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1519 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1526 if (!W_ERROR_IS_OK(result)) {
1527 printf("SetPrinter call failed!\n");
1531 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1536 if (is_valid_policy_hnd(&pol))
1537 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1543 /****************************************************************************
1544 ****************************************************************************/
1546 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1547 TALLOC_CTX *mem_ctx,
1548 int argc, const char **argv)
1550 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1556 const char *arch = NULL;
1557 uint32_t delete_flags = 0;
1559 /* parse the command arguments */
1560 if (argc < 2 || argc > 4) {
1561 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1568 vers = atoi (argv[3]);
1571 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1574 /* delete the driver for all architectures */
1575 for (i=0; archi_table[i].long_archi; i++) {
1577 if (arch && !strequal( archi_table[i].long_archi, arch))
1580 if (vers >= 0 && archi_table[i].version != vers)
1583 /* make the call to remove the driver */
1584 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1585 cli->srv_name_slash,
1586 archi_table[i].long_archi,
1589 archi_table[i].version,
1592 if ( !W_ERROR_IS_OK(result) )
1594 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1595 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1596 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1601 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1602 archi_table[i].long_archi, archi_table[i].version);
1611 /****************************************************************************
1612 ****************************************************************************/
1614 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1615 TALLOC_CTX *mem_ctx,
1616 int argc, const char **argv)
1618 WERROR result = WERR_OK;
1622 /* parse the command arguments */
1624 printf ("Usage: %s <driver>\n", argv[0]);
1628 /* delete the driver for all architectures */
1629 for (i=0; archi_table[i].long_archi; i++) {
1630 /* make the call to remove the driver */
1631 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1632 cli->srv_name_slash,
1633 archi_table[i].long_archi,
1636 if (!NT_STATUS_IS_OK(status)) {
1639 if ( !W_ERROR_IS_OK(result) ) {
1640 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1641 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1642 argv[1], archi_table[i].long_archi,
1646 printf ("Driver %s removed for arch [%s].\n", argv[1],
1647 archi_table[i].long_archi);
1654 /****************************************************************************
1655 ****************************************************************************/
1657 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1658 TALLOC_CTX *mem_ctx,
1659 int argc, const char **argv)
1663 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1666 union spoolss_PrintProcessorDirectoryInfo info;
1669 /* parse the command arguments */
1671 printf ("Usage: %s [environment]\n", argv[0]);
1676 environment = argv[1];
1679 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1680 cli->srv_name_slash,
1688 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1690 buffer = data_blob_talloc_zero(mem_ctx, needed);
1692 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1693 cli->srv_name_slash,
1703 if (W_ERROR_IS_OK(result)) {
1704 printf("%s\n", info.info1.directory_name);
1710 /****************************************************************************
1711 ****************************************************************************/
1713 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1714 int argc, const char **argv)
1719 const char *printername;
1720 union spoolss_AddFormInfo info;
1721 struct spoolss_AddFormInfo1 info1;
1722 struct spoolss_AddFormInfo2 info2;
1725 /* Parse the command arguments */
1727 if (argc < 3 || argc > 5) {
1728 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1732 /* Get a printer handle */
1734 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1736 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1740 if (!W_ERROR_IS_OK(werror))
1743 /* Dummy up some values for the form data */
1746 level = atoi(argv[3]);
1751 info1.flags = SPOOLSS_FORM_USER;
1752 info1.form_name = argv[2];
1753 info1.size.width = 100;
1754 info1.size.height = 100;
1755 info1.area.left = 0;
1756 info1.area.top = 10;
1757 info1.area.right = 20;
1758 info1.area.bottom = 30;
1760 info.info1 = &info1;
1764 info2.flags = SPOOLSS_FORM_USER;
1765 info2.form_name = argv[2];
1766 info2.size.width = 100;
1767 info2.size.height = 100;
1768 info2.area.left = 0;
1769 info2.area.top = 10;
1770 info2.area.right = 20;
1771 info2.area.bottom = 30;
1772 info2.keyword = argv[2];
1773 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
1774 info2.mui_dll = NULL;
1775 info2.ressource_id = 0;
1776 info2.display_name = argv[2];
1779 info.info2 = &info2;
1787 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1794 if (is_valid_policy_hnd(&handle))
1795 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1800 /****************************************************************************
1801 ****************************************************************************/
1803 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1804 int argc, const char **argv)
1809 const char *printername;
1810 union spoolss_AddFormInfo info;
1811 struct spoolss_AddFormInfo1 info1;
1813 /* Parse the command arguments */
1816 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1820 /* Get a printer handle */
1822 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1824 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1826 SEC_FLAG_MAXIMUM_ALLOWED,
1828 if (!W_ERROR_IS_OK(werror))
1831 /* Dummy up some values for the form data */
1833 info1.flags = SPOOLSS_FORM_PRINTER;
1834 info1.size.width = 100;
1835 info1.size.height = 100;
1836 info1.area.left = 0;
1837 info1.area.top = 1000;
1838 info1.area.right = 2000;
1839 info1.area.bottom = 3000;
1840 info1.form_name = argv[2];
1842 info.info1 = &info1;
1846 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1854 if (is_valid_policy_hnd(&handle))
1855 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1860 /****************************************************************************
1861 ****************************************************************************/
1863 static const char *get_form_flag(int form_flag)
1865 switch (form_flag) {
1866 case SPOOLSS_FORM_USER:
1868 case SPOOLSS_FORM_BUILTIN:
1869 return "FORM_BUILTIN";
1870 case SPOOLSS_FORM_PRINTER:
1871 return "FORM_PRINTER";
1877 /****************************************************************************
1878 ****************************************************************************/
1880 static void display_form_info1(struct spoolss_FormInfo1 *r)
1883 "\tflag: %s (%d)\n" \
1884 "\twidth: %d, length: %d\n" \
1885 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1886 r->form_name, get_form_flag(r->flags), r->flags,
1887 r->size.width, r->size.height,
1888 r->area.left, r->area.right,
1889 r->area.top, r->area.bottom);
1892 /****************************************************************************
1893 ****************************************************************************/
1895 static void display_form_info2(struct spoolss_FormInfo2 *r)
1898 "\tflag: %s (%d)\n" \
1899 "\twidth: %d, length: %d\n" \
1900 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1901 r->form_name, get_form_flag(r->flags), r->flags,
1902 r->size.width, r->size.height,
1903 r->area.left, r->area.right,
1904 r->area.top, r->area.bottom);
1905 printf("\tkeyword: %s\n", r->keyword);
1906 printf("\tstring_type: 0x%08x\n", r->string_type);
1907 printf("\tmui_dll: %s\n", r->mui_dll);
1908 printf("\tressource_id: 0x%08x\n", r->ressource_id);
1909 printf("\tdisplay_name: %s\n", r->display_name);
1910 printf("\tlang_id: %d\n", r->lang_id);
1914 /****************************************************************************
1915 ****************************************************************************/
1917 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1918 int argc, const char **argv)
1923 const char *printername;
1925 uint32_t offered = 0;
1926 union spoolss_FormInfo info;
1930 /* Parse the command arguments */
1932 if (argc < 3 || argc > 5) {
1933 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1937 /* Get a printer handle */
1939 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1941 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1943 SEC_FLAG_MAXIMUM_ALLOWED,
1945 if (!W_ERROR_IS_OK(werror))
1949 level = atoi(argv[3]);
1954 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1963 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1964 buffer = data_blob_talloc_zero(mem_ctx, needed);
1966 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1977 if (!NT_STATUS_IS_OK(status)) {
1983 display_form_info1(&info.info1);
1986 display_form_info2(&info.info2);
1991 if (is_valid_policy_hnd(&handle))
1992 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1997 /****************************************************************************
1998 ****************************************************************************/
2000 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2001 TALLOC_CTX *mem_ctx, int argc,
2007 const char *printername;
2009 /* Parse the command arguments */
2012 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2016 /* Get a printer handle */
2018 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2020 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2022 SEC_FLAG_MAXIMUM_ALLOWED,
2024 if (!W_ERROR_IS_OK(werror))
2027 /* Delete the form */
2029 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2033 if (!NT_STATUS_IS_OK(status)) {
2034 return ntstatus_to_werror(status);
2038 if (is_valid_policy_hnd(&handle))
2039 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2044 /****************************************************************************
2045 ****************************************************************************/
2047 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2048 TALLOC_CTX *mem_ctx, int argc,
2053 const char *printername;
2054 uint32 num_forms, level = 1, i;
2055 union spoolss_FormInfo *forms;
2057 /* Parse the command arguments */
2059 if (argc < 2 || argc > 4) {
2060 printf ("Usage: %s <printer> [level]\n", argv[0]);
2064 /* Get a printer handle */
2066 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2068 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2070 SEC_FLAG_MAXIMUM_ALLOWED,
2072 if (!W_ERROR_IS_OK(werror))
2076 level = atoi(argv[2]);
2079 /* Enumerate forms */
2081 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2088 if (!W_ERROR_IS_OK(werror))
2091 /* Display output */
2093 for (i = 0; i < num_forms; i++) {
2096 display_form_info1(&forms[i].info1);
2099 display_form_info2(&forms[i].info2);
2105 if (is_valid_policy_hnd(&handle))
2106 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2111 /****************************************************************************
2112 ****************************************************************************/
2114 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2115 TALLOC_CTX *mem_ctx,
2116 int argc, const char **argv)
2120 const char *printername;
2122 union spoolss_PrinterInfo info;
2123 enum winreg_Type type;
2124 union spoolss_PrinterData data;
2126 /* parse the command arguments */
2128 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2129 " <value> <data>\n",
2131 result = WERR_INVALID_PARAM;
2135 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2139 if (strequal(argv[2], "string")) {
2143 if (strequal(argv[2], "binary")) {
2147 if (strequal(argv[2], "dword")) {
2151 if (strequal(argv[2], "multistring")) {
2152 type = REG_MULTI_SZ;
2155 if (type == REG_NONE) {
2156 printf("Unknown data type: %s\n", argv[2]);
2157 result = WERR_INVALID_PARAM;
2161 /* get a printer handle */
2163 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2165 SEC_FLAG_MAXIMUM_ALLOWED,
2167 if (!W_ERROR_IS_OK(result)) {
2171 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2176 if (!W_ERROR_IS_OK(result)) {
2180 printf("%s\n", current_timestring(mem_ctx, true));
2181 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2183 /* Set the printer data */
2187 data.string = talloc_strdup(mem_ctx, argv[4]);
2188 W_ERROR_HAVE_NO_MEMORY(data.string);
2191 data.value = strtoul(argv[4], NULL, 10);
2194 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2196 case REG_MULTI_SZ: {
2198 const char **strings = NULL;
2200 for (i=4; i<argc; i++) {
2201 if (strcmp(argv[i], "NULL") == 0) {
2204 if (!add_string_to_array(mem_ctx, argv[i],
2207 result = WERR_NOMEM;
2211 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2212 if (!data.string_array) {
2213 result = WERR_NOMEM;
2216 for (i=0; i < num_strings; i++) {
2217 data.string_array[i] = strings[i];
2222 printf("Unknown data type: %s\n", argv[2]);
2223 result = WERR_INVALID_PARAM;
2227 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2229 argv[3], /* value_name */
2232 0, /* autocalculated size */
2234 if (!W_ERROR_IS_OK(result)) {
2235 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2238 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2240 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2245 if (!W_ERROR_IS_OK(result)) {
2249 printf("%s\n", current_timestring(mem_ctx, true));
2250 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2254 if (is_valid_policy_hnd(&pol)) {
2255 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2261 /****************************************************************************
2262 ****************************************************************************/
2264 static void display_job_info1(struct spoolss_JobInfo1 *r)
2266 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2267 r->user_name, r->document_name, r->text_status, r->pages_printed,
2271 /****************************************************************************
2272 ****************************************************************************/
2274 static void display_job_info2(struct spoolss_JobInfo2 *r)
2276 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2277 r->position, r->job_id,
2278 r->user_name, r->document_name, r->text_status, r->pages_printed,
2279 r->total_pages, r->size);
2282 /****************************************************************************
2283 ****************************************************************************/
2285 static void display_job_info3(struct spoolss_JobInfo3 *r)
2287 printf("jobid[%d], next_jobid[%d]\n",
2288 r->job_id, r->next_job_id);
2291 /****************************************************************************
2292 ****************************************************************************/
2294 static void display_job_info4(struct spoolss_JobInfo4 *r)
2296 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2297 r->position, r->job_id,
2298 r->user_name, r->document_name, r->text_status, r->pages_printed,
2299 r->total_pages, r->size, r->size_high);
2302 /****************************************************************************
2303 ****************************************************************************/
2305 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2306 TALLOC_CTX *mem_ctx, int argc,
2310 uint32_t level = 1, count, i;
2311 const char *printername;
2313 union spoolss_JobInfo *info;
2315 if (argc < 2 || argc > 3) {
2316 printf("Usage: %s printername [level]\n", argv[0]);
2321 level = atoi(argv[2]);
2324 /* Open printer handle */
2326 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2328 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2330 SEC_FLAG_MAXIMUM_ALLOWED,
2332 if (!W_ERROR_IS_OK(result))
2335 /* Enumerate ports */
2337 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2345 if (!W_ERROR_IS_OK(result)) {
2349 for (i = 0; i < count; i++) {
2352 display_job_info1(&info[i].info1);
2355 display_job_info2(&info[i].info2);
2358 d_printf("unknown info level %d\n", level);
2364 if (is_valid_policy_hnd(&hnd)) {
2365 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2371 /****************************************************************************
2372 ****************************************************************************/
2374 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2375 TALLOC_CTX *mem_ctx, int argc,
2379 const char *printername;
2380 struct policy_handle hnd;
2383 union spoolss_JobInfo info;
2385 if (argc < 3 || argc > 4) {
2386 printf("Usage: %s printername job_id [level]\n", argv[0]);
2390 job_id = atoi(argv[2]);
2393 level = atoi(argv[3]);
2396 /* Open printer handle */
2398 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2400 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2402 SEC_FLAG_MAXIMUM_ALLOWED,
2404 if (!W_ERROR_IS_OK(result)) {
2408 /* Enumerate ports */
2410 result = rpccli_spoolss_getjob(cli, mem_ctx,
2417 if (!W_ERROR_IS_OK(result)) {
2423 display_job_info1(&info.info1);
2426 display_job_info2(&info.info2);
2429 display_job_info3(&info.info3);
2432 display_job_info4(&info.info4);
2435 d_printf("unknown info level %d\n", level);
2440 if (is_valid_policy_hnd(&hnd)) {
2441 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2448 /****************************************************************************
2449 ****************************************************************************/
2451 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2452 TALLOC_CTX *mem_ctx, int argc,
2458 const char *printername;
2460 uint32_t value_offered = 0;
2461 const char *value_name = NULL;
2462 uint32_t value_needed;
2463 enum winreg_Type type;
2464 uint8_t *data = NULL;
2465 uint32_t data_offered = 0;
2466 uint32_t data_needed;
2469 printf("Usage: %s printername\n", argv[0]);
2473 /* Open printer handle */
2475 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2477 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2479 SEC_FLAG_MAXIMUM_ALLOWED,
2481 if (!W_ERROR_IS_OK(result)) {
2485 /* Enumerate data */
2487 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2499 data_offered = data_needed;
2500 value_offered = value_needed;
2501 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2502 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2504 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2506 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2517 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2519 fstrcpy(v.valuename, value_name);
2521 v.size = data_offered;
2523 display_reg_value(v);
2527 if (W_ERROR_V(result) == ERRnomoreitems) {
2528 result = W_ERROR(ERRsuccess);
2532 if (is_valid_policy_hnd(&hnd)) {
2533 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2539 /****************************************************************************
2540 ****************************************************************************/
2542 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2543 TALLOC_CTX *mem_ctx, int argc,
2548 const char *printername;
2551 struct spoolss_PrinterEnumValues *info;
2554 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)) {
2570 /* Enumerate subkeys */
2572 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2578 if (!W_ERROR_IS_OK(result)) {
2582 for (i=0; i < count; i++) {
2583 display_printer_data(info[i].value_name,
2589 if (is_valid_policy_hnd(&hnd)) {
2590 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2596 /****************************************************************************
2597 ****************************************************************************/
2599 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2600 TALLOC_CTX *mem_ctx, int argc,
2604 const char *printername;
2605 const char *keyname = NULL;
2607 const char **key_buffer = NULL;
2610 if (argc < 2 || argc > 3) {
2611 printf("Usage: %s printername [keyname]\n", argv[0]);
2621 /* Open printer handle */
2623 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2625 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2627 SEC_FLAG_MAXIMUM_ALLOWED,
2629 if (!W_ERROR_IS_OK(result)) {
2633 /* Enumerate subkeys */
2635 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2641 if (!W_ERROR_IS_OK(result)) {
2645 for (i=0; key_buffer && key_buffer[i]; i++) {
2646 printf("%s\n", key_buffer[i]);
2651 if (is_valid_policy_hnd(&hnd)) {
2652 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2658 /****************************************************************************
2659 ****************************************************************************/
2661 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2662 TALLOC_CTX *mem_ctx, int argc,
2665 const char *printername;
2666 const char *clientname;
2670 struct spoolss_NotifyOption option;
2673 printf("Usage: %s printername\n", argv[0]);
2680 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2682 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2684 SEC_FLAG_MAXIMUM_ALLOWED,
2686 if (!W_ERROR_IS_OK(result)) {
2687 printf("Error opening %s\n", argv[1]);
2691 /* Create spool options */
2696 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2697 if (option.types == NULL) {
2698 result = WERR_NOMEM;
2702 option.types[0].type = PRINTER_NOTIFY_TYPE;
2703 option.types[0].count = 1;
2704 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2705 if (option.types[0].fields == NULL) {
2706 result = WERR_NOMEM;
2709 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
2711 option.types[1].type = JOB_NOTIFY_TYPE;
2712 option.types[1].count = 1;
2713 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2714 if (option.types[1].fields == NULL) {
2715 result = WERR_NOMEM;
2718 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
2720 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2722 result = WERR_NOMEM;
2728 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2736 if (!W_ERROR_IS_OK(result)) {
2737 printf("Error rffpcnex %s\n", argv[1]);
2742 if (is_valid_policy_hnd(&hnd))
2743 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2748 /****************************************************************************
2749 ****************************************************************************/
2751 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2752 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2754 union spoolss_PrinterInfo info1, info2;
2756 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2758 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2759 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2764 if ( !W_ERROR_IS_OK(werror) ) {
2765 printf("failed (%s)\n", win_errstr(werror));
2766 talloc_destroy(mem_ctx);
2771 printf("Retrieving printer properties for %s...", cli2->desthost);
2772 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2777 if ( !W_ERROR_IS_OK(werror) ) {
2778 printf("failed (%s)\n", win_errstr(werror));
2779 talloc_destroy(mem_ctx);
2784 talloc_destroy(mem_ctx);
2789 /****************************************************************************
2790 ****************************************************************************/
2792 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2793 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2795 union spoolss_PrinterInfo info1, info2;
2797 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2798 SEC_DESC *sd1, *sd2;
2802 printf("Retrieving printer security for %s...", cli1->desthost);
2803 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2808 if ( !W_ERROR_IS_OK(werror) ) {
2809 printf("failed (%s)\n", win_errstr(werror));
2815 printf("Retrieving printer security for %s...", cli2->desthost);
2816 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2821 if ( !W_ERROR_IS_OK(werror) ) {
2822 printf("failed (%s)\n", win_errstr(werror));
2831 sd1 = info1.info3.secdesc;
2832 sd2 = info2.info3.secdesc;
2834 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2835 printf("NULL secdesc!\n");
2840 if (!sec_desc_equal( sd1, sd2 ) ) {
2841 printf("Security Descriptors *not* equal!\n");
2846 printf("Security descriptors match\n");
2849 talloc_destroy(mem_ctx);
2854 /****************************************************************************
2855 ****************************************************************************/
2857 extern struct user_auth_info *rpcclient_auth_info;
2859 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2860 TALLOC_CTX *mem_ctx, int argc,
2863 const char *printername;
2864 char *printername_path = NULL;
2865 struct cli_state *cli_server2 = NULL;
2866 struct rpc_pipe_client *cli2 = NULL;
2867 POLICY_HND hPrinter1, hPrinter2;
2872 printf("Usage: %s <printer> <server>\n", argv[0]);
2876 printername = argv[1];
2878 /* first get the connection to the remote server */
2880 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2883 get_cmdline_auth_info_username(rpcclient_auth_info),
2885 get_cmdline_auth_info_password(rpcclient_auth_info),
2886 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2887 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2889 if ( !NT_STATUS_IS_OK(nt_status) )
2890 return WERR_GENERAL_FAILURE;
2892 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
2894 if (!NT_STATUS_IS_OK(nt_status)) {
2895 printf("failed to open spoolss pipe on server %s (%s)\n",
2896 argv[2], nt_errstr(nt_status));
2897 return WERR_GENERAL_FAILURE;
2900 /* now open up both printers */
2902 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2904 printf("Opening %s...", printername_path);
2906 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2910 if ( !W_ERROR_IS_OK(werror) ) {
2911 printf("failed (%s)\n", win_errstr(werror));
2916 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2918 printf("Opening %s...", printername_path);
2919 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2923 if ( !W_ERROR_IS_OK(werror) ) {
2924 printf("failed (%s)\n", win_errstr(werror));
2929 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2930 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2932 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2939 printf("Closing printers...");
2940 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2941 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2944 /* close the second remote connection */
2946 cli_shutdown( cli_server2 );
2950 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
2952 printf("print_processor_name: %s\n", r->print_processor_name);
2955 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
2956 TALLOC_CTX *mem_ctx, int argc,
2960 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2961 uint32_t num_procs, level = 1, i;
2962 union spoolss_PrintProcessorInfo *procs;
2964 /* Parse the command arguments */
2966 if (argc < 1 || argc > 4) {
2967 printf ("Usage: %s [environment] [level]\n", argv[0]);
2972 environment = argv[1];
2976 level = atoi(argv[2]);
2979 /* Enumerate Print Processors */
2981 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
2982 cli->srv_name_slash,
2988 if (!W_ERROR_IS_OK(werror))
2991 /* Display output */
2993 for (i = 0; i < num_procs; i++) {
2996 display_proc_info1(&procs[i].info1);
3005 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3007 printf("name_array: %s\n", r->name_array);
3010 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3011 TALLOC_CTX *mem_ctx, int argc,
3015 const char *print_processor_name = "winprint";
3016 uint32_t num_procs, level = 1, i;
3017 union spoolss_PrintProcDataTypesInfo *procs;
3019 /* Parse the command arguments */
3021 if (argc < 1 || argc > 4) {
3022 printf ("Usage: %s [environment] [level]\n", argv[0]);
3027 print_processor_name = argv[1];
3031 level = atoi(argv[2]);
3034 /* Enumerate Print Processor Data Types */
3036 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3037 cli->srv_name_slash,
3038 print_processor_name,
3043 if (!W_ERROR_IS_OK(werror))
3046 /* Display output */
3048 for (i = 0; i < num_procs; i++) {
3051 display_proc_data_types_info1(&procs[i].info1);
3060 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3062 printf("monitor_name: %s\n", r->monitor_name);
3065 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3067 printf("monitor_name: %s\n", r->monitor_name);
3068 printf("environment: %s\n", r->environment);
3069 printf("dll_name: %s\n", r->dll_name);
3072 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3073 TALLOC_CTX *mem_ctx, int argc,
3077 uint32_t count, level = 1, i;
3078 union spoolss_MonitorInfo *info;
3080 /* Parse the command arguments */
3083 printf("Usage: %s [level]\n", argv[0]);
3088 level = atoi(argv[1]);
3091 /* Enumerate Print Monitors */
3093 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3094 cli->srv_name_slash,
3099 if (!W_ERROR_IS_OK(werror)) {
3103 /* Display output */
3105 for (i = 0; i < count; i++) {
3108 display_monitor1(&info[i].info1);
3111 display_monitor2(&info[i].info2);
3120 /* List of commands exported by this module */
3121 struct cmd_set spoolss_commands[] = {
3125 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3126 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3127 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3128 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3129 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3130 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3131 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3132 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3133 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3134 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3135 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3136 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3137 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3138 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3139 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3140 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3141 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3142 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3143 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3144 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3145 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3146 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3147 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3148 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3149 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3150 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3151 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3152 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3153 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3154 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3155 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3156 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3157 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },