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);
2453 /****************************************************************************
2454 ****************************************************************************/
2456 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2457 TALLOC_CTX *mem_ctx, int argc,
2463 const char *printername;
2464 struct policy_handle hnd;
2465 uint32_t value_offered = 0;
2466 const char *value_name = NULL;
2467 uint32_t value_needed;
2468 enum winreg_Type type;
2469 uint8_t *data = NULL;
2470 uint32_t data_offered = 0;
2471 uint32_t data_needed;
2474 printf("Usage: %s printername\n", argv[0]);
2478 /* Open printer handle */
2480 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2482 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2484 SEC_FLAG_MAXIMUM_ALLOWED,
2486 if (!W_ERROR_IS_OK(result)) {
2490 /* Enumerate data */
2492 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2504 data_offered = data_needed;
2505 value_offered = value_needed;
2506 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2507 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2509 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2511 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2522 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2524 fstrcpy(v.valuename, value_name);
2526 v.size = data_offered;
2528 display_reg_value(v);
2532 if (W_ERROR_V(result) == ERRnomoreitems) {
2533 result = W_ERROR(ERRsuccess);
2537 if (is_valid_policy_hnd(&hnd)) {
2538 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2544 /****************************************************************************
2545 ****************************************************************************/
2547 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2548 TALLOC_CTX *mem_ctx, int argc,
2553 const char *printername;
2554 struct policy_handle hnd;
2556 struct spoolss_PrinterEnumValues *info;
2559 printf("Usage: %s printername <keyname>\n", argv[0]);
2563 /* Open printer handle */
2565 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2567 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2569 SEC_FLAG_MAXIMUM_ALLOWED,
2571 if (!W_ERROR_IS_OK(result)) {
2575 /* Enumerate subkeys */
2577 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2583 if (!W_ERROR_IS_OK(result)) {
2587 for (i=0; i < count; i++) {
2588 display_printer_data(info[i].value_name,
2594 if (is_valid_policy_hnd(&hnd)) {
2595 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2601 /****************************************************************************
2602 ****************************************************************************/
2604 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2605 TALLOC_CTX *mem_ctx, int argc,
2609 const char *printername;
2610 const char *keyname = NULL;
2611 struct policy_handle hnd;
2612 const char **key_buffer = NULL;
2615 if (argc < 2 || argc > 3) {
2616 printf("Usage: %s printername [keyname]\n", argv[0]);
2626 /* Open printer handle */
2628 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2630 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2632 SEC_FLAG_MAXIMUM_ALLOWED,
2634 if (!W_ERROR_IS_OK(result)) {
2638 /* Enumerate subkeys */
2640 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
2646 if (!W_ERROR_IS_OK(result)) {
2650 for (i=0; key_buffer && key_buffer[i]; i++) {
2651 printf("%s\n", key_buffer[i]);
2656 if (is_valid_policy_hnd(&hnd)) {
2657 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2663 /****************************************************************************
2664 ****************************************************************************/
2666 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2667 TALLOC_CTX *mem_ctx, int argc,
2670 const char *printername;
2671 const char *clientname;
2672 struct policy_handle hnd;
2675 struct spoolss_NotifyOption option;
2678 printf("Usage: %s printername\n", argv[0]);
2685 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2687 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2689 SEC_FLAG_MAXIMUM_ALLOWED,
2691 if (!W_ERROR_IS_OK(result)) {
2692 printf("Error opening %s\n", argv[1]);
2696 /* Create spool options */
2701 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2702 if (option.types == NULL) {
2703 result = WERR_NOMEM;
2707 option.types[0].type = PRINTER_NOTIFY_TYPE;
2708 option.types[0].count = 1;
2709 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2710 if (option.types[0].fields == NULL) {
2711 result = WERR_NOMEM;
2714 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
2716 option.types[1].type = JOB_NOTIFY_TYPE;
2717 option.types[1].count = 1;
2718 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
2719 if (option.types[1].fields == NULL) {
2720 result = WERR_NOMEM;
2723 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
2725 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2727 result = WERR_NOMEM;
2733 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2741 if (!W_ERROR_IS_OK(result)) {
2742 printf("Error rffpcnex %s\n", argv[1]);
2747 if (is_valid_policy_hnd(&hnd))
2748 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2753 /****************************************************************************
2754 ****************************************************************************/
2756 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
2757 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
2759 union spoolss_PrinterInfo info1, info2;
2761 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2763 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2764 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2769 if ( !W_ERROR_IS_OK(werror) ) {
2770 printf("failed (%s)\n", win_errstr(werror));
2771 talloc_destroy(mem_ctx);
2776 printf("Retrieving printer properties for %s...", cli2->desthost);
2777 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2782 if ( !W_ERROR_IS_OK(werror) ) {
2783 printf("failed (%s)\n", win_errstr(werror));
2784 talloc_destroy(mem_ctx);
2789 talloc_destroy(mem_ctx);
2794 /****************************************************************************
2795 ****************************************************************************/
2797 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
2798 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
2800 union spoolss_PrinterInfo info1, info2;
2802 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2803 SEC_DESC *sd1, *sd2;
2807 printf("Retrieving printer security for %s...", cli1->desthost);
2808 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2813 if ( !W_ERROR_IS_OK(werror) ) {
2814 printf("failed (%s)\n", win_errstr(werror));
2820 printf("Retrieving printer security for %s...", cli2->desthost);
2821 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2826 if ( !W_ERROR_IS_OK(werror) ) {
2827 printf("failed (%s)\n", win_errstr(werror));
2836 sd1 = info1.info3.secdesc;
2837 sd2 = info2.info3.secdesc;
2839 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2840 printf("NULL secdesc!\n");
2845 if (!sec_desc_equal( sd1, sd2 ) ) {
2846 printf("Security Descriptors *not* equal!\n");
2851 printf("Security descriptors match\n");
2854 talloc_destroy(mem_ctx);
2859 /****************************************************************************
2860 ****************************************************************************/
2862 extern struct user_auth_info *rpcclient_auth_info;
2864 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2865 TALLOC_CTX *mem_ctx, int argc,
2868 const char *printername;
2869 char *printername_path = NULL;
2870 struct cli_state *cli_server2 = NULL;
2871 struct rpc_pipe_client *cli2 = NULL;
2872 struct policy_handle hPrinter1, hPrinter2;
2877 printf("Usage: %s <printer> <server>\n", argv[0]);
2881 printername = argv[1];
2883 /* first get the connection to the remote server */
2885 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2888 get_cmdline_auth_info_username(rpcclient_auth_info),
2890 get_cmdline_auth_info_password(rpcclient_auth_info),
2891 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2892 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2894 if ( !NT_STATUS_IS_OK(nt_status) )
2895 return WERR_GENERAL_FAILURE;
2897 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
2899 if (!NT_STATUS_IS_OK(nt_status)) {
2900 printf("failed to open spoolss pipe on server %s (%s)\n",
2901 argv[2], nt_errstr(nt_status));
2902 return WERR_GENERAL_FAILURE;
2905 /* now open up both printers */
2907 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
2909 printf("Opening %s...", printername_path);
2911 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2915 if ( !W_ERROR_IS_OK(werror) ) {
2916 printf("failed (%s)\n", win_errstr(werror));
2921 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
2923 printf("Opening %s...", printername_path);
2924 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
2928 if ( !W_ERROR_IS_OK(werror) ) {
2929 printf("failed (%s)\n", win_errstr(werror));
2934 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2935 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2937 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2944 printf("Closing printers...");
2945 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
2946 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
2949 /* close the second remote connection */
2951 cli_shutdown( cli_server2 );
2955 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
2957 printf("print_processor_name: %s\n", r->print_processor_name);
2960 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
2961 TALLOC_CTX *mem_ctx, int argc,
2965 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2966 uint32_t num_procs, level = 1, i;
2967 union spoolss_PrintProcessorInfo *procs;
2969 /* Parse the command arguments */
2971 if (argc < 1 || argc > 4) {
2972 printf ("Usage: %s [environment] [level]\n", argv[0]);
2977 environment = argv[1];
2981 level = atoi(argv[2]);
2984 /* Enumerate Print Processors */
2986 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
2987 cli->srv_name_slash,
2993 if (!W_ERROR_IS_OK(werror))
2996 /* Display output */
2998 for (i = 0; i < num_procs; i++) {
3001 display_proc_info1(&procs[i].info1);
3010 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3012 printf("name_array: %s\n", r->name_array);
3015 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3016 TALLOC_CTX *mem_ctx, int argc,
3020 const char *print_processor_name = "winprint";
3021 uint32_t num_procs, level = 1, i;
3022 union spoolss_PrintProcDataTypesInfo *procs;
3024 /* Parse the command arguments */
3026 if (argc < 1 || argc > 4) {
3027 printf ("Usage: %s [environment] [level]\n", argv[0]);
3032 print_processor_name = argv[1];
3036 level = atoi(argv[2]);
3039 /* Enumerate Print Processor Data Types */
3041 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3042 cli->srv_name_slash,
3043 print_processor_name,
3048 if (!W_ERROR_IS_OK(werror))
3051 /* Display output */
3053 for (i = 0; i < num_procs; i++) {
3056 display_proc_data_types_info1(&procs[i].info1);
3065 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3067 printf("monitor_name: %s\n", r->monitor_name);
3070 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3072 printf("monitor_name: %s\n", r->monitor_name);
3073 printf("environment: %s\n", r->environment);
3074 printf("dll_name: %s\n", r->dll_name);
3077 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3078 TALLOC_CTX *mem_ctx, int argc,
3082 uint32_t count, level = 1, i;
3083 union spoolss_MonitorInfo *info;
3085 /* Parse the command arguments */
3088 printf("Usage: %s [level]\n", argv[0]);
3093 level = atoi(argv[1]);
3096 /* Enumerate Print Monitors */
3098 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3099 cli->srv_name_slash,
3104 if (!W_ERROR_IS_OK(werror)) {
3108 /* Display output */
3110 for (i = 0; i < count; i++) {
3113 display_monitor1(&info[i].info1);
3116 display_monitor2(&info[i].info2);
3125 /* List of commands exported by this module */
3126 struct cmd_set spoolss_commands[] = {
3130 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3131 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3132 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3133 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3134 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3135 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3136 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3137 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3138 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3139 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3140 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3141 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3142 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3143 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3144 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3145 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3146 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3147 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3148 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3149 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3150 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3151 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3152 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3153 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3154 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3155 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3156 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3157 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3158 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3159 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3160 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3161 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3162 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },