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"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
29 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
31 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
32 _cli->srv_name_slash, _arg); \
33 W_ERROR_HAVE_NO_MEMORY(_printername); \
36 /* The version int is used by getdrivers. Note that
37 all architecture strings that support mutliple
38 versions must be grouped together since enumdrivers
39 uses this property to prevent issuing multiple
40 enumdriver calls for the same arch */
43 static const struct print_architecture_table_node archi_table
[]= {
45 {"Windows 4.0", "WIN40", 0 },
46 {"Windows NT x86", "W32X86", 2 },
47 {"Windows NT x86", "W32X86", 3 },
48 {"Windows NT R4000", "W32MIPS", 2 },
49 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
50 {"Windows NT PowerPC", "W32PPC", 2 },
51 {"Windows IA64", "IA64", 3 },
52 {"Windows x64", "x64", 3 },
59 * rpcclient module for SPOOLSS rpc pipe.
61 * This generally just parses and checks command lines, and then calls
62 * a cli_spoolss function.
65 /****************************************************************************
66 function to do the mapping between the long architecture name and
68 ****************************************************************************/
70 static const char *cmd_spoolss_get_short_archi(const char *long_archi
)
74 DEBUG(107,("Getting architecture dependant directory\n"));
77 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
78 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
80 if (archi_table
[i
].long_archi
==NULL
) {
81 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
85 /* this might be client code - but shouldn't this be an fstrcpy etc? */
88 DEBUGADD(108,("index: [%d]\n", i
));
89 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
90 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
92 return archi_table
[i
].short_archi
;
95 /****************************************************************************
96 ****************************************************************************/
98 static WERROR
cmd_spoolss_open_printer_ex(struct rpc_pipe_client
*cli
,
100 int argc
, const char **argv
)
103 struct policy_handle hnd
;
106 printf("Usage: %s <printername>\n", argv
[0]);
111 return WERR_GENERAL_FAILURE
;
113 /* Open the printer handle */
115 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
119 if (W_ERROR_IS_OK(werror
)) {
120 printf("Printer %s opened successfully\n", argv
[1]);
121 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, &werror
);
123 if (!W_ERROR_IS_OK(werror
)) {
124 printf("Error closing printer handle! (%s)\n",
125 get_dos_error_msg(werror
));
133 /****************************************************************************
134 ****************************************************************************/
136 static void display_print_info0(struct spoolss_PrinterInfo0
*r
)
141 printf("\tprintername:[%s]\n", r
->printername
);
142 printf("\tservername:[%s]\n", r
->servername
);
143 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
144 printf("\ttotal_jobs:[0x%x]\n", r
->total_jobs
);
145 printf("\ttotal_bytes:[0x%x]\n", r
->total_bytes
);
146 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r
->time
.year
, r
->time
.month
,
147 r
->time
.day
, r
->time
.day_of_week
);
148 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r
->time
.hour
, r
->time
.minute
,
149 r
->time
.second
, r
->time
.millisecond
);
151 printf("\tglobal_counter:[0x%x]\n", r
->global_counter
);
152 printf("\ttotal_pages:[0x%x]\n", r
->total_pages
);
154 printf("\tversion:[0x%x]\n", r
->version
);
155 printf("\tfree_build:[0x%x]\n", r
->free_build
);
156 printf("\tspooling:[0x%x]\n", r
->spooling
);
157 printf("\tmax_spooling:[0x%x]\n", r
->max_spooling
);
158 printf("\tsession_counter:[0x%x]\n", r
->session_counter
);
159 printf("\tnum_error_out_of_paper:[0x%x]\n", r
->num_error_out_of_paper
);
160 printf("\tnum_error_not_ready:[0x%x]\n", r
->num_error_not_ready
);
161 printf("\tjob_error:[0x%x]\n", r
->job_error
);
162 printf("\tnumber_of_processors:[0x%x]\n", r
->number_of_processors
);
163 printf("\tprocessor_type:[0x%x]\n", r
->processor_type
);
164 printf("\thigh_part_total_bytes:[0x%x]\n", r
->high_part_total_bytes
);
165 printf("\tchange_id:[0x%x]\n", r
->change_id
);
166 printf("\tlast_error: %s\n", win_errstr(r
->last_error
));
167 printf("\tstatus:[0x%x]\n", r
->status
);
168 printf("\tenumerate_network_printers:[0x%x]\n", r
->enumerate_network_printers
);
169 printf("\tc_setprinter:[0x%x]\n", r
->c_setprinter
);
170 printf("\tprocessor_architecture:[0x%x]\n", r
->processor_architecture
);
171 printf("\tprocessor_level:[0x%x]\n", r
->processor_level
);
172 printf("\tref_ic:[0x%x]\n", r
->ref_ic
);
173 printf("\treserved2:[0x%x]\n", r
->reserved2
);
174 printf("\treserved3:[0x%x]\n", r
->reserved3
);
179 /****************************************************************************
180 ****************************************************************************/
182 static void display_print_info1(struct spoolss_PrinterInfo1
*r
)
184 printf("\tflags:[0x%x]\n", r
->flags
);
185 printf("\tname:[%s]\n", r
->name
);
186 printf("\tdescription:[%s]\n", r
->description
);
187 printf("\tcomment:[%s]\n", r
->comment
);
192 /****************************************************************************
193 ****************************************************************************/
195 static void display_print_info2(struct spoolss_PrinterInfo2
*r
)
197 printf("\tservername:[%s]\n", r
->servername
);
198 printf("\tprintername:[%s]\n", r
->printername
);
199 printf("\tsharename:[%s]\n", r
->sharename
);
200 printf("\tportname:[%s]\n", r
->portname
);
201 printf("\tdrivername:[%s]\n", r
->drivername
);
202 printf("\tcomment:[%s]\n", r
->comment
);
203 printf("\tlocation:[%s]\n", r
->location
);
204 printf("\tsepfile:[%s]\n", r
->sepfile
);
205 printf("\tprintprocessor:[%s]\n", r
->printprocessor
);
206 printf("\tdatatype:[%s]\n", r
->datatype
);
207 printf("\tparameters:[%s]\n", r
->parameters
);
208 printf("\tattributes:[0x%x]\n", r
->attributes
);
209 printf("\tpriority:[0x%x]\n", r
->priority
);
210 printf("\tdefaultpriority:[0x%x]\n", r
->defaultpriority
);
211 printf("\tstarttime:[0x%x]\n", r
->starttime
);
212 printf("\tuntiltime:[0x%x]\n", r
->untiltime
);
213 printf("\tstatus:[0x%x]\n", r
->status
);
214 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
215 printf("\taverageppm:[0x%x]\n", r
->averageppm
);
218 display_sec_desc(r
->secdesc
);
223 /****************************************************************************
224 ****************************************************************************/
226 static void display_print_info3(struct spoolss_PrinterInfo3
*r
)
228 display_sec_desc(r
->secdesc
);
233 /****************************************************************************
234 ****************************************************************************/
236 static void display_print_info4(struct spoolss_PrinterInfo4
*r
)
238 printf("\tservername:[%s]\n", r
->servername
);
239 printf("\tprintername:[%s]\n", r
->printername
);
240 printf("\tattributes:[0x%x]\n", r
->attributes
);
244 /****************************************************************************
245 ****************************************************************************/
247 static void display_print_info5(struct spoolss_PrinterInfo5
*r
)
249 printf("\tprintername:[%s]\n", r
->printername
);
250 printf("\tportname:[%s]\n", r
->portname
);
251 printf("\tattributes:[0x%x]\n", r
->attributes
);
252 printf("\tdevice_not_selected_timeout:[0x%x]\n", r
->device_not_selected_timeout
);
253 printf("\ttransmission_retry_timeout:[0x%x]\n", r
->transmission_retry_timeout
);
257 /****************************************************************************
258 ****************************************************************************/
260 static void display_print_info6(struct spoolss_PrinterInfo6
*r
)
262 printf("\tstatus:[0x%x]\n", r
->status
);
266 /****************************************************************************
267 ****************************************************************************/
269 static void display_print_info7(struct spoolss_PrinterInfo7
*r
)
271 printf("\tguid:[%s]\n", r
->guid
);
272 printf("\taction:[0x%x]\n", r
->action
);
276 /****************************************************************************
277 ****************************************************************************/
279 static WERROR
cmd_spoolss_enum_printers(struct rpc_pipe_client
*cli
,
281 int argc
, const char **argv
)
285 union spoolss_PrinterInfo
*info
;
288 uint32_t flags
= PRINTER_ENUM_LOCAL
;
291 printf("Usage: %s [level] [name] [flags]\n", argv
[0]);
296 level
= atoi(argv
[1]);
302 name
= cli
->srv_name_slash
;
306 flags
= atoi(argv
[3]);
309 result
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
316 if (W_ERROR_IS_OK(result
)) {
319 printf ("No printers returned.\n");
323 for (i
= 0; i
< count
; i
++) {
326 display_print_info0(&info
[i
].info0
);
329 display_print_info1(&info
[i
].info1
);
332 display_print_info2(&info
[i
].info2
);
335 display_print_info3(&info
[i
].info3
);
338 display_print_info4(&info
[i
].info4
);
341 display_print_info5(&info
[i
].info5
);
344 display_print_info6(&info
[i
].info6
);
347 printf("unknown info level %d\n", level
);
357 /****************************************************************************
358 ****************************************************************************/
360 static void display_port_info_1(struct spoolss_PortInfo1
*r
)
362 printf("\tPort Name:\t[%s]\n", r
->port_name
);
365 /****************************************************************************
366 ****************************************************************************/
368 static void display_port_info_2(struct spoolss_PortInfo2
*r
)
370 printf("\tPort Name:\t[%s]\n", r
->port_name
);
371 printf("\tMonitor Name:\t[%s]\n", r
->monitor_name
);
372 printf("\tDescription:\t[%s]\n", r
->description
);
373 printf("\tPort Type:\t" );
375 int comma
= 0; /* hack */
377 if (r
->port_type
& SPOOLSS_PORT_TYPE_READ
) {
381 if (r
->port_type
& SPOOLSS_PORT_TYPE_WRITE
) {
382 printf( "%sWrite", comma
? ", " : "" );
385 /* These two have slightly different interpretations
386 on 95/98/ME but I'm disregarding that for now */
387 if (r
->port_type
& SPOOLSS_PORT_TYPE_REDIRECTED
) {
388 printf( "%sRedirected", comma
? ", " : "" );
391 if (r
->port_type
& SPOOLSS_PORT_TYPE_NET_ATTACHED
) {
392 printf( "%sNet-Attached", comma
? ", " : "" );
396 printf( "[Unset]\n" );
398 printf("\tReserved:\t[%d]\n", r
->reserved
);
402 /****************************************************************************
403 ****************************************************************************/
405 static WERROR
cmd_spoolss_enum_ports(struct rpc_pipe_client
*cli
,
406 TALLOC_CTX
*mem_ctx
, int argc
,
412 union spoolss_PortInfo
*info
;
415 printf("Usage: %s [level]\n", argv
[0]);
420 level
= atoi(argv
[1]);
423 /* Enumerate ports */
425 result
= rpccli_spoolss_enumports(cli
, mem_ctx
,
431 if (W_ERROR_IS_OK(result
)) {
434 for (i
= 0; i
< count
; i
++) {
437 display_port_info_1(&info
[i
].info1
);
440 display_port_info_2(&info
[i
].info2
);
443 printf("unknown info level %d\n", level
);
452 /****************************************************************************
453 ****************************************************************************/
455 static WERROR
cmd_spoolss_setprinter(struct rpc_pipe_client
*cli
,
457 int argc
, const char **argv
)
459 struct policy_handle pol
;
462 uint32_t info_level
= 2;
463 union spoolss_PrinterInfo info
;
464 struct spoolss_SetPrinterInfoCtr info_ctr
;
465 const char *printername
, *comment
= NULL
;
466 struct spoolss_DevmodeContainer devmode_ctr
;
467 struct sec_desc_buf secdesc_ctr
;
469 if (argc
== 1 || argc
> 3) {
470 printf("Usage: %s printername comment\n", argv
[0]);
475 /* Open a printer handle */
480 ZERO_STRUCT(devmode_ctr
);
481 ZERO_STRUCT(secdesc_ctr
);
483 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
485 /* get a printer handle */
486 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
490 if (!W_ERROR_IS_OK(result
))
493 /* Get printer info */
494 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
499 if (!W_ERROR_IS_OK(result
))
503 /* Modify the comment. */
504 info
.info2
.comment
= comment
;
505 info
.info2
.secdesc
= NULL
;
506 info
.info2
.devmode
= NULL
;
509 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
511 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
518 if (W_ERROR_IS_OK(result
))
519 printf("Success in setting comment.\n");
522 if (is_valid_policy_hnd(&pol
))
523 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
528 /****************************************************************************
529 ****************************************************************************/
531 static WERROR
cmd_spoolss_setprintername(struct rpc_pipe_client
*cli
,
533 int argc
, const char **argv
)
535 struct policy_handle pol
;
538 uint32_t info_level
= 2;
539 union spoolss_PrinterInfo info
;
540 const char *printername
,
541 *new_printername
= NULL
;
542 struct spoolss_SetPrinterInfoCtr info_ctr
;
543 struct spoolss_DevmodeContainer devmode_ctr
;
544 struct sec_desc_buf secdesc_ctr
;
546 ZERO_STRUCT(devmode_ctr
);
547 ZERO_STRUCT(secdesc_ctr
);
549 if (argc
== 1 || argc
> 3) {
550 printf("Usage: %s printername new_printername\n", argv
[0]);
555 /* Open a printer handle */
557 new_printername
= argv
[2];
560 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
562 /* get a printer handle */
563 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
567 if (!W_ERROR_IS_OK(result
))
570 /* Get printer info */
571 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
576 if (!W_ERROR_IS_OK(result
))
579 /* Modify the printername. */
580 info
.info2
.printername
= new_printername
;
581 info
.info2
.devmode
= NULL
;
582 info
.info2
.secdesc
= NULL
;
584 info_ctr
.level
= info_level
;
585 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
587 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
594 if (W_ERROR_IS_OK(result
))
595 printf("Success in setting printername.\n");
598 if (is_valid_policy_hnd(&pol
))
599 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
604 /****************************************************************************
605 ****************************************************************************/
607 static WERROR
cmd_spoolss_getprinter(struct rpc_pipe_client
*cli
,
609 int argc
, const char **argv
)
611 struct policy_handle pol
;
614 const char *printername
;
615 union spoolss_PrinterInfo info
;
617 if (argc
== 1 || argc
> 3) {
618 printf("Usage: %s <printername> [level]\n", argv
[0]);
622 /* Open a printer handle */
624 level
= atoi(argv
[2]);
627 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
629 /* get a printer handle */
631 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
633 SEC_FLAG_MAXIMUM_ALLOWED
,
635 if (!W_ERROR_IS_OK(result
)) {
639 /* Get printer info */
641 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
646 if (!W_ERROR_IS_OK(result
)) {
650 /* Display printer info */
653 display_print_info0(&info
.info0
);
656 display_print_info1(&info
.info1
);
659 display_print_info2(&info
.info2
);
662 display_print_info3(&info
.info3
);
665 display_print_info4(&info
.info4
);
668 display_print_info5(&info
.info5
);
671 display_print_info6(&info
.info6
);
674 display_print_info7(&info
.info7
);
677 printf("unknown info level %d\n", level
);
681 if (is_valid_policy_hnd(&pol
)) {
682 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
688 /****************************************************************************
689 ****************************************************************************/
691 static void display_reg_value(struct regval_blob value
)
693 const char *text
= NULL
;
698 printf("%s: REG_DWORD: 0x%08x\n", value
.valuename
,
699 *((uint32_t *) value
.data_p
));
702 blob
= data_blob_const(value
.data_p
, value
.size
);
703 pull_reg_sz(talloc_tos(), &blob
, &text
);
704 printf("%s: REG_SZ: %s\n", value
.valuename
, text
? text
: "");
707 char *hex
= hex_encode_talloc(NULL
, value
.data_p
, value
.size
);
709 printf("%s: REG_BINARY:", value
.valuename
);
711 for (i
=0; i
<len
; i
++) {
712 if (hex
[i
] == '\0') {
727 blob
= data_blob_const(value
.data_p
, value
.size
);
729 if (!pull_reg_multi_sz(NULL
, &blob
, &values
)) {
730 d_printf("pull_reg_multi_sz failed\n");
734 printf("%s: REG_MULTI_SZ: \n", value
.valuename
);
735 for (i
=0; values
[i
] != NULL
; i
++) {
736 d_printf("%s\n", values
[i
]);
742 printf("%s: unknown type %d\n", value
.valuename
, value
.type
);
747 /****************************************************************************
748 ****************************************************************************/
750 static void display_printer_data(const char *v
,
751 enum winreg_Type type
,
752 union spoolss_PrinterData
*r
)
758 printf("%s: REG_DWORD: 0x%08x\n", v
, r
->value
);
761 printf("%s: REG_SZ: %s\n", v
, r
->string
);
764 char *hex
= hex_encode_talloc(NULL
,
765 r
->binary
.data
, r
->binary
.length
);
767 printf("%s: REG_BINARY:", v
);
769 for (i
=0; i
<len
; i
++) {
770 if (hex
[i
] == '\0') {
783 printf("%s: REG_MULTI_SZ: ", v
);
784 for (i
=0; r
->string_array
[i
] != NULL
; i
++) {
785 printf("%s ", r
->string_array
[i
]);
790 printf("%s: unknown type 0x%02x:\n", v
, type
);
795 /****************************************************************************
796 ****************************************************************************/
798 static WERROR
cmd_spoolss_getprinterdata(struct rpc_pipe_client
*cli
,
800 int argc
, const char **argv
)
802 struct policy_handle pol
;
805 const char *valuename
;
806 enum winreg_Type type
;
807 union spoolss_PrinterData data
;
810 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
811 printf("<printername> of . queries print server\n");
816 /* Open a printer handle */
818 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
819 fstrcpy(printername
, cli
->srv_name_slash
);
821 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
822 cli
->srv_name_slash
, argv
[1]);
824 /* get a printer handle */
826 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
828 SEC_FLAG_MAXIMUM_ALLOWED
,
830 if (!W_ERROR_IS_OK(result
))
833 /* Get printer info */
835 result
= rpccli_spoolss_getprinterdata(cli
, mem_ctx
,
841 if (!W_ERROR_IS_OK(result
))
844 /* Display printer data */
846 display_printer_data(valuename
, type
, &data
);
849 if (is_valid_policy_hnd(&pol
))
850 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
855 /****************************************************************************
856 ****************************************************************************/
858 static WERROR
cmd_spoolss_getprinterdataex(struct rpc_pipe_client
*cli
,
860 int argc
, const char **argv
)
862 struct policy_handle pol
;
866 const char *valuename
, *keyname
;
868 enum winreg_Type type
;
869 union spoolss_PrinterData data
;
870 uint32_t offered
= 0;
874 printf("Usage: %s <printername> <keyname> <valuename>\n",
876 printf("<printername> of . queries print server\n");
882 /* Open a printer handle */
884 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
885 fstrcpy(printername
, cli
->srv_name_slash
);
887 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
888 cli
->srv_name_slash
, argv
[1]);
890 /* get a printer handle */
892 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
894 SEC_FLAG_MAXIMUM_ALLOWED
,
896 if (!W_ERROR_IS_OK(result
))
899 /* Get printer info */
901 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
910 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
912 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
923 if (!NT_STATUS_IS_OK(status
)) {
927 if (!W_ERROR_IS_OK(result
))
930 /* Display printer data */
932 display_printer_data(valuename
, type
, &data
);
936 if (is_valid_policy_hnd(&pol
))
937 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
942 /****************************************************************************
943 ****************************************************************************/
945 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
951 printf("Printer Driver Info 1:\n");
952 printf("\tDriver Name: [%s]\n", r
->driver_name
);
956 /****************************************************************************
957 ****************************************************************************/
959 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
965 printf("Printer Driver Info 2:\n");
966 printf("\tVersion: [%x]\n", r
->version
);
967 printf("\tDriver Name: [%s]\n", r
->driver_name
);
968 printf("\tArchitecture: [%s]\n", r
->architecture
);
969 printf("\tDriver Path: [%s]\n", r
->driver_path
);
970 printf("\tDatafile: [%s]\n", r
->data_file
);
971 printf("\tConfigfile: [%s]\n", r
->config_file
);
975 /****************************************************************************
976 ****************************************************************************/
978 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
986 printf("Printer Driver Info 3:\n");
987 printf("\tVersion: [%x]\n", r
->version
);
988 printf("\tDriver Name: [%s]\n", r
->driver_name
);
989 printf("\tArchitecture: [%s]\n", r
->architecture
);
990 printf("\tDriver Path: [%s]\n", r
->driver_path
);
991 printf("\tDatafile: [%s]\n", r
->data_file
);
992 printf("\tConfigfile: [%s]\n", r
->config_file
);
993 printf("\tHelpfile: [%s]\n", r
->help_file
);
995 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
996 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
999 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1000 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1004 /****************************************************************************
1005 ****************************************************************************/
1007 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1015 printf("Printer Driver Info 4:\n");
1016 printf("\tVersion: [%x]\n", r
->version
);
1017 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1018 printf("\tArchitecture: [%s]\n", r
->architecture
);
1019 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1020 printf("\tDatafile: [%s]\n", r
->data_file
);
1021 printf("\tConfigfile: [%s]\n", r
->config_file
);
1022 printf("\tHelpfile: [%s]\n", r
->help_file
);
1024 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1025 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1028 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1029 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1031 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1032 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1037 /****************************************************************************
1038 ****************************************************************************/
1040 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1046 printf("Printer Driver Info 5:\n");
1047 printf("\tVersion: [%x]\n", r
->version
);
1048 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1049 printf("\tArchitecture: [%s]\n", r
->architecture
);
1050 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1051 printf("\tDatafile: [%s]\n", r
->data_file
);
1052 printf("\tConfigfile: [%s]\n", r
->config_file
);
1053 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1054 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1055 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1059 /****************************************************************************
1060 ****************************************************************************/
1062 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1070 printf("Printer Driver Info 6:\n");
1071 printf("\tVersion: [%x]\n", r
->version
);
1072 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1073 printf("\tArchitecture: [%s]\n", r
->architecture
);
1074 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1075 printf("\tDatafile: [%s]\n", r
->data_file
);
1076 printf("\tConfigfile: [%s]\n", r
->config_file
);
1077 printf("\tHelpfile: [%s]\n", r
->help_file
);
1079 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1080 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1083 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1084 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1086 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1087 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1090 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1091 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1092 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1093 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1094 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1095 printf("\tProvider: [%s]\n", r
->provider
);
1100 /****************************************************************************
1101 ****************************************************************************/
1103 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1111 printf("Printer Driver Info 8:\n");
1112 printf("\tVersion: [%x]\n", r
->version
);
1113 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1114 printf("\tArchitecture: [%s]\n", r
->architecture
);
1115 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1116 printf("\tDatafile: [%s]\n", r
->data_file
);
1117 printf("\tConfigfile: [%s]\n", r
->config_file
);
1118 printf("\tHelpfile: [%s]\n", r
->help_file
);
1119 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1120 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1122 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1123 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1126 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1127 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1130 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1131 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1132 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1133 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1134 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1135 printf("\tProvider: [%s]\n", r
->provider
);
1136 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1137 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1138 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1139 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1141 printf("\tInf Path: [%s]\n", r
->inf_path
);
1142 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1143 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1144 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1146 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1147 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1148 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1153 /****************************************************************************
1154 ****************************************************************************/
1156 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1157 TALLOC_CTX
*mem_ctx
,
1158 int argc
, const char **argv
)
1160 struct policy_handle pol
;
1163 const char *printername
;
1165 bool success
= false;
1166 union spoolss_DriverInfo info
;
1167 uint32_t server_major_version
;
1168 uint32_t server_minor_version
;
1170 if ((argc
== 1) || (argc
> 3)) {
1171 printf("Usage: %s <printername> [level]\n", argv
[0]);
1175 /* get the arguments need to open the printer handle */
1177 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1180 level
= atoi(argv
[2]);
1183 /* Open a printer handle */
1185 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1189 if (!W_ERROR_IS_OK(werror
)) {
1190 printf("Error opening printer handle for %s!\n", printername
);
1194 /* loop through and print driver info level for each architecture */
1196 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1198 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1200 archi_table
[i
].long_archi
,
1203 archi_table
[i
].version
,
1206 &server_major_version
,
1207 &server_minor_version
);
1208 if (!W_ERROR_IS_OK(werror
)) {
1212 /* need at least one success */
1216 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1220 display_print_driver1(&info
.info1
);
1223 display_print_driver2(&info
.info2
);
1226 display_print_driver3(&info
.info3
);
1229 display_print_driver4(&info
.info4
);
1232 display_print_driver5(&info
.info5
);
1235 display_print_driver6(&info
.info6
);
1238 display_print_driver8(&info
.info8
);
1241 printf("unknown info level %d\n", level
);
1248 if (is_valid_policy_hnd(&pol
)) {
1249 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1259 /****************************************************************************
1260 ****************************************************************************/
1262 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1263 TALLOC_CTX
*mem_ctx
,
1264 const char *architecture
,
1269 union spoolss_DriverInfo
*info
= NULL
;
1272 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1273 cli
->srv_name_slash
,
1280 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1281 printf("Server does not support environment [%s]\n",
1290 if (!W_ERROR_IS_OK(werror
)) {
1291 printf("Error getting driver for environment [%s] - %s\n",
1292 architecture
, win_errstr(werror
));
1296 printf("\n[%s]\n", architecture
);
1300 for (j
=0; j
< count
; j
++) {
1301 display_print_driver1(&info
[j
].info1
);
1305 for (j
=0; j
< count
; j
++) {
1306 display_print_driver2(&info
[j
].info2
);
1310 for (j
=0; j
< count
; j
++) {
1311 display_print_driver3(&info
[j
].info3
);
1315 for (j
=0; j
< count
; j
++) {
1316 display_print_driver4(&info
[j
].info4
);
1320 for (j
=0; j
< count
; j
++) {
1321 display_print_driver5(&info
[j
].info5
);
1325 for (j
=0; j
< count
; j
++) {
1326 display_print_driver6(&info
[j
].info6
);
1330 for (j
=0; j
< count
; j
++) {
1331 display_print_driver8(&info
[j
].info8
);
1335 printf("unknown info level %d\n", level
);
1336 return WERR_UNKNOWN_LEVEL
;
1342 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1343 TALLOC_CTX
*mem_ctx
,
1344 int argc
, const char **argv
)
1346 WERROR werror
= WERR_OK
;
1349 const char *architecture
= NULL
;
1352 printf("Usage: enumdrivers [level] [architecture]\n");
1357 level
= atoi(argv
[1]);
1361 architecture
= argv
[2];
1365 return enum_driver_by_architecture(cli
, mem_ctx
,
1370 /* loop through and print driver info level for each architecture */
1371 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1372 /* check to see if we already asked for this architecture string */
1374 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1378 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1379 archi_table
[i
].long_archi
,
1381 if (!W_ERROR_IS_OK(werror
)) {
1389 /****************************************************************************
1390 ****************************************************************************/
1392 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1394 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1397 /****************************************************************************
1398 ****************************************************************************/
1400 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1401 TALLOC_CTX
*mem_ctx
,
1402 int argc
, const char **argv
)
1406 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1409 union spoolss_DriverDirectoryInfo info
;
1413 printf("Usage: %s [environment]\n", argv
[0]);
1417 /* Get the arguments need to open the printer handle */
1423 /* Get the directory. Only use Info level 1 */
1425 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1426 cli
->srv_name_slash
,
1434 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1436 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1438 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1439 cli
->srv_name_slash
,
1449 if (W_ERROR_IS_OK(result
)) {
1450 display_printdriverdir_1(&info
.info1
);
1456 /****************************************************************************
1457 ****************************************************************************/
1459 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1460 struct spoolss_AddDriverInfo3
*info
,
1466 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1468 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1470 info
->version
= archi_table
[i
].version
;
1471 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1476 if (archi_table
[i
].long_archi
== NULL
)
1478 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1485 /**************************************************************************
1486 wrapper for strtok to get the next parameter from a delimited list.
1487 Needed to handle the empty parameter string denoted by "NULL"
1488 *************************************************************************/
1490 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1491 const char *delim
, const char **dest
,
1496 /* get the next token */
1497 ptr
= strtok_r(str
, delim
, saveptr
);
1499 /* a string of 'NULL' is used to represent an empty
1500 parameter because two consecutive delimiters
1501 will not return an empty string. See man strtok(3)
1503 if (ptr
&& (StrCaseCmp(ptr
, "NULL") == 0)) {
1508 *dest
= talloc_strdup(mem_ctx
, ptr
);
1514 /********************************************************************************
1515 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1516 string in the form of
1517 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1518 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1519 <Default Data Type>:<Comma Separated list of Files>
1520 *******************************************************************************/
1522 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1527 char *saveptr
= NULL
;
1528 struct spoolss_StringArray
*deps
;
1529 const char **file_array
= NULL
;
1532 /* fill in the UNISTR fields */
1533 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1534 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1535 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1536 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1537 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1538 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1539 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1541 /* <Comma Separated List of Dependent Files> */
1542 /* save the beginning of the string */
1543 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1546 /* begin to strip out each filename */
1547 str
= strtok_r(str
, ",", &saveptr
);
1549 /* no dependent files, we are done */
1554 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1559 while (str
!= NULL
) {
1560 add_string_to_array(deps
, str
, &file_array
, &count
);
1561 str
= strtok_r(NULL
, ",", &saveptr
);
1564 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1565 if (!deps
->string
) {
1569 for (i
=0; i
< count
; i
++) {
1570 deps
->string
[i
] = file_array
[i
];
1573 r
->dependent_files
= deps
;
1578 /****************************************************************************
1579 ****************************************************************************/
1581 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1582 TALLOC_CTX
*mem_ctx
,
1583 int argc
, const char **argv
)
1588 struct spoolss_AddDriverInfoCtr info_ctr
;
1589 struct spoolss_AddDriverInfo3 info3
;
1593 /* parse the command arguments */
1594 if (argc
!= 3 && argc
!= 4)
1596 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1597 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1598 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1599 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1600 printf ("\t[version]\n");
1605 /* Fill in the spoolss_AddDriverInfo3 struct */
1608 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1610 printf ("Error Unknown architechture [%s]\n", argv
[1]);
1611 return WERR_INVALID_PARAM
;
1614 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1616 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1617 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1619 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1620 return WERR_INVALID_PARAM
;
1623 /* if printer driver version specified, override the default version
1624 * used by the architecture. This allows installation of Windows
1625 * 2000 (version 3) printer drivers. */
1628 info3
.version
= atoi(argv
[3]);
1632 info_ctr
.level
= level
;
1633 info_ctr
.info
.info3
= &info3
;
1635 status
= rpccli_spoolss_AddPrinterDriver(cli
, mem_ctx
,
1636 cli
->srv_name_slash
,
1639 if (!NT_STATUS_IS_OK(status
)) {
1640 return ntstatus_to_werror(status
);
1642 if (W_ERROR_IS_OK(result
)) {
1643 printf ("Printer Driver %s successfully installed.\n",
1651 /****************************************************************************
1652 ****************************************************************************/
1654 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1655 TALLOC_CTX
*mem_ctx
,
1656 int argc
, const char **argv
)
1659 struct spoolss_SetPrinterInfoCtr info_ctr
;
1660 struct spoolss_SetPrinterInfo2 info2
;
1662 /* parse the command arguments */
1665 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1669 /* Fill in the DRIVER_INFO_2 struct */
1672 info2
.printername
= argv
[1];
1673 info2
.drivername
= argv
[3];
1674 info2
.sharename
= argv
[2];
1675 info2
.portname
= argv
[4];
1676 info2
.comment
= "Created by rpcclient";
1677 info2
.printprocessor
= "winprint";
1678 info2
.datatype
= "RAW";
1679 info2
.devmode_ptr
= 0;
1680 info2
.secdesc_ptr
= 0;
1681 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1683 info2
.defaultpriority
= 0;
1684 info2
.starttime
= 0;
1685 info2
.untiltime
= 0;
1687 /* These three fields must not be used by AddPrinter()
1688 as defined in the MS Platform SDK documentation..
1692 info2.averageppm = 0;
1696 info_ctr
.info
.info2
= &info2
;
1698 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1700 if (W_ERROR_IS_OK(result
))
1701 printf ("Printer %s successfully installed.\n", argv
[1]);
1706 /****************************************************************************
1707 ****************************************************************************/
1709 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1710 TALLOC_CTX
*mem_ctx
,
1711 int argc
, const char **argv
)
1713 struct policy_handle pol
;
1717 const char *printername
;
1718 union spoolss_PrinterInfo info
;
1719 struct spoolss_SetPrinterInfoCtr info_ctr
;
1720 struct spoolss_DevmodeContainer devmode_ctr
;
1721 struct sec_desc_buf secdesc_ctr
;
1723 ZERO_STRUCT(devmode_ctr
);
1724 ZERO_STRUCT(secdesc_ctr
);
1726 /* parse the command arguments */
1729 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1733 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1735 /* Get a printer handle */
1737 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1741 if (!W_ERROR_IS_OK(result
))
1744 /* Get printer info */
1746 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1751 if (!W_ERROR_IS_OK(result
)) {
1752 printf ("Unable to retrieve printer information!\n");
1756 /* Set the printer driver */
1758 info
.info2
.drivername
= argv
[2];
1759 info
.info2
.devmode
= NULL
;
1760 info
.info2
.secdesc
= NULL
;
1763 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
1765 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
1772 if (!W_ERROR_IS_OK(result
)) {
1773 printf("SetPrinter call failed!\n");
1777 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1782 if (is_valid_policy_hnd(&pol
))
1783 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1789 /****************************************************************************
1790 ****************************************************************************/
1792 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
1793 TALLOC_CTX
*mem_ctx
,
1794 int argc
, const char **argv
)
1796 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
1802 const char *arch
= NULL
;
1803 uint32_t delete_flags
= 0;
1805 /* parse the command arguments */
1806 if (argc
< 2 || argc
> 4) {
1807 printf ("Usage: %s <driver> [arch] [version]\n", argv
[0]);
1814 vers
= atoi (argv
[3]);
1817 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
1820 /* delete the driver for all architectures */
1821 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1823 if (arch
&& !strequal( archi_table
[i
].long_archi
, arch
))
1826 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
1829 /* make the call to remove the driver */
1830 status
= rpccli_spoolss_DeletePrinterDriverEx(cli
, mem_ctx
,
1831 cli
->srv_name_slash
,
1832 archi_table
[i
].long_archi
,
1835 archi_table
[i
].version
,
1838 if ( !W_ERROR_IS_OK(result
) )
1840 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1841 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1842 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
1847 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
1848 archi_table
[i
].long_archi
, archi_table
[i
].version
);
1857 /****************************************************************************
1858 ****************************************************************************/
1860 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
1861 TALLOC_CTX
*mem_ctx
,
1862 int argc
, const char **argv
)
1864 WERROR result
= WERR_OK
;
1868 /* parse the command arguments */
1870 printf ("Usage: %s <driver>\n", argv
[0]);
1874 /* delete the driver for all architectures */
1875 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1876 /* make the call to remove the driver */
1877 status
= rpccli_spoolss_DeletePrinterDriver(cli
, mem_ctx
,
1878 cli
->srv_name_slash
,
1879 archi_table
[i
].long_archi
,
1882 if (!NT_STATUS_IS_OK(status
)) {
1885 if ( !W_ERROR_IS_OK(result
) ) {
1886 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1887 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1888 argv
[1], archi_table
[i
].long_archi
,
1892 printf ("Driver %s removed for arch [%s].\n", argv
[1],
1893 archi_table
[i
].long_archi
);
1900 /****************************************************************************
1901 ****************************************************************************/
1903 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
1904 TALLOC_CTX
*mem_ctx
,
1905 int argc
, const char **argv
)
1909 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
1912 union spoolss_PrintProcessorDirectoryInfo info
;
1915 /* parse the command arguments */
1917 printf ("Usage: %s [environment]\n", argv
[0]);
1922 environment
= argv
[1];
1925 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1926 cli
->srv_name_slash
,
1934 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1936 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1938 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1939 cli
->srv_name_slash
,
1949 if (W_ERROR_IS_OK(result
)) {
1950 printf("%s\n", info
.info1
.directory_name
);
1956 /****************************************************************************
1957 ****************************************************************************/
1959 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
1960 int argc
, const char **argv
)
1962 struct policy_handle handle
;
1965 const char *printername
;
1966 union spoolss_AddFormInfo info
;
1967 struct spoolss_AddFormInfo1 info1
;
1968 struct spoolss_AddFormInfo2 info2
;
1971 /* Parse the command arguments */
1973 if (argc
< 3 || argc
> 5) {
1974 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
1978 /* Get a printer handle */
1980 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1982 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1986 if (!W_ERROR_IS_OK(werror
))
1989 /* Dummy up some values for the form data */
1992 level
= atoi(argv
[3]);
1997 info1
.flags
= SPOOLSS_FORM_USER
;
1998 info1
.form_name
= argv
[2];
1999 info1
.size
.width
= 100;
2000 info1
.size
.height
= 100;
2001 info1
.area
.left
= 0;
2002 info1
.area
.top
= 10;
2003 info1
.area
.right
= 20;
2004 info1
.area
.bottom
= 30;
2006 info
.info1
= &info1
;
2010 info2
.flags
= SPOOLSS_FORM_USER
;
2011 info2
.form_name
= argv
[2];
2012 info2
.size
.width
= 100;
2013 info2
.size
.height
= 100;
2014 info2
.area
.left
= 0;
2015 info2
.area
.top
= 10;
2016 info2
.area
.right
= 20;
2017 info2
.area
.bottom
= 30;
2018 info2
.keyword
= argv
[2];
2019 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2020 info2
.mui_dll
= NULL
;
2021 info2
.ressource_id
= 0;
2022 info2
.display_name
= argv
[2];
2025 info
.info2
= &info2
;
2033 status
= rpccli_spoolss_AddForm(cli
, mem_ctx
,
2040 if (is_valid_policy_hnd(&handle
))
2041 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2046 /****************************************************************************
2047 ****************************************************************************/
2049 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2050 int argc
, const char **argv
)
2052 struct policy_handle handle
;
2055 const char *printername
;
2056 union spoolss_AddFormInfo info
;
2057 struct spoolss_AddFormInfo1 info1
;
2059 /* Parse the command arguments */
2062 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2066 /* Get a printer handle */
2068 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2070 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2072 SEC_FLAG_MAXIMUM_ALLOWED
,
2074 if (!W_ERROR_IS_OK(werror
))
2077 /* Dummy up some values for the form data */
2079 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2080 info1
.size
.width
= 100;
2081 info1
.size
.height
= 100;
2082 info1
.area
.left
= 0;
2083 info1
.area
.top
= 1000;
2084 info1
.area
.right
= 2000;
2085 info1
.area
.bottom
= 3000;
2086 info1
.form_name
= argv
[2];
2088 info
.info1
= &info1
;
2092 status
= rpccli_spoolss_SetForm(cli
, mem_ctx
,
2100 if (is_valid_policy_hnd(&handle
))
2101 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2106 /****************************************************************************
2107 ****************************************************************************/
2109 static const char *get_form_flag(int form_flag
)
2111 switch (form_flag
) {
2112 case SPOOLSS_FORM_USER
:
2114 case SPOOLSS_FORM_BUILTIN
:
2115 return "FORM_BUILTIN";
2116 case SPOOLSS_FORM_PRINTER
:
2117 return "FORM_PRINTER";
2123 /****************************************************************************
2124 ****************************************************************************/
2126 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2129 "\tflag: %s (%d)\n" \
2130 "\twidth: %d, length: %d\n" \
2131 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2132 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2133 r
->size
.width
, r
->size
.height
,
2134 r
->area
.left
, r
->area
.right
,
2135 r
->area
.top
, r
->area
.bottom
);
2138 /****************************************************************************
2139 ****************************************************************************/
2141 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2144 "\tflag: %s (%d)\n" \
2145 "\twidth: %d, length: %d\n" \
2146 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2147 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2148 r
->size
.width
, r
->size
.height
,
2149 r
->area
.left
, r
->area
.right
,
2150 r
->area
.top
, r
->area
.bottom
);
2151 printf("\tkeyword: %s\n", r
->keyword
);
2152 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2153 printf("\tmui_dll: %s\n", r
->mui_dll
);
2154 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2155 printf("\tdisplay_name: %s\n", r
->display_name
);
2156 printf("\tlang_id: %d\n", r
->lang_id
);
2160 /****************************************************************************
2161 ****************************************************************************/
2163 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2164 int argc
, const char **argv
)
2166 struct policy_handle handle
;
2169 const char *printername
;
2171 uint32_t offered
= 0;
2172 union spoolss_FormInfo info
;
2176 /* Parse the command arguments */
2178 if (argc
< 3 || argc
> 5) {
2179 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2183 /* Get a printer handle */
2185 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2187 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2189 SEC_FLAG_MAXIMUM_ALLOWED
,
2191 if (!W_ERROR_IS_OK(werror
))
2195 level
= atoi(argv
[3]);
2200 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2209 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2210 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2212 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2223 if (!NT_STATUS_IS_OK(status
)) {
2229 display_form_info1(&info
.info1
);
2232 display_form_info2(&info
.info2
);
2237 if (is_valid_policy_hnd(&handle
))
2238 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2243 /****************************************************************************
2244 ****************************************************************************/
2246 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2247 TALLOC_CTX
*mem_ctx
, int argc
,
2250 struct policy_handle handle
;
2253 const char *printername
;
2255 /* Parse the command arguments */
2258 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2262 /* Get a printer handle */
2264 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2266 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2268 SEC_FLAG_MAXIMUM_ALLOWED
,
2270 if (!W_ERROR_IS_OK(werror
))
2273 /* Delete the form */
2275 status
= rpccli_spoolss_DeleteForm(cli
, mem_ctx
,
2279 if (!NT_STATUS_IS_OK(status
)) {
2280 return ntstatus_to_werror(status
);
2284 if (is_valid_policy_hnd(&handle
))
2285 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2290 /****************************************************************************
2291 ****************************************************************************/
2293 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2294 TALLOC_CTX
*mem_ctx
, int argc
,
2297 struct policy_handle handle
;
2299 const char *printername
;
2300 uint32_t num_forms
, level
= 1, i
;
2301 union spoolss_FormInfo
*forms
;
2303 /* Parse the command arguments */
2305 if (argc
< 2 || argc
> 4) {
2306 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2310 /* Get a printer handle */
2312 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2314 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2316 SEC_FLAG_MAXIMUM_ALLOWED
,
2318 if (!W_ERROR_IS_OK(werror
))
2322 level
= atoi(argv
[2]);
2325 /* Enumerate forms */
2327 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2334 if (!W_ERROR_IS_OK(werror
))
2337 /* Display output */
2339 for (i
= 0; i
< num_forms
; i
++) {
2342 display_form_info1(&forms
[i
].info1
);
2345 display_form_info2(&forms
[i
].info2
);
2351 if (is_valid_policy_hnd(&handle
))
2352 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2357 /****************************************************************************
2358 ****************************************************************************/
2360 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2361 TALLOC_CTX
*mem_ctx
,
2362 int argc
, const char **argv
)
2366 const char *printername
;
2367 struct policy_handle pol
;
2368 union spoolss_PrinterInfo info
;
2369 enum winreg_Type type
;
2370 union spoolss_PrinterData data
;
2372 /* parse the command arguments */
2374 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2375 " <value> <data>\n",
2377 result
= WERR_INVALID_PARAM
;
2381 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2385 if (strequal(argv
[2], "string")) {
2389 if (strequal(argv
[2], "binary")) {
2393 if (strequal(argv
[2], "dword")) {
2397 if (strequal(argv
[2], "multistring")) {
2398 type
= REG_MULTI_SZ
;
2401 if (type
== REG_NONE
) {
2402 printf("Unknown data type: %s\n", argv
[2]);
2403 result
= WERR_INVALID_PARAM
;
2407 /* get a printer handle */
2409 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2411 SEC_FLAG_MAXIMUM_ALLOWED
,
2413 if (!W_ERROR_IS_OK(result
)) {
2417 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2422 if (!W_ERROR_IS_OK(result
)) {
2426 printf("%s\n", current_timestring(mem_ctx
, true));
2427 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2429 /* Set the printer data */
2433 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2434 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2437 data
.value
= strtoul(argv
[4], NULL
, 10);
2440 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2442 case REG_MULTI_SZ
: {
2444 const char **strings
= NULL
;
2446 for (i
=4; i
<argc
; i
++) {
2447 if (strcmp(argv
[i
], "NULL") == 0) {
2450 if (!add_string_to_array(mem_ctx
, argv
[i
],
2453 result
= WERR_NOMEM
;
2457 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2458 if (!data
.string_array
) {
2459 result
= WERR_NOMEM
;
2462 for (i
=0; i
< num_strings
; i
++) {
2463 data
.string_array
[i
] = strings
[i
];
2468 printf("Unknown data type: %s\n", argv
[2]);
2469 result
= WERR_INVALID_PARAM
;
2473 status
= rpccli_spoolss_SetPrinterData(cli
, mem_ctx
,
2475 argv
[3], /* value_name */
2478 0, /* autocalculated size */
2480 if (!W_ERROR_IS_OK(result
)) {
2481 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2484 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2486 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2491 if (!W_ERROR_IS_OK(result
)) {
2495 printf("%s\n", current_timestring(mem_ctx
, true));
2496 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2500 if (is_valid_policy_hnd(&pol
)) {
2501 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
2507 /****************************************************************************
2508 ****************************************************************************/
2510 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2512 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2513 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2517 /****************************************************************************
2518 ****************************************************************************/
2520 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2522 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2523 r
->position
, r
->job_id
,
2524 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2525 r
->total_pages
, r
->size
);
2528 /****************************************************************************
2529 ****************************************************************************/
2531 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2533 printf("jobid[%d], next_jobid[%d]\n",
2534 r
->job_id
, r
->next_job_id
);
2537 /****************************************************************************
2538 ****************************************************************************/
2540 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2542 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2543 r
->position
, r
->job_id
,
2544 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2545 r
->total_pages
, r
->size
, r
->size_high
);
2548 /****************************************************************************
2549 ****************************************************************************/
2551 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2552 TALLOC_CTX
*mem_ctx
, int argc
,
2556 uint32_t level
= 1, count
, i
;
2557 const char *printername
;
2558 struct policy_handle hnd
;
2559 union spoolss_JobInfo
*info
;
2561 if (argc
< 2 || argc
> 3) {
2562 printf("Usage: %s printername [level]\n", argv
[0]);
2567 level
= atoi(argv
[2]);
2570 /* Open printer handle */
2572 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2574 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2576 SEC_FLAG_MAXIMUM_ALLOWED
,
2578 if (!W_ERROR_IS_OK(result
))
2581 /* Enumerate ports */
2583 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2591 if (!W_ERROR_IS_OK(result
)) {
2595 for (i
= 0; i
< count
; i
++) {
2598 display_job_info1(&info
[i
].info1
);
2601 display_job_info2(&info
[i
].info2
);
2604 d_printf("unknown info level %d\n", level
);
2610 if (is_valid_policy_hnd(&hnd
)) {
2611 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2617 /****************************************************************************
2618 ****************************************************************************/
2620 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2621 TALLOC_CTX
*mem_ctx
, int argc
,
2625 const char *printername
;
2626 struct policy_handle hnd
;
2629 union spoolss_JobInfo info
;
2631 if (argc
< 3 || argc
> 4) {
2632 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2636 job_id
= atoi(argv
[2]);
2639 level
= atoi(argv
[3]);
2642 /* Open printer handle */
2644 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2646 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2648 SEC_FLAG_MAXIMUM_ALLOWED
,
2650 if (!W_ERROR_IS_OK(result
)) {
2654 /* Enumerate ports */
2656 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2663 if (!W_ERROR_IS_OK(result
)) {
2669 display_job_info1(&info
.info1
);
2672 display_job_info2(&info
.info2
);
2675 display_job_info3(&info
.info3
);
2678 display_job_info4(&info
.info4
);
2681 d_printf("unknown info level %d\n", level
);
2686 if (is_valid_policy_hnd(&hnd
)) {
2687 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2693 /****************************************************************************
2694 ****************************************************************************/
2696 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
2697 TALLOC_CTX
*mem_ctx
, int argc
,
2702 const char *printername
;
2703 struct policy_handle hnd
;
2705 enum spoolss_JobControl command
;
2708 printf("Usage: %s printername job_id command\n", argv
[0]);
2712 job_id
= atoi(argv
[2]);
2713 command
= atoi(argv
[3]);
2715 /* Open printer handle */
2717 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2719 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2721 SEC_FLAG_MAXIMUM_ALLOWED
,
2723 if (!W_ERROR_IS_OK(result
)) {
2729 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
2736 if (!W_ERROR_IS_OK(result
)) {
2741 if (is_valid_policy_hnd(&hnd
)) {
2742 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2748 /****************************************************************************
2749 ****************************************************************************/
2751 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
2752 TALLOC_CTX
*mem_ctx
, int argc
,
2758 const char *printername
;
2759 struct policy_handle hnd
;
2760 uint32_t value_offered
= 0;
2761 const char *value_name
= NULL
;
2762 uint32_t value_needed
;
2763 enum winreg_Type type
;
2764 uint8_t *data
= NULL
;
2765 uint32_t data_offered
= 0;
2766 uint32_t data_needed
;
2769 printf("Usage: %s printername\n", argv
[0]);
2773 /* Open printer handle */
2775 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2777 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2779 SEC_FLAG_MAXIMUM_ALLOWED
,
2781 if (!W_ERROR_IS_OK(result
)) {
2785 /* Enumerate data */
2787 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2799 data_offered
= data_needed
;
2800 value_offered
= value_needed
;
2801 data
= talloc_zero_array(mem_ctx
, uint8_t, data_needed
);
2802 value_name
= talloc_zero_array(mem_ctx
, char, value_needed
);
2804 while (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2806 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2817 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2818 struct regval_blob v
;
2819 fstrcpy(v
.valuename
, value_name
);
2821 v
.size
= data_offered
;
2823 display_reg_value(v
);
2827 if (W_ERROR_V(result
) == ERRnomoreitems
) {
2828 result
= W_ERROR(ERRsuccess
);
2832 if (is_valid_policy_hnd(&hnd
)) {
2833 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2839 /****************************************************************************
2840 ****************************************************************************/
2842 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
2843 TALLOC_CTX
*mem_ctx
, int argc
,
2848 const char *printername
;
2849 struct policy_handle hnd
;
2851 struct spoolss_PrinterEnumValues
*info
;
2854 printf("Usage: %s printername <keyname>\n", argv
[0]);
2858 /* Open printer handle */
2860 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2862 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2864 SEC_FLAG_MAXIMUM_ALLOWED
,
2866 if (!W_ERROR_IS_OK(result
)) {
2870 /* Enumerate subkeys */
2872 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
2878 if (!W_ERROR_IS_OK(result
)) {
2882 for (i
=0; i
< count
; i
++) {
2883 display_printer_data(info
[i
].value_name
,
2889 if (is_valid_policy_hnd(&hnd
)) {
2890 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2896 /****************************************************************************
2897 ****************************************************************************/
2899 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
2900 TALLOC_CTX
*mem_ctx
, int argc
,
2904 const char *printername
;
2905 const char *keyname
= NULL
;
2906 struct policy_handle hnd
;
2907 const char **key_buffer
= NULL
;
2909 uint32_t offered
= 0;
2911 if (argc
< 2 || argc
> 4) {
2912 printf("Usage: %s printername [keyname] [offered]\n", argv
[0]);
2923 offered
= atoi(argv
[3]);
2926 /* Open printer handle */
2928 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2930 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2932 SEC_FLAG_MAXIMUM_ALLOWED
,
2934 if (!W_ERROR_IS_OK(result
)) {
2938 /* Enumerate subkeys */
2940 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
2946 if (!W_ERROR_IS_OK(result
)) {
2950 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
2951 printf("%s\n", key_buffer
[i
]);
2956 if (is_valid_policy_hnd(&hnd
)) {
2957 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2963 /****************************************************************************
2964 ****************************************************************************/
2966 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
2967 TALLOC_CTX
*mem_ctx
, int argc
,
2970 const char *printername
;
2971 const char *clientname
;
2972 struct policy_handle hnd
;
2975 struct spoolss_NotifyOption option
;
2978 printf("Usage: %s printername\n", argv
[0]);
2985 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2987 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2989 SEC_FLAG_MAXIMUM_ALLOWED
,
2991 if (!W_ERROR_IS_OK(result
)) {
2992 printf("Error opening %s\n", argv
[1]);
2996 /* Create spool options */
3001 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3002 if (option
.types
== NULL
) {
3003 result
= WERR_NOMEM
;
3007 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3008 option
.types
[0].count
= 1;
3009 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3010 if (option
.types
[0].fields
== NULL
) {
3011 result
= WERR_NOMEM
;
3014 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3016 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3017 option
.types
[1].count
= 1;
3018 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3019 if (option
.types
[1].fields
== NULL
) {
3020 result
= WERR_NOMEM
;
3023 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3025 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
3027 result
= WERR_NOMEM
;
3033 status
= rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli
, mem_ctx
,
3041 if (!W_ERROR_IS_OK(result
)) {
3042 printf("Error rffpcnex %s\n", argv
[1]);
3047 if (is_valid_policy_hnd(&hnd
))
3048 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3053 /****************************************************************************
3054 ****************************************************************************/
3056 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3057 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3059 union spoolss_PrinterInfo info1
, info2
;
3061 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3063 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3064 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3069 if ( !W_ERROR_IS_OK(werror
) ) {
3070 printf("failed (%s)\n", win_errstr(werror
));
3071 talloc_destroy(mem_ctx
);
3076 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3077 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3082 if ( !W_ERROR_IS_OK(werror
) ) {
3083 printf("failed (%s)\n", win_errstr(werror
));
3084 talloc_destroy(mem_ctx
);
3089 talloc_destroy(mem_ctx
);
3094 /****************************************************************************
3095 ****************************************************************************/
3097 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3098 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3100 union spoolss_PrinterInfo info1
, info2
;
3102 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3103 SEC_DESC
*sd1
, *sd2
;
3107 printf("Retrieving printer security for %s...", cli1
->desthost
);
3108 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3113 if ( !W_ERROR_IS_OK(werror
) ) {
3114 printf("failed (%s)\n", win_errstr(werror
));
3120 printf("Retrieving printer security for %s...", cli2
->desthost
);
3121 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3126 if ( !W_ERROR_IS_OK(werror
) ) {
3127 printf("failed (%s)\n", win_errstr(werror
));
3136 sd1
= info1
.info3
.secdesc
;
3137 sd2
= info2
.info3
.secdesc
;
3139 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3140 printf("NULL secdesc!\n");
3145 if (!security_descriptor_equal( sd1
, sd2
) ) {
3146 printf("Security Descriptors *not* equal!\n");
3151 printf("Security descriptors match\n");
3154 talloc_destroy(mem_ctx
);
3159 /****************************************************************************
3160 ****************************************************************************/
3162 extern struct user_auth_info
*rpcclient_auth_info
;
3164 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3165 TALLOC_CTX
*mem_ctx
, int argc
,
3168 const char *printername
;
3169 char *printername_path
= NULL
;
3170 struct cli_state
*cli_server2
= NULL
;
3171 struct rpc_pipe_client
*cli2
= NULL
;
3172 struct policy_handle hPrinter1
, hPrinter2
;
3177 printf("Usage: %s <printer> <server>\n", argv
[0]);
3181 printername
= argv
[1];
3183 /* first get the connection to the remote server */
3185 nt_status
= cli_full_connection(&cli_server2
, global_myname(), argv
[2],
3188 get_cmdline_auth_info_username(rpcclient_auth_info
),
3190 get_cmdline_auth_info_password(rpcclient_auth_info
),
3191 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info
) ? CLI_FULL_CONNECTION_USE_KERBEROS
: 0,
3192 get_cmdline_auth_info_signing_state(rpcclient_auth_info
), NULL
);
3194 if ( !NT_STATUS_IS_OK(nt_status
) )
3195 return WERR_GENERAL_FAILURE
;
3197 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
.syntax_id
,
3199 if (!NT_STATUS_IS_OK(nt_status
)) {
3200 printf("failed to open spoolss pipe on server %s (%s)\n",
3201 argv
[2], nt_errstr(nt_status
));
3202 return WERR_GENERAL_FAILURE
;
3205 /* now open up both printers */
3207 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3209 printf("Opening %s...", printername_path
);
3211 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3215 if ( !W_ERROR_IS_OK(werror
) ) {
3216 printf("failed (%s)\n", win_errstr(werror
));
3221 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3223 printf("Opening %s...", printername_path
);
3224 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3228 if ( !W_ERROR_IS_OK(werror
) ) {
3229 printf("failed (%s)\n", win_errstr(werror
));
3234 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3235 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3237 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3244 printf("Closing printers...");
3245 rpccli_spoolss_ClosePrinter( cli
, mem_ctx
, &hPrinter1
, NULL
);
3246 rpccli_spoolss_ClosePrinter( cli2
, mem_ctx
, &hPrinter2
, NULL
);
3249 /* close the second remote connection */
3251 cli_shutdown( cli_server2
);
3255 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3257 printf("print_processor_name: %s\n", r
->print_processor_name
);
3260 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3261 TALLOC_CTX
*mem_ctx
, int argc
,
3265 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3266 uint32_t num_procs
, level
= 1, i
;
3267 union spoolss_PrintProcessorInfo
*procs
;
3269 /* Parse the command arguments */
3271 if (argc
< 1 || argc
> 4) {
3272 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3277 environment
= argv
[1];
3281 level
= atoi(argv
[2]);
3284 /* Enumerate Print Processors */
3286 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3287 cli
->srv_name_slash
,
3293 if (!W_ERROR_IS_OK(werror
))
3296 /* Display output */
3298 for (i
= 0; i
< num_procs
; i
++) {
3301 display_proc_info1(&procs
[i
].info1
);
3310 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3312 printf("name_array: %s\n", r
->name_array
);
3315 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3316 TALLOC_CTX
*mem_ctx
, int argc
,
3320 const char *print_processor_name
= "winprint";
3321 uint32_t num_procs
, level
= 1, i
;
3322 union spoolss_PrintProcDataTypesInfo
*procs
;
3324 /* Parse the command arguments */
3326 if (argc
< 1 || argc
> 4) {
3327 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3332 print_processor_name
= argv
[1];
3336 level
= atoi(argv
[2]);
3339 /* Enumerate Print Processor Data Types */
3341 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3342 cli
->srv_name_slash
,
3343 print_processor_name
,
3348 if (!W_ERROR_IS_OK(werror
))
3351 /* Display output */
3353 for (i
= 0; i
< num_procs
; i
++) {
3356 display_proc_data_types_info1(&procs
[i
].info1
);
3365 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3367 printf("monitor_name: %s\n", r
->monitor_name
);
3370 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3372 printf("monitor_name: %s\n", r
->monitor_name
);
3373 printf("environment: %s\n", r
->environment
);
3374 printf("dll_name: %s\n", r
->dll_name
);
3377 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3378 TALLOC_CTX
*mem_ctx
, int argc
,
3382 uint32_t count
, level
= 1, i
;
3383 union spoolss_MonitorInfo
*info
;
3385 /* Parse the command arguments */
3388 printf("Usage: %s [level]\n", argv
[0]);
3393 level
= atoi(argv
[1]);
3396 /* Enumerate Print Monitors */
3398 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3399 cli
->srv_name_slash
,
3404 if (!W_ERROR_IS_OK(werror
)) {
3408 /* Display output */
3410 for (i
= 0; i
< count
; i
++) {
3413 display_monitor1(&info
[i
].info1
);
3416 display_monitor2(&info
[i
].info2
);
3425 static WERROR
cmd_spoolss_create_printer_ic(struct rpc_pipe_client
*cli
,
3426 TALLOC_CTX
*mem_ctx
, int argc
,
3431 struct policy_handle handle
, gdi_handle
;
3432 const char *printername
;
3433 struct spoolss_DevmodeContainer devmode_ctr
;
3435 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3437 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3439 SEC_FLAG_MAXIMUM_ALLOWED
,
3441 if (!W_ERROR_IS_OK(result
)) {
3445 ZERO_STRUCT(devmode_ctr
);
3447 status
= rpccli_spoolss_CreatePrinterIC(cli
, mem_ctx
,
3452 if (!W_ERROR_IS_OK(result
)) {
3457 if (is_valid_policy_hnd(&gdi_handle
)) {
3458 rpccli_spoolss_DeletePrinterIC(cli
, mem_ctx
, &gdi_handle
, NULL
);
3460 if (is_valid_policy_hnd(&handle
)) {
3461 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3467 /* List of commands exported by this module */
3468 struct cmd_set spoolss_commands
[] = {
3472 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a print driver", "" },
3473 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a printer", "" },
3474 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver", "" },
3475 { "deldriverex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriverex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver with files", "" },
3476 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data", "" },
3477 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data for a key", "" },
3478 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer keys", "" },
3479 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate print jobs", "" },
3480 { "getjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_get_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print job", "" },
3481 { "setjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_set_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set print job", "" },
3482 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer ports", "" },
3483 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate installed printer drivers", "" },
3484 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printers", "" },
3485 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver data", "" },
3486 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer driver data with keyname", ""},
3487 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver information", "" },
3488 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver upload directory", "" },
3489 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer info", "" },
3490 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Open printer handle", "" },
3491 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer driver", "" },
3492 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print processor directory", "" },
3493 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add form", "" },
3494 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set form", "" },
3495 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get form", "" },
3496 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete form", "" },
3497 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate forms", "" },
3498 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer comment", "" },
3499 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printername", "" },
3500 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set REG_SZ printer data", "" },
3501 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Rffpcnex test", "" },
3502 { "printercmp", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_printercmp
, &ndr_table_spoolss
.syntax_id
, NULL
, "Printer comparison test", "" },
3503 { "enumprocs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_procs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processors", "" },
3504 { "enumprocdatatypes", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_proc_data_types
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processor Data Types", "" },
3505 { "enummonitors", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_monitors
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Monitors", "" },
3506 { "createprinteric", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_create_printer_ic
, &ndr_table_spoolss
.syntax_id
, NULL
, "Create Printer IC", "" },