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)
108 struct policy_handle hnd;
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;
260 uint32_t flags = PRINTER_ENUM_LOCAL;
263 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
268 level = atoi(argv[1]);
274 name = cli->srv_name_slash;
278 flags = atoi(argv[3]);
281 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
288 if (W_ERROR_IS_OK(result)) {
291 printf ("No printers returned.\n");
295 for (i = 0; i < count; i++) {
298 display_print_info0(&info[i].info0);
301 display_print_info1(&info[i].info1);
304 display_print_info2(&info[i].info2);
307 display_print_info3(&info[i].info3);
310 printf("unknown info level %d\n", level);
320 /****************************************************************************
321 ****************************************************************************/
323 static void display_port_info_1(struct spoolss_PortInfo1 *r)
325 printf("\tPort Name:\t[%s]\n", r->port_name);
328 /****************************************************************************
329 ****************************************************************************/
331 static void display_port_info_2(struct spoolss_PortInfo2 *r)
333 printf("\tPort Name:\t[%s]\n", r->port_name);
334 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
335 printf("\tDescription:\t[%s]\n", r->description);
336 printf("\tPort Type:\t" );
338 int comma = 0; /* hack */
340 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
344 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
345 printf( "%sWrite", comma ? ", " : "" );
348 /* These two have slightly different interpretations
349 on 95/98/ME but I'm disregarding that for now */
350 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
351 printf( "%sRedirected", comma ? ", " : "" );
354 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
355 printf( "%sNet-Attached", comma ? ", " : "" );
359 printf( "[Unset]\n" );
361 printf("\tReserved:\t[%d]\n", r->reserved);
365 /****************************************************************************
366 ****************************************************************************/
368 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
369 TALLOC_CTX *mem_ctx, int argc,
375 union spoolss_PortInfo *info;
378 printf("Usage: %s [level]\n", argv[0]);
383 level = atoi(argv[1]);
386 /* Enumerate ports */
388 result = rpccli_spoolss_enumports(cli, mem_ctx,
394 if (W_ERROR_IS_OK(result)) {
397 for (i = 0; i < count; i++) {
400 display_port_info_1(&info[i].info1);
403 display_port_info_2(&info[i].info2);
406 printf("unknown info level %d\n", level);
415 /****************************************************************************
416 ****************************************************************************/
418 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
420 int argc, const char **argv)
422 struct policy_handle pol;
425 uint32_t info_level = 2;
426 union spoolss_PrinterInfo info;
427 struct spoolss_SetPrinterInfoCtr info_ctr;
428 const char *printername, *comment = NULL;
429 struct spoolss_DevmodeContainer devmode_ctr;
430 struct sec_desc_buf secdesc_ctr;
432 if (argc == 1 || argc > 3) {
433 printf("Usage: %s printername comment\n", argv[0]);
438 /* Open a printer handle */
443 ZERO_STRUCT(devmode_ctr);
444 ZERO_STRUCT(secdesc_ctr);
446 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
448 /* get a printer handle */
449 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
453 if (!W_ERROR_IS_OK(result))
456 /* Get printer info */
457 result = rpccli_spoolss_getprinter(cli, mem_ctx,
462 if (!W_ERROR_IS_OK(result))
466 /* Modify the comment. */
467 info.info2.comment = comment;
468 info.info2.secdesc = NULL;
469 info.info2.devmode = NULL;
472 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
474 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
481 if (W_ERROR_IS_OK(result))
482 printf("Success in setting comment.\n");
485 if (is_valid_policy_hnd(&pol))
486 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
491 /****************************************************************************
492 ****************************************************************************/
494 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
496 int argc, const char **argv)
498 struct policy_handle pol;
501 uint32_t info_level = 2;
502 union spoolss_PrinterInfo info;
503 const char *printername,
504 *new_printername = NULL;
505 struct spoolss_SetPrinterInfoCtr info_ctr;
506 struct spoolss_DevmodeContainer devmode_ctr;
507 struct sec_desc_buf secdesc_ctr;
509 ZERO_STRUCT(devmode_ctr);
510 ZERO_STRUCT(secdesc_ctr);
512 if (argc == 1 || argc > 3) {
513 printf("Usage: %s printername new_printername\n", argv[0]);
518 /* Open a printer handle */
520 new_printername = argv[2];
523 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
525 /* get a printer handle */
526 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
530 if (!W_ERROR_IS_OK(result))
533 /* Get printer info */
534 result = rpccli_spoolss_getprinter(cli, mem_ctx,
539 if (!W_ERROR_IS_OK(result))
542 /* Modify the printername. */
543 info.info2.printername = new_printername;
544 info.info2.devmode = NULL;
545 info.info2.secdesc = NULL;
547 info_ctr.level = info_level;
548 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
550 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
557 if (W_ERROR_IS_OK(result))
558 printf("Success in setting printername.\n");
561 if (is_valid_policy_hnd(&pol))
562 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
567 /****************************************************************************
568 ****************************************************************************/
570 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
572 int argc, const char **argv)
574 struct policy_handle pol;
577 const char *printername;
578 union spoolss_PrinterInfo info;
580 if (argc == 1 || argc > 3) {
581 printf("Usage: %s <printername> [level]\n", argv[0]);
585 /* Open a printer handle */
587 level = atoi(argv[2]);
590 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
592 /* get a printer handle */
594 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
596 SEC_FLAG_MAXIMUM_ALLOWED,
598 if (!W_ERROR_IS_OK(result)) {
602 /* Get printer info */
604 result = rpccli_spoolss_getprinter(cli, mem_ctx,
609 if (!W_ERROR_IS_OK(result)) {
613 /* Display printer info */
616 display_print_info0(&info.info0);
619 display_print_info1(&info.info1);
622 display_print_info2(&info.info2);
625 display_print_info3(&info.info3);
628 display_print_info7(&info.info7);
631 printf("unknown info level %d\n", level);
635 if (is_valid_policy_hnd(&pol)) {
636 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
642 /****************************************************************************
643 ****************************************************************************/
645 static void display_reg_value(REGISTRY_VALUE value)
651 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
652 *((uint32_t *) value.data_p));
655 rpcstr_pull_talloc(talloc_tos(),
660 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
663 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
665 printf("%s: REG_BINARY:", value.valuename);
667 for (i=0; i<len; i++) {
668 if (hex[i] == '\0') {
681 uint32_t i, num_values;
684 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
685 value.size, &num_values,
687 d_printf("reg_pull_multi_sz failed\n");
691 printf("%s: REG_MULTI_SZ: \n", value.valuename);
692 for (i=0; i<num_values; i++) {
693 d_printf("%s\n", values[i]);
699 printf("%s: unknown type %d\n", value.valuename, value.type);
704 /****************************************************************************
705 ****************************************************************************/
707 static void display_printer_data(const char *v,
708 enum winreg_Type type,
709 union spoolss_PrinterData *r)
715 printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
718 printf("%s: REG_SZ: %s\n", v, r->string);
721 char *hex = hex_encode_talloc(NULL,
722 r->binary.data, r->binary.length);
724 printf("%s: REG_BINARY:", v);
726 for (i=0; i<len; i++) {
727 if (hex[i] == '\0') {
740 printf("%s: REG_MULTI_SZ: ", v);
741 for (i=0; r->string_array[i] != NULL; i++) {
742 printf("%s ", r->string_array[i]);
747 printf("%s: unknown type 0x%02x:\n", v, type);
752 /****************************************************************************
753 ****************************************************************************/
755 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
757 int argc, const char **argv)
759 struct policy_handle pol;
762 const char *valuename;
763 enum winreg_Type type;
764 union spoolss_PrinterData data;
767 printf("Usage: %s <printername> <valuename>\n", argv[0]);
768 printf("<printername> of . queries print server\n");
773 /* Open a printer handle */
775 if (strncmp(argv[1], ".", sizeof(".")) == 0)
776 fstrcpy(printername, cli->srv_name_slash);
778 slprintf(printername, sizeof(printername)-1, "%s\\%s",
779 cli->srv_name_slash, argv[1]);
781 /* get a printer handle */
783 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
785 SEC_FLAG_MAXIMUM_ALLOWED,
787 if (!W_ERROR_IS_OK(result))
790 /* Get printer info */
792 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
798 if (!W_ERROR_IS_OK(result))
801 /* Display printer data */
803 display_printer_data(valuename, type, &data);
806 if (is_valid_policy_hnd(&pol))
807 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
812 /****************************************************************************
813 ****************************************************************************/
815 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
817 int argc, const char **argv)
819 struct policy_handle pol;
823 const char *valuename, *keyname;
824 REGISTRY_VALUE value;
826 enum winreg_Type type;
827 uint8_t *buffer = NULL;
828 uint32_t offered = 0;
832 printf("Usage: %s <printername> <keyname> <valuename>\n",
834 printf("<printername> of . queries print server\n");
840 /* Open a printer handle */
842 if (strncmp(argv[1], ".", sizeof(".")) == 0)
843 fstrcpy(printername, cli->srv_name_slash);
845 slprintf(printername, sizeof(printername)-1, "%s\\%s",
846 cli->srv_name_slash, argv[1]);
848 /* get a printer handle */
850 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
852 SEC_FLAG_MAXIMUM_ALLOWED,
854 if (!W_ERROR_IS_OK(result))
857 /* Get printer info */
859 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
868 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
870 buffer = talloc_array(mem_ctx, uint8_t, needed);
871 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
882 if (!NT_STATUS_IS_OK(status)) {
886 if (!W_ERROR_IS_OK(result)) {
891 if (!W_ERROR_IS_OK(result))
894 /* Display printer data */
896 fstrcpy(value.valuename, valuename);
899 value.data_p = buffer;
901 display_reg_value(value);
904 if (is_valid_policy_hnd(&pol))
905 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
910 /****************************************************************************
911 ****************************************************************************/
913 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
919 printf("Printer Driver Info 1:\n");
920 printf("\tDriver Name: [%s]\n\n", r->driver_name);
923 /****************************************************************************
924 ****************************************************************************/
926 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
932 printf("Printer Driver Info 2:\n");
933 printf("\tVersion: [%x]\n", r->version);
934 printf("\tDriver Name: [%s]\n", r->driver_name);
935 printf("\tArchitecture: [%s]\n", r->architecture);
936 printf("\tDriver Path: [%s]\n", r->driver_path);
937 printf("\tDatafile: [%s]\n", r->data_file);
938 printf("\tConfigfile: [%s]\n\n", r->config_file);
941 /****************************************************************************
942 ****************************************************************************/
944 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
952 printf("Printer Driver Info 3:\n");
953 printf("\tVersion: [%x]\n", r->version);
954 printf("\tDriver Name: [%s]\n", r->driver_name);
955 printf("\tArchitecture: [%s]\n", r->architecture);
956 printf("\tDriver Path: [%s]\n", r->driver_path);
957 printf("\tDatafile: [%s]\n", r->data_file);
958 printf("\tConfigfile: [%s]\n\n", r->config_file);
959 printf("\tHelpfile: [%s]\n\n", r->help_file);
961 for (i=0; r->dependent_files[i] != NULL; i++) {
962 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
967 printf("\tMonitorname: [%s]\n", r->monitor_name);
968 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
972 /****************************************************************************
973 ****************************************************************************/
975 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
977 int argc, const char **argv)
979 struct policy_handle pol;
982 const char *printername;
984 bool success = false;
985 union spoolss_DriverInfo info;
986 uint32_t server_major_version;
987 uint32_t server_minor_version;
989 if ((argc == 1) || (argc > 3)) {
990 printf("Usage: %s <printername> [level]\n", argv[0]);
994 /* get the arguments need to open the printer handle */
996 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
999 level = atoi(argv[2]);
1002 /* Open a printer handle */
1004 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1008 if (!W_ERROR_IS_OK(werror)) {
1009 printf("Error opening printer handle for %s!\n", printername);
1013 /* loop through and print driver info level for each architecture */
1015 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1017 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1019 archi_table[i].long_archi,
1022 archi_table[i].version,
1025 &server_major_version,
1026 &server_minor_version);
1027 if (!W_ERROR_IS_OK(werror)) {
1031 /* need at least one success */
1035 printf("\n[%s]\n", archi_table[i].long_archi);
1039 display_print_driver1(&info.info1);
1042 display_print_driver2(&info.info2);
1045 display_print_driver3(&info.info3);
1048 printf("unknown info level %d\n", level);
1055 if (is_valid_policy_hnd(&pol)) {
1056 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1066 /****************************************************************************
1067 ****************************************************************************/
1069 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1070 TALLOC_CTX *mem_ctx,
1071 int argc, const char **argv)
1073 WERROR werror = WERR_OK;
1075 union spoolss_DriverInfo *info;
1076 uint32_t i, j, count;
1079 printf("Usage: enumdrivers [level]\n");
1084 level = atoi(argv[1]);
1088 /* loop through and print driver info level for each architecture */
1089 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1090 /* check to see if we already asked for this architecture string */
1092 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1096 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1097 cli->srv_name_slash,
1098 archi_table[i].long_archi,
1104 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1105 printf("Server does not support environment [%s]\n",
1106 archi_table[i].long_archi);
1115 if (!W_ERROR_IS_OK(werror)) {
1116 printf("Error getting driver for environment [%s] - %d\n",
1117 archi_table[i].long_archi, W_ERROR_V(werror));
1121 printf("\n[%s]\n", archi_table[i].long_archi);
1125 for (j=0; j < count; j++) {
1126 display_print_driver1(&info[j].info1);
1130 for (j=0; j < count; j++) {
1131 display_print_driver2(&info[j].info2);
1135 for (j=0; j < count; j++) {
1136 display_print_driver3(&info[j].info3);
1140 printf("unknown info level %d\n", level);
1141 return WERR_UNKNOWN_LEVEL;
1148 /****************************************************************************
1149 ****************************************************************************/
1151 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1153 printf("\tDirectory Name:[%s]\n", r->directory_name);
1156 /****************************************************************************
1157 ****************************************************************************/
1159 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1160 TALLOC_CTX *mem_ctx,
1161 int argc, const char **argv)
1165 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1168 union spoolss_DriverDirectoryInfo info;
1172 printf("Usage: %s [environment]\n", argv[0]);
1176 /* Get the arguments need to open the printer handle */
1182 /* Get the directory. Only use Info level 1 */
1184 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1185 cli->srv_name_slash,
1193 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1195 buffer = data_blob_talloc_zero(mem_ctx, needed);
1197 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1198 cli->srv_name_slash,
1208 if (W_ERROR_IS_OK(result)) {
1209 display_printdriverdir_1(&info.info1);
1215 /****************************************************************************
1216 ****************************************************************************/
1218 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1219 struct spoolss_AddDriverInfo3 *info,
1225 for (i=0; archi_table[i].long_archi != NULL; i++)
1227 if (strcmp(arch, archi_table[i].short_archi) == 0)
1229 info->version = archi_table[i].version;
1230 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1235 if (archi_table[i].long_archi == NULL)
1237 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1244 /**************************************************************************
1245 wrapper for strtok to get the next parameter from a delimited list.
1246 Needed to handle the empty parameter string denoted by "NULL"
1247 *************************************************************************/
1249 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1250 const char *delim, const char **dest,
1255 /* get the next token */
1256 ptr = strtok_r(str, delim, saveptr);
1258 /* a string of 'NULL' is used to represent an empty
1259 parameter because two consecutive delimiters
1260 will not return an empty string. See man strtok(3)
1262 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1267 *dest = talloc_strdup(mem_ctx, ptr);
1273 /********************************************************************************
1274 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1275 string in the form of
1276 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1277 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1278 <Default Data Type>:<Comma Separated list of Files>
1279 *******************************************************************************/
1281 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1286 char *saveptr = NULL;
1287 struct spoolss_StringArray *deps;
1288 const char **file_array = NULL;
1291 /* fill in the UNISTR fields */
1292 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1293 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1294 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1295 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1296 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1297 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1298 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1300 /* <Comma Separated List of Dependent Files> */
1301 /* save the beginning of the string */
1302 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1305 /* begin to strip out each filename */
1306 str = strtok_r(str, ",", &saveptr);
1308 /* no dependent files, we are done */
1313 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1318 while (str != NULL) {
1319 add_string_to_array(deps, str, &file_array, &count);
1320 str = strtok_r(NULL, ",", &saveptr);
1323 deps->string = talloc_zero_array(deps, const char *, count + 1);
1324 if (!deps->string) {
1328 for (i=0; i < count; i++) {
1329 deps->string[i] = file_array[i];
1332 r->dependent_files = deps;
1337 /****************************************************************************
1338 ****************************************************************************/
1340 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1341 TALLOC_CTX *mem_ctx,
1342 int argc, const char **argv)
1347 struct spoolss_AddDriverInfoCtr info_ctr;
1348 struct spoolss_AddDriverInfo3 info3;
1352 /* parse the command arguments */
1353 if (argc != 3 && argc != 4)
1355 printf ("Usage: %s <Environment> \\\n", argv[0]);
1356 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1357 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1358 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1359 printf ("\t[version]\n");
1364 /* Fill in the spoolss_AddDriverInfo3 struct */
1367 arch = cmd_spoolss_get_short_archi(argv[1]);
1369 printf ("Error Unknown architechture [%s]\n", argv[1]);
1370 return WERR_INVALID_PARAM;
1373 set_drv_info_3_env(mem_ctx, &info3, arch);
1375 driver_args = talloc_strdup( mem_ctx, argv[2] );
1376 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1378 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1379 return WERR_INVALID_PARAM;
1382 /* if printer driver version specified, override the default version
1383 * used by the architecture. This allows installation of Windows
1384 * 2000 (version 3) printer drivers. */
1387 info3.version = atoi(argv[3]);
1391 info_ctr.level = level;
1392 info_ctr.info.info3 = &info3;
1394 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1395 cli->srv_name_slash,
1398 if (!NT_STATUS_IS_OK(status)) {
1399 return ntstatus_to_werror(status);
1401 if (W_ERROR_IS_OK(result)) {
1402 printf ("Printer Driver %s successfully installed.\n",
1410 /****************************************************************************
1411 ****************************************************************************/
1413 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1414 TALLOC_CTX *mem_ctx,
1415 int argc, const char **argv)
1418 struct spoolss_SetPrinterInfoCtr info_ctr;
1419 struct spoolss_SetPrinterInfo2 info2;
1421 /* parse the command arguments */
1424 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1428 /* Fill in the DRIVER_INFO_2 struct */
1431 info2.printername = argv[1];
1432 info2.drivername = argv[3];
1433 info2.sharename = argv[2];
1434 info2.portname = argv[4];
1435 info2.comment = "Created by rpcclient";
1436 info2.printprocessor = "winprint";
1437 info2.datatype = "RAW";
1438 info2.devmode = NULL;
1439 info2.secdesc = NULL;
1440 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1442 info2.defaultpriority = 0;
1443 info2.starttime = 0;
1444 info2.untiltime = 0;
1446 /* These three fields must not be used by AddPrinter()
1447 as defined in the MS Platform SDK documentation..
1451 info2.averageppm = 0;
1455 info_ctr.info.info2 = &info2;
1457 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1459 if (W_ERROR_IS_OK(result))
1460 printf ("Printer %s successfully installed.\n", argv[1]);
1465 /****************************************************************************
1466 ****************************************************************************/
1468 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1469 TALLOC_CTX *mem_ctx,
1470 int argc, const char **argv)
1472 struct policy_handle pol;
1476 const char *printername;
1477 union spoolss_PrinterInfo info;
1478 struct spoolss_SetPrinterInfoCtr info_ctr;
1479 struct spoolss_DevmodeContainer devmode_ctr;
1480 struct sec_desc_buf secdesc_ctr;
1482 ZERO_STRUCT(devmode_ctr);
1483 ZERO_STRUCT(secdesc_ctr);
1485 /* parse the command arguments */
1488 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1492 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1494 /* Get a printer handle */
1496 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1500 if (!W_ERROR_IS_OK(result))
1503 /* Get printer info */
1505 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1510 if (!W_ERROR_IS_OK(result)) {
1511 printf ("Unable to retrieve printer information!\n");
1515 /* Set the printer driver */
1517 info.info2.drivername = argv[2];
1518 info.info2.devmode = NULL;
1519 info.info2.secdesc = NULL;
1522 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1524 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1531 if (!W_ERROR_IS_OK(result)) {
1532 printf("SetPrinter call failed!\n");
1536 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1541 if (is_valid_policy_hnd(&pol))
1542 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1548 /****************************************************************************
1549 ****************************************************************************/
1551 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1552 TALLOC_CTX *mem_ctx,
1553 int argc, const char **argv)
1555 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1561 const char *arch = NULL;
1562 uint32_t delete_flags = 0;
1564 /* parse the command arguments */
1565 if (argc < 2 || argc > 4) {
1566 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1573 vers = atoi (argv[3]);
1576 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1579 /* delete the driver for all architectures */
1580 for (i=0; archi_table[i].long_archi; i++) {
1582 if (arch && !strequal( archi_table[i].long_archi, arch))
1585 if (vers >= 0 && archi_table[i].version != vers)
1588 /* make the call to remove the driver */
1589 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1590 cli->srv_name_slash,
1591 archi_table[i].long_archi,
1594 archi_table[i].version,
1597 if ( !W_ERROR_IS_OK(result) )
1599 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1600 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1601 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1606 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1607 archi_table[i].long_archi, archi_table[i].version);
1616 /****************************************************************************
1617 ****************************************************************************/
1619 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1620 TALLOC_CTX *mem_ctx,
1621 int argc, const char **argv)
1623 WERROR result = WERR_OK;
1627 /* parse the command arguments */
1629 printf ("Usage: %s <driver>\n", argv[0]);
1633 /* delete the driver for all architectures */
1634 for (i=0; archi_table[i].long_archi; i++) {
1635 /* make the call to remove the driver */
1636 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1637 cli->srv_name_slash,
1638 archi_table[i].long_archi,
1641 if (!NT_STATUS_IS_OK(status)) {
1644 if ( !W_ERROR_IS_OK(result) ) {
1645 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1646 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1647 argv[1], archi_table[i].long_archi,
1651 printf ("Driver %s removed for arch [%s].\n", argv[1],
1652 archi_table[i].long_archi);
1659 /****************************************************************************
1660 ****************************************************************************/
1662 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1663 TALLOC_CTX *mem_ctx,
1664 int argc, const char **argv)
1668 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1671 union spoolss_PrintProcessorDirectoryInfo info;
1674 /* parse the command arguments */
1676 printf ("Usage: %s [environment]\n", argv[0]);
1681 environment = argv[1];
1684 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1685 cli->srv_name_slash,
1693 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1695 buffer = data_blob_talloc_zero(mem_ctx, needed);
1697 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1698 cli->srv_name_slash,
1708 if (W_ERROR_IS_OK(result)) {
1709 printf("%s\n", info.info1.directory_name);
1715 /****************************************************************************
1716 ****************************************************************************/
1718 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1719 int argc, const char **argv)
1721 struct policy_handle handle;
1724 const char *printername;
1725 union spoolss_AddFormInfo info;
1726 struct spoolss_AddFormInfo1 info1;
1727 struct spoolss_AddFormInfo2 info2;
1730 /* Parse the command arguments */
1732 if (argc < 3 || argc > 5) {
1733 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1737 /* Get a printer handle */
1739 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1741 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1745 if (!W_ERROR_IS_OK(werror))
1748 /* Dummy up some values for the form data */
1751 level = atoi(argv[3]);
1756 info1.flags = SPOOLSS_FORM_USER;
1757 info1.form_name = argv[2];
1758 info1.size.width = 100;
1759 info1.size.height = 100;
1760 info1.area.left = 0;
1761 info1.area.top = 10;
1762 info1.area.right = 20;
1763 info1.area.bottom = 30;
1765 info.info1 = &info1;
1769 info2.flags = SPOOLSS_FORM_USER;
1770 info2.form_name = argv[2];
1771 info2.size.width = 100;
1772 info2.size.height = 100;
1773 info2.area.left = 0;
1774 info2.area.top = 10;
1775 info2.area.right = 20;
1776 info2.area.bottom = 30;
1777 info2.keyword = argv[2];
1778 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
1779 info2.mui_dll = NULL;
1780 info2.ressource_id = 0;
1781 info2.display_name = argv[2];
1784 info.info2 = &info2;
1792 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1799 if (is_valid_policy_hnd(&handle))
1800 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1805 /****************************************************************************
1806 ****************************************************************************/
1808 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1809 int argc, const char **argv)
1811 struct policy_handle handle;
1814 const char *printername;
1815 union spoolss_AddFormInfo info;
1816 struct spoolss_AddFormInfo1 info1;
1818 /* Parse the command arguments */
1821 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1825 /* Get a printer handle */
1827 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1829 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1831 SEC_FLAG_MAXIMUM_ALLOWED,
1833 if (!W_ERROR_IS_OK(werror))
1836 /* Dummy up some values for the form data */
1838 info1.flags = SPOOLSS_FORM_PRINTER;
1839 info1.size.width = 100;
1840 info1.size.height = 100;
1841 info1.area.left = 0;
1842 info1.area.top = 1000;
1843 info1.area.right = 2000;
1844 info1.area.bottom = 3000;
1845 info1.form_name = argv[2];
1847 info.info1 = &info1;
1851 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1859 if (is_valid_policy_hnd(&handle))
1860 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1865 /****************************************************************************
1866 ****************************************************************************/
1868 static const char *get_form_flag(int form_flag)
1870 switch (form_flag) {
1871 case SPOOLSS_FORM_USER:
1873 case SPOOLSS_FORM_BUILTIN:
1874 return "FORM_BUILTIN";
1875 case SPOOLSS_FORM_PRINTER:
1876 return "FORM_PRINTER";
1882 /****************************************************************************
1883 ****************************************************************************/
1885 static void display_form_info1(struct spoolss_FormInfo1 *r)
1888 "\tflag: %s (%d)\n" \
1889 "\twidth: %d, length: %d\n" \
1890 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1891 r->form_name, get_form_flag(r->flags), r->flags,
1892 r->size.width, r->size.height,
1893 r->area.left, r->area.right,
1894 r->area.top, r->area.bottom);
1897 /****************************************************************************
1898 ****************************************************************************/
1900 static void display_form_info2(struct spoolss_FormInfo2 *r)
1903 "\tflag: %s (%d)\n" \
1904 "\twidth: %d, length: %d\n" \
1905 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1906 r->form_name, get_form_flag(r->flags), r->flags,
1907 r->size.width, r->size.height,
1908 r->area.left, r->area.right,
1909 r->area.top, r->area.bottom);
1910 printf("\tkeyword: %s\n", r->keyword);
1911 printf("\tstring_type: 0x%08x\n", r->string_type);
1912 printf("\tmui_dll: %s\n", r->mui_dll);
1913 printf("\tressource_id: 0x%08x\n", r->ressource_id);
1914 printf("\tdisplay_name: %s\n", r->display_name);
1915 printf("\tlang_id: %d\n", r->lang_id);
1919 /****************************************************************************
1920 ****************************************************************************/
1922 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1923 int argc, const char **argv)
1925 struct policy_handle handle;
1928 const char *printername;
1930 uint32_t offered = 0;
1931 union spoolss_FormInfo info;
1935 /* Parse the command arguments */
1937 if (argc < 3 || argc > 5) {
1938 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1942 /* Get a printer handle */
1944 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1946 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1948 SEC_FLAG_MAXIMUM_ALLOWED,
1950 if (!W_ERROR_IS_OK(werror))
1954 level = atoi(argv[3]);
1959 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1968 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
1969 buffer = data_blob_talloc_zero(mem_ctx, needed);
1971 status = rpccli_spoolss_GetForm(cli, mem_ctx,
1982 if (!NT_STATUS_IS_OK(status)) {
1988 display_form_info1(&info.info1);
1991 display_form_info2(&info.info2);
1996 if (is_valid_policy_hnd(&handle))
1997 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2002 /****************************************************************************
2003 ****************************************************************************/
2005 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2006 TALLOC_CTX *mem_ctx, int argc,
2009 struct policy_handle handle;
2012 const char *printername;
2014 /* Parse the command arguments */
2017 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2021 /* Get a printer handle */
2023 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2025 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2027 SEC_FLAG_MAXIMUM_ALLOWED,
2029 if (!W_ERROR_IS_OK(werror))
2032 /* Delete the form */
2034 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2038 if (!NT_STATUS_IS_OK(status)) {
2039 return ntstatus_to_werror(status);
2043 if (is_valid_policy_hnd(&handle))
2044 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2049 /****************************************************************************
2050 ****************************************************************************/
2052 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2053 TALLOC_CTX *mem_ctx, int argc,
2056 struct policy_handle handle;
2058 const char *printername;
2059 uint32_t num_forms, level = 1, i;
2060 union spoolss_FormInfo *forms;
2062 /* Parse the command arguments */
2064 if (argc < 2 || argc > 4) {
2065 printf ("Usage: %s <printer> [level]\n", argv[0]);
2069 /* Get a printer handle */
2071 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2073 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2075 SEC_FLAG_MAXIMUM_ALLOWED,
2077 if (!W_ERROR_IS_OK(werror))
2081 level = atoi(argv[2]);
2084 /* Enumerate forms */
2086 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2093 if (!W_ERROR_IS_OK(werror))
2096 /* Display output */
2098 for (i = 0; i < num_forms; i++) {
2101 display_form_info1(&forms[i].info1);
2104 display_form_info2(&forms[i].info2);
2110 if (is_valid_policy_hnd(&handle))
2111 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2116 /****************************************************************************
2117 ****************************************************************************/
2119 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2120 TALLOC_CTX *mem_ctx,
2121 int argc, const char **argv)
2125 const char *printername;
2126 struct policy_handle pol;
2127 union spoolss_PrinterInfo info;
2128 enum winreg_Type type;
2129 union spoolss_PrinterData data;
2131 /* parse the command arguments */
2133 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2134 " <value> <data>\n",
2136 result = WERR_INVALID_PARAM;
2140 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2144 if (strequal(argv[2], "string")) {
2148 if (strequal(argv[2], "binary")) {
2152 if (strequal(argv[2], "dword")) {
2156 if (strequal(argv[2], "multistring")) {
2157 type = REG_MULTI_SZ;
2160 if (type == REG_NONE) {
2161 printf("Unknown data type: %s\n", argv[2]);
2162 result = WERR_INVALID_PARAM;
2166 /* get a printer handle */
2168 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2170 SEC_FLAG_MAXIMUM_ALLOWED,
2172 if (!W_ERROR_IS_OK(result)) {
2176 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2181 if (!W_ERROR_IS_OK(result)) {
2185 printf("%s\n", current_timestring(mem_ctx, true));
2186 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2188 /* Set the printer data */
2192 data.string = talloc_strdup(mem_ctx, argv[4]);
2193 W_ERROR_HAVE_NO_MEMORY(data.string);
2196 data.value = strtoul(argv[4], NULL, 10);
2199 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2201 case REG_MULTI_SZ: {
2203 const char **strings = NULL;
2205 for (i=4; i<argc; i++) {
2206 if (strcmp(argv[i], "NULL") == 0) {
2209 if (!add_string_to_array(mem_ctx, argv[i],
2212 result = WERR_NOMEM;
2216 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2217 if (!data.string_array) {
2218 result = WERR_NOMEM;
2221 for (i=0; i < num_strings; i++) {
2222 data.string_array[i] = strings[i];
2227 printf("Unknown data type: %s\n", argv[2]);
2228 result = WERR_INVALID_PARAM;
2232 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2234 argv[3], /* value_name */
2237 0, /* autocalculated size */
2239 if (!W_ERROR_IS_OK(result)) {
2240 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2243 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2245 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2250 if (!W_ERROR_IS_OK(result)) {
2254 printf("%s\n", current_timestring(mem_ctx, true));
2255 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2259 if (is_valid_policy_hnd(&pol)) {
2260 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2266 /****************************************************************************
2267 ****************************************************************************/
2269 static void display_job_info1(struct spoolss_JobInfo1 *r)
2271 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2272 r->user_name, r->document_name, r->text_status, r->pages_printed,
2276 /****************************************************************************
2277 ****************************************************************************/
2279 static void display_job_info2(struct spoolss_JobInfo2 *r)
2281 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2282 r->position, r->job_id,
2283 r->user_name, r->document_name, r->text_status, r->pages_printed,
2284 r->total_pages, r->size);
2287 /****************************************************************************
2288 ****************************************************************************/
2290 static void display_job_info3(struct spoolss_JobInfo3 *r)
2292 printf("jobid[%d], next_jobid[%d]\n",
2293 r->job_id, r->next_job_id);
2296 /****************************************************************************
2297 ****************************************************************************/
2299 static void display_job_info4(struct spoolss_JobInfo4 *r)
2301 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2302 r->position, r->job_id,
2303 r->user_name, r->document_name, r->text_status, r->pages_printed,
2304 r->total_pages, r->size, r->size_high);
2307 /****************************************************************************
2308 ****************************************************************************/
2310 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2311 TALLOC_CTX *mem_ctx, int argc,
2315 uint32_t level = 1, count, i;
2316 const char *printername;
2317 struct policy_handle hnd;
2318 union spoolss_JobInfo *info;
2320 if (argc < 2 || argc > 3) {
2321 printf("Usage: %s printername [level]\n", argv[0]);
2326 level = atoi(argv[2]);
2329 /* Open printer handle */
2331 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2333 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2335 SEC_FLAG_MAXIMUM_ALLOWED,
2337 if (!W_ERROR_IS_OK(result))
2340 /* Enumerate ports */
2342 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2350 if (!W_ERROR_IS_OK(result)) {
2354 for (i = 0; i < count; i++) {
2357 display_job_info1(&info[i].info1);
2360 display_job_info2(&info[i].info2);
2363 d_printf("unknown info level %d\n", level);
2369 if (is_valid_policy_hnd(&hnd)) {
2370 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2376 /****************************************************************************
2377 ****************************************************************************/
2379 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2380 TALLOC_CTX *mem_ctx, int argc,
2384 const char *printername;
2385 struct policy_handle hnd;
2388 union spoolss_JobInfo info;
2390 if (argc < 3 || argc > 4) {
2391 printf("Usage: %s printername job_id [level]\n", argv[0]);
2395 job_id = atoi(argv[2]);
2398 level = atoi(argv[3]);
2401 /* Open printer handle */
2403 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2405 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2407 SEC_FLAG_MAXIMUM_ALLOWED,
2409 if (!W_ERROR_IS_OK(result)) {
2413 /* Enumerate ports */
2415 result = rpccli_spoolss_getjob(cli, mem_ctx,
2422 if (!W_ERROR_IS_OK(result)) {
2428 display_job_info1(&info.info1);
2431 display_job_info2(&info.info2);
2434 display_job_info3(&info.info3);
2437 display_job_info4(&info.info4);
2440 d_printf("unknown info level %d\n", level);
2445 if (is_valid_policy_hnd(&hnd)) {
2446 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2452 /****************************************************************************
2453 ****************************************************************************/
2455 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2456 TALLOC_CTX *mem_ctx, int argc,
2461 const char *printername;
2462 struct policy_handle hnd;
2464 enum spoolss_JobControl command;
2467 printf("Usage: %s printername job_id command\n", argv[0]);
2471 job_id = atoi(argv[2]);
2472 command = atoi(argv[3]);
2474 /* Open printer handle */
2476 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2478 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2480 SEC_FLAG_MAXIMUM_ALLOWED,
2482 if (!W_ERROR_IS_OK(result)) {
2488 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2495 if (!W_ERROR_IS_OK(result)) {
2500 if (is_valid_policy_hnd(&hnd)) {
2501 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2507 /****************************************************************************
2508 ****************************************************************************/
2510 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2511 TALLOC_CTX *mem_ctx, int argc,
2517 const char *printername;
2518 struct policy_handle hnd;
2519 uint32_t value_offered = 0;
2520 const char *value_name = NULL;
2521 uint32_t value_needed;
2522 enum winreg_Type type;
2523 uint8_t *data = NULL;
2524 uint32_t data_offered = 0;
2525 uint32_t data_needed;
2528 printf("Usage: %s printername\n", argv[0]);
2532 /* Open printer handle */
2534 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2536 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2538 SEC_FLAG_MAXIMUM_ALLOWED,
2540 if (!W_ERROR_IS_OK(result)) {
2544 /* Enumerate data */
2546 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2558 data_offered = data_needed;
2559 value_offered = value_needed;
2560 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2561 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2563 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2565 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2576 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2578 fstrcpy(v.valuename, value_name);
2580 v.size = data_offered;
2582 display_reg_value(v);
2586 if (W_ERROR_V(result) == ERRnomoreitems) {
2587 result = W_ERROR(ERRsuccess);
2591 if (is_valid_policy_hnd(&hnd)) {
2592 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2598 /****************************************************************************
2599 ****************************************************************************/
2601 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2602 TALLOC_CTX *mem_ctx, int argc,
2607 const char *printername;
2608 struct policy_handle hnd;
2610 struct spoolss_PrinterEnumValues *info;
2613 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_enumprinterdataex(cli, mem_ctx,
2637 if (!W_ERROR_IS_OK(result)) {
2641 for (i=0; i < count; i++) {
2642 display_printer_data(info[i].value_name,
2648 if (is_valid_policy_hnd(&hnd)) {
2649 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2655 /****************************************************************************
2656 ****************************************************************************/
2658 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2659 TALLOC_CTX *mem_ctx, int argc,
2663 const char *printername;
2664 const char *keyname = NULL;
2665 struct policy_handle hnd;
2666 const char **key_buffer = NULL;
2669 if (argc < 2 || argc > 3) {
2670 printf("Usage: %s printername [keyname]\n", argv[0]);
2680 /* Open printer handle */
2682 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2684 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2686 SEC_FLAG_MAXIMUM_ALLOWED,
2688 if (!W_ERROR_IS_OK(result)) {
2692 /* Enumerate subkeys */
2694 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2700 if (!W_ERROR_IS_OK(result)) {
2704 for (i=0; key_buffer && key_buffer[i]; i++) {
2705 printf("%s\n", key_buffer[i]);
2710 if (is_valid_policy_hnd(&hnd)) {
2711 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2717 /****************************************************************************
2718 ****************************************************************************/
2720 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2721 TALLOC_CTX *mem_ctx, int argc,
2724 const char *printername;
2725 const char *clientname;
2726 struct policy_handle hnd;
2729 struct spoolss_NotifyOption option;
2732 printf("Usage: %s printername\n", argv[0]);
2739 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2741 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2743 SEC_FLAG_MAXIMUM_ALLOWED,
2745 if (!W_ERROR_IS_OK(result)) {
2746 printf("Error opening %s\n", argv[1]);
2750 /* Create spool options */
2755 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2756 if (option.types == NULL) {
2757 result = WERR_NOMEM;
2761 option.types[0].type = PRINTER_NOTIFY_TYPE;
2762 option.types[0].count = 1;
2763 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2764 if (option.types[0].fields == NULL) {
2765 result = WERR_NOMEM;
2768 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
2770 option.types[1].type = JOB_NOTIFY_TYPE;
2771 option.types[1].count = 1;
2772 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2773 if (option.types[1].fields == NULL) {
2774 result = WERR_NOMEM;
2777 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
2779 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2781 result = WERR_NOMEM;
2787 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2795 if (!W_ERROR_IS_OK(result)) {
2796 printf("Error rffpcnex %s\n", argv[1]);
2801 if (is_valid_policy_hnd(&hnd))
2802 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2807 /****************************************************************************
2808 ****************************************************************************/
2810 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
2811 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
2813 union spoolss_PrinterInfo info1, info2;
2815 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2817 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2818 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2823 if ( !W_ERROR_IS_OK(werror) ) {
2824 printf("failed (%s)\n", win_errstr(werror));
2825 talloc_destroy(mem_ctx);
2830 printf("Retrieving printer properties for %s...", cli2->desthost);
2831 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2836 if ( !W_ERROR_IS_OK(werror) ) {
2837 printf("failed (%s)\n", win_errstr(werror));
2838 talloc_destroy(mem_ctx);
2843 talloc_destroy(mem_ctx);
2848 /****************************************************************************
2849 ****************************************************************************/
2851 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
2852 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
2854 union spoolss_PrinterInfo info1, info2;
2856 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2857 SEC_DESC *sd1, *sd2;
2861 printf("Retrieving printer security for %s...", cli1->desthost);
2862 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2867 if ( !W_ERROR_IS_OK(werror) ) {
2868 printf("failed (%s)\n", win_errstr(werror));
2874 printf("Retrieving printer security for %s...", cli2->desthost);
2875 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2880 if ( !W_ERROR_IS_OK(werror) ) {
2881 printf("failed (%s)\n", win_errstr(werror));
2890 sd1 = info1.info3.secdesc;
2891 sd2 = info2.info3.secdesc;
2893 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2894 printf("NULL secdesc!\n");
2899 if (!security_descriptor_equal( sd1, sd2 ) ) {
2900 printf("Security Descriptors *not* equal!\n");
2905 printf("Security descriptors match\n");
2908 talloc_destroy(mem_ctx);
2913 /****************************************************************************
2914 ****************************************************************************/
2916 extern struct user_auth_info *rpcclient_auth_info;
2918 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2919 TALLOC_CTX *mem_ctx, int argc,
2922 const char *printername;
2923 char *printername_path = NULL;
2924 struct cli_state *cli_server2 = NULL;
2925 struct rpc_pipe_client *cli2 = NULL;
2926 struct policy_handle hPrinter1, hPrinter2;
2931 printf("Usage: %s <printer> <server>\n", argv[0]);
2935 printername = argv[1];
2937 /* first get the connection to the remote server */
2939 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2942 get_cmdline_auth_info_username(rpcclient_auth_info),
2944 get_cmdline_auth_info_password(rpcclient_auth_info),
2945 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2946 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2948 if ( !NT_STATUS_IS_OK(nt_status) )
2949 return WERR_GENERAL_FAILURE;
2951 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
2953 if (!NT_STATUS_IS_OK(nt_status)) {
2954 printf("failed to open spoolss pipe on server %s (%s)\n",
2955 argv[2], nt_errstr(nt_status));
2956 return WERR_GENERAL_FAILURE;
2959 /* now open up both printers */
2961 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2963 printf("Opening %s...", printername_path);
2965 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2969 if ( !W_ERROR_IS_OK(werror) ) {
2970 printf("failed (%s)\n", win_errstr(werror));
2975 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2977 printf("Opening %s...", printername_path);
2978 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2982 if ( !W_ERROR_IS_OK(werror) ) {
2983 printf("failed (%s)\n", win_errstr(werror));
2988 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2989 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2991 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2998 printf("Closing printers...");
2999 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3000 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3003 /* close the second remote connection */
3005 cli_shutdown( cli_server2 );
3009 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3011 printf("print_processor_name: %s\n", r->print_processor_name);
3014 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3015 TALLOC_CTX *mem_ctx, int argc,
3019 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3020 uint32_t num_procs, level = 1, i;
3021 union spoolss_PrintProcessorInfo *procs;
3023 /* Parse the command arguments */
3025 if (argc < 1 || argc > 4) {
3026 printf ("Usage: %s [environment] [level]\n", argv[0]);
3031 environment = argv[1];
3035 level = atoi(argv[2]);
3038 /* Enumerate Print Processors */
3040 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3041 cli->srv_name_slash,
3047 if (!W_ERROR_IS_OK(werror))
3050 /* Display output */
3052 for (i = 0; i < num_procs; i++) {
3055 display_proc_info1(&procs[i].info1);
3064 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3066 printf("name_array: %s\n", r->name_array);
3069 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3070 TALLOC_CTX *mem_ctx, int argc,
3074 const char *print_processor_name = "winprint";
3075 uint32_t num_procs, level = 1, i;
3076 union spoolss_PrintProcDataTypesInfo *procs;
3078 /* Parse the command arguments */
3080 if (argc < 1 || argc > 4) {
3081 printf ("Usage: %s [environment] [level]\n", argv[0]);
3086 print_processor_name = argv[1];
3090 level = atoi(argv[2]);
3093 /* Enumerate Print Processor Data Types */
3095 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3096 cli->srv_name_slash,
3097 print_processor_name,
3102 if (!W_ERROR_IS_OK(werror))
3105 /* Display output */
3107 for (i = 0; i < num_procs; i++) {
3110 display_proc_data_types_info1(&procs[i].info1);
3119 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3121 printf("monitor_name: %s\n", r->monitor_name);
3124 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3126 printf("monitor_name: %s\n", r->monitor_name);
3127 printf("environment: %s\n", r->environment);
3128 printf("dll_name: %s\n", r->dll_name);
3131 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3132 TALLOC_CTX *mem_ctx, int argc,
3136 uint32_t count, level = 1, i;
3137 union spoolss_MonitorInfo *info;
3139 /* Parse the command arguments */
3142 printf("Usage: %s [level]\n", argv[0]);
3147 level = atoi(argv[1]);
3150 /* Enumerate Print Monitors */
3152 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3153 cli->srv_name_slash,
3158 if (!W_ERROR_IS_OK(werror)) {
3162 /* Display output */
3164 for (i = 0; i < count; i++) {
3167 display_monitor1(&info[i].info1);
3170 display_monitor2(&info[i].info2);
3179 /* List of commands exported by this module */
3180 struct cmd_set spoolss_commands[] = {
3184 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3185 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3186 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3187 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3188 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3189 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3190 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3191 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3192 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3193 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3194 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3195 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3196 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3197 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3198 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3199 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3200 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3201 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3202 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3203 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3204 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3205 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3206 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3207 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3208 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3209 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3210 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3211 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3212 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3213 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3214 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3215 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3216 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3217 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },