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
;
867 struct regval_blob value
;
869 enum winreg_Type type
;
870 uint8_t *buffer
= NULL
;
871 uint32_t offered
= 0;
875 printf("Usage: %s <printername> <keyname> <valuename>\n",
877 printf("<printername> of . queries print server\n");
883 /* Open a printer handle */
885 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
886 fstrcpy(printername
, cli
->srv_name_slash
);
888 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
889 cli
->srv_name_slash
, argv
[1]);
891 /* get a printer handle */
893 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
895 SEC_FLAG_MAXIMUM_ALLOWED
,
897 if (!W_ERROR_IS_OK(result
))
900 /* Get printer info */
902 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
911 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
913 buffer
= talloc_array(mem_ctx
, uint8_t, needed
);
914 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
925 if (!NT_STATUS_IS_OK(status
)) {
929 if (!W_ERROR_IS_OK(result
)) {
934 if (!W_ERROR_IS_OK(result
))
937 /* Display printer data */
939 fstrcpy(value
.valuename
, valuename
);
942 value
.data_p
= buffer
;
944 display_reg_value(value
);
947 if (is_valid_policy_hnd(&pol
))
948 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
953 /****************************************************************************
954 ****************************************************************************/
956 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
962 printf("Printer Driver Info 1:\n");
963 printf("\tDriver Name: [%s]\n", r
->driver_name
);
967 /****************************************************************************
968 ****************************************************************************/
970 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
976 printf("Printer Driver Info 2:\n");
977 printf("\tVersion: [%x]\n", r
->version
);
978 printf("\tDriver Name: [%s]\n", r
->driver_name
);
979 printf("\tArchitecture: [%s]\n", r
->architecture
);
980 printf("\tDriver Path: [%s]\n", r
->driver_path
);
981 printf("\tDatafile: [%s]\n", r
->data_file
);
982 printf("\tConfigfile: [%s]\n", r
->config_file
);
986 /****************************************************************************
987 ****************************************************************************/
989 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
997 printf("Printer Driver Info 3:\n");
998 printf("\tVersion: [%x]\n", r
->version
);
999 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1000 printf("\tArchitecture: [%s]\n", r
->architecture
);
1001 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1002 printf("\tDatafile: [%s]\n", r
->data_file
);
1003 printf("\tConfigfile: [%s]\n", r
->config_file
);
1004 printf("\tHelpfile: [%s]\n", r
->help_file
);
1006 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1007 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1010 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1011 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1015 /****************************************************************************
1016 ****************************************************************************/
1018 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1026 printf("Printer Driver Info 4:\n");
1027 printf("\tVersion: [%x]\n", r
->version
);
1028 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1029 printf("\tArchitecture: [%s]\n", r
->architecture
);
1030 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1031 printf("\tDatafile: [%s]\n", r
->data_file
);
1032 printf("\tConfigfile: [%s]\n", r
->config_file
);
1033 printf("\tHelpfile: [%s]\n", r
->help_file
);
1035 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1036 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1039 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1040 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1042 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1043 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1048 /****************************************************************************
1049 ****************************************************************************/
1051 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1057 printf("Printer Driver Info 5:\n");
1058 printf("\tVersion: [%x]\n", r
->version
);
1059 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1060 printf("\tArchitecture: [%s]\n", r
->architecture
);
1061 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1062 printf("\tDatafile: [%s]\n", r
->data_file
);
1063 printf("\tConfigfile: [%s]\n", r
->config_file
);
1064 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1065 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1066 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1070 /****************************************************************************
1071 ****************************************************************************/
1073 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1081 printf("Printer Driver Info 6:\n");
1082 printf("\tVersion: [%x]\n", r
->version
);
1083 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1084 printf("\tArchitecture: [%s]\n", r
->architecture
);
1085 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1086 printf("\tDatafile: [%s]\n", r
->data_file
);
1087 printf("\tConfigfile: [%s]\n", r
->config_file
);
1088 printf("\tHelpfile: [%s]\n", r
->help_file
);
1090 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1091 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1094 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1095 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1097 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1098 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1101 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1102 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1103 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1104 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1105 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1106 printf("\tProvider: [%s]\n", r
->provider
);
1111 /****************************************************************************
1112 ****************************************************************************/
1114 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1122 printf("Printer Driver Info 8:\n");
1123 printf("\tVersion: [%x]\n", r
->version
);
1124 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1125 printf("\tArchitecture: [%s]\n", r
->architecture
);
1126 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1127 printf("\tDatafile: [%s]\n", r
->data_file
);
1128 printf("\tConfigfile: [%s]\n", r
->config_file
);
1129 printf("\tHelpfile: [%s]\n", r
->help_file
);
1130 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1131 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1133 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1134 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1137 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1138 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1141 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1142 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1143 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1144 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1145 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1146 printf("\tProvider: [%s]\n", r
->provider
);
1147 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1148 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1149 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1150 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1152 printf("\tInf Path: [%s]\n", r
->inf_path
);
1153 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1154 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1155 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1157 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1158 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1159 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1164 /****************************************************************************
1165 ****************************************************************************/
1167 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1168 TALLOC_CTX
*mem_ctx
,
1169 int argc
, const char **argv
)
1171 struct policy_handle pol
;
1174 const char *printername
;
1176 bool success
= false;
1177 union spoolss_DriverInfo info
;
1178 uint32_t server_major_version
;
1179 uint32_t server_minor_version
;
1181 if ((argc
== 1) || (argc
> 3)) {
1182 printf("Usage: %s <printername> [level]\n", argv
[0]);
1186 /* get the arguments need to open the printer handle */
1188 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1191 level
= atoi(argv
[2]);
1194 /* Open a printer handle */
1196 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1200 if (!W_ERROR_IS_OK(werror
)) {
1201 printf("Error opening printer handle for %s!\n", printername
);
1205 /* loop through and print driver info level for each architecture */
1207 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1209 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1211 archi_table
[i
].long_archi
,
1214 archi_table
[i
].version
,
1217 &server_major_version
,
1218 &server_minor_version
);
1219 if (!W_ERROR_IS_OK(werror
)) {
1223 /* need at least one success */
1227 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1231 display_print_driver1(&info
.info1
);
1234 display_print_driver2(&info
.info2
);
1237 display_print_driver3(&info
.info3
);
1240 display_print_driver4(&info
.info4
);
1243 display_print_driver5(&info
.info5
);
1246 display_print_driver6(&info
.info6
);
1249 display_print_driver8(&info
.info8
);
1252 printf("unknown info level %d\n", level
);
1259 if (is_valid_policy_hnd(&pol
)) {
1260 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1270 /****************************************************************************
1271 ****************************************************************************/
1273 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1274 TALLOC_CTX
*mem_ctx
,
1275 const char *architecture
,
1280 union spoolss_DriverInfo
*info
= NULL
;
1283 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1284 cli
->srv_name_slash
,
1291 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1292 printf("Server does not support environment [%s]\n",
1301 if (!W_ERROR_IS_OK(werror
)) {
1302 printf("Error getting driver for environment [%s] - %s\n",
1303 architecture
, win_errstr(werror
));
1307 printf("\n[%s]\n", architecture
);
1311 for (j
=0; j
< count
; j
++) {
1312 display_print_driver1(&info
[j
].info1
);
1316 for (j
=0; j
< count
; j
++) {
1317 display_print_driver2(&info
[j
].info2
);
1321 for (j
=0; j
< count
; j
++) {
1322 display_print_driver3(&info
[j
].info3
);
1326 for (j
=0; j
< count
; j
++) {
1327 display_print_driver4(&info
[j
].info4
);
1331 for (j
=0; j
< count
; j
++) {
1332 display_print_driver5(&info
[j
].info5
);
1336 for (j
=0; j
< count
; j
++) {
1337 display_print_driver6(&info
[j
].info6
);
1341 for (j
=0; j
< count
; j
++) {
1342 display_print_driver8(&info
[j
].info8
);
1346 printf("unknown info level %d\n", level
);
1347 return WERR_UNKNOWN_LEVEL
;
1353 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1354 TALLOC_CTX
*mem_ctx
,
1355 int argc
, const char **argv
)
1357 WERROR werror
= WERR_OK
;
1360 const char *architecture
= NULL
;
1363 printf("Usage: enumdrivers [level] [architecture]\n");
1368 level
= atoi(argv
[1]);
1372 architecture
= argv
[2];
1376 return enum_driver_by_architecture(cli
, mem_ctx
,
1381 /* loop through and print driver info level for each architecture */
1382 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1383 /* check to see if we already asked for this architecture string */
1385 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1389 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1390 archi_table
[i
].long_archi
,
1392 if (!W_ERROR_IS_OK(werror
)) {
1400 /****************************************************************************
1401 ****************************************************************************/
1403 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1405 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1408 /****************************************************************************
1409 ****************************************************************************/
1411 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1412 TALLOC_CTX
*mem_ctx
,
1413 int argc
, const char **argv
)
1417 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1420 union spoolss_DriverDirectoryInfo info
;
1424 printf("Usage: %s [environment]\n", argv
[0]);
1428 /* Get the arguments need to open the printer handle */
1434 /* Get the directory. Only use Info level 1 */
1436 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1437 cli
->srv_name_slash
,
1445 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1447 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1449 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1450 cli
->srv_name_slash
,
1460 if (W_ERROR_IS_OK(result
)) {
1461 display_printdriverdir_1(&info
.info1
);
1467 /****************************************************************************
1468 ****************************************************************************/
1470 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1471 struct spoolss_AddDriverInfo3
*info
,
1477 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1479 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1481 info
->version
= archi_table
[i
].version
;
1482 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1487 if (archi_table
[i
].long_archi
== NULL
)
1489 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1496 /**************************************************************************
1497 wrapper for strtok to get the next parameter from a delimited list.
1498 Needed to handle the empty parameter string denoted by "NULL"
1499 *************************************************************************/
1501 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1502 const char *delim
, const char **dest
,
1507 /* get the next token */
1508 ptr
= strtok_r(str
, delim
, saveptr
);
1510 /* a string of 'NULL' is used to represent an empty
1511 parameter because two consecutive delimiters
1512 will not return an empty string. See man strtok(3)
1514 if (ptr
&& (StrCaseCmp(ptr
, "NULL") == 0)) {
1519 *dest
= talloc_strdup(mem_ctx
, ptr
);
1525 /********************************************************************************
1526 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1527 string in the form of
1528 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1529 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1530 <Default Data Type>:<Comma Separated list of Files>
1531 *******************************************************************************/
1533 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1538 char *saveptr
= NULL
;
1539 struct spoolss_StringArray
*deps
;
1540 const char **file_array
= NULL
;
1543 /* fill in the UNISTR fields */
1544 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1545 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1546 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1547 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1548 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1549 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1550 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1552 /* <Comma Separated List of Dependent Files> */
1553 /* save the beginning of the string */
1554 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1557 /* begin to strip out each filename */
1558 str
= strtok_r(str
, ",", &saveptr
);
1560 /* no dependent files, we are done */
1565 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1570 while (str
!= NULL
) {
1571 add_string_to_array(deps
, str
, &file_array
, &count
);
1572 str
= strtok_r(NULL
, ",", &saveptr
);
1575 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1576 if (!deps
->string
) {
1580 for (i
=0; i
< count
; i
++) {
1581 deps
->string
[i
] = file_array
[i
];
1584 r
->dependent_files
= deps
;
1589 /****************************************************************************
1590 ****************************************************************************/
1592 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1593 TALLOC_CTX
*mem_ctx
,
1594 int argc
, const char **argv
)
1599 struct spoolss_AddDriverInfoCtr info_ctr
;
1600 struct spoolss_AddDriverInfo3 info3
;
1604 /* parse the command arguments */
1605 if (argc
!= 3 && argc
!= 4)
1607 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1608 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1609 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1610 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1611 printf ("\t[version]\n");
1616 /* Fill in the spoolss_AddDriverInfo3 struct */
1619 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1621 printf ("Error Unknown architechture [%s]\n", argv
[1]);
1622 return WERR_INVALID_PARAM
;
1625 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1627 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1628 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1630 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1631 return WERR_INVALID_PARAM
;
1634 /* if printer driver version specified, override the default version
1635 * used by the architecture. This allows installation of Windows
1636 * 2000 (version 3) printer drivers. */
1639 info3
.version
= atoi(argv
[3]);
1643 info_ctr
.level
= level
;
1644 info_ctr
.info
.info3
= &info3
;
1646 status
= rpccli_spoolss_AddPrinterDriver(cli
, mem_ctx
,
1647 cli
->srv_name_slash
,
1650 if (!NT_STATUS_IS_OK(status
)) {
1651 return ntstatus_to_werror(status
);
1653 if (W_ERROR_IS_OK(result
)) {
1654 printf ("Printer Driver %s successfully installed.\n",
1662 /****************************************************************************
1663 ****************************************************************************/
1665 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1666 TALLOC_CTX
*mem_ctx
,
1667 int argc
, const char **argv
)
1670 struct spoolss_SetPrinterInfoCtr info_ctr
;
1671 struct spoolss_SetPrinterInfo2 info2
;
1673 /* parse the command arguments */
1676 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1680 /* Fill in the DRIVER_INFO_2 struct */
1683 info2
.printername
= argv
[1];
1684 info2
.drivername
= argv
[3];
1685 info2
.sharename
= argv
[2];
1686 info2
.portname
= argv
[4];
1687 info2
.comment
= "Created by rpcclient";
1688 info2
.printprocessor
= "winprint";
1689 info2
.datatype
= "RAW";
1690 info2
.devmode
= NULL
;
1691 info2
.secdesc
= NULL
;
1692 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1694 info2
.defaultpriority
= 0;
1695 info2
.starttime
= 0;
1696 info2
.untiltime
= 0;
1698 /* These three fields must not be used by AddPrinter()
1699 as defined in the MS Platform SDK documentation..
1703 info2.averageppm = 0;
1707 info_ctr
.info
.info2
= &info2
;
1709 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1711 if (W_ERROR_IS_OK(result
))
1712 printf ("Printer %s successfully installed.\n", argv
[1]);
1717 /****************************************************************************
1718 ****************************************************************************/
1720 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1721 TALLOC_CTX
*mem_ctx
,
1722 int argc
, const char **argv
)
1724 struct policy_handle pol
;
1728 const char *printername
;
1729 union spoolss_PrinterInfo info
;
1730 struct spoolss_SetPrinterInfoCtr info_ctr
;
1731 struct spoolss_DevmodeContainer devmode_ctr
;
1732 struct sec_desc_buf secdesc_ctr
;
1734 ZERO_STRUCT(devmode_ctr
);
1735 ZERO_STRUCT(secdesc_ctr
);
1737 /* parse the command arguments */
1740 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1744 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1746 /* Get a printer handle */
1748 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1752 if (!W_ERROR_IS_OK(result
))
1755 /* Get printer info */
1757 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1762 if (!W_ERROR_IS_OK(result
)) {
1763 printf ("Unable to retrieve printer information!\n");
1767 /* Set the printer driver */
1769 info
.info2
.drivername
= argv
[2];
1770 info
.info2
.devmode
= NULL
;
1771 info
.info2
.secdesc
= NULL
;
1774 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
1776 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
1783 if (!W_ERROR_IS_OK(result
)) {
1784 printf("SetPrinter call failed!\n");
1788 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1793 if (is_valid_policy_hnd(&pol
))
1794 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1800 /****************************************************************************
1801 ****************************************************************************/
1803 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
1804 TALLOC_CTX
*mem_ctx
,
1805 int argc
, const char **argv
)
1807 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
1813 const char *arch
= NULL
;
1814 uint32_t delete_flags
= 0;
1816 /* parse the command arguments */
1817 if (argc
< 2 || argc
> 4) {
1818 printf ("Usage: %s <driver> [arch] [version]\n", argv
[0]);
1825 vers
= atoi (argv
[3]);
1828 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
1831 /* delete the driver for all architectures */
1832 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1834 if (arch
&& !strequal( archi_table
[i
].long_archi
, arch
))
1837 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
1840 /* make the call to remove the driver */
1841 status
= rpccli_spoolss_DeletePrinterDriverEx(cli
, mem_ctx
,
1842 cli
->srv_name_slash
,
1843 archi_table
[i
].long_archi
,
1846 archi_table
[i
].version
,
1849 if ( !W_ERROR_IS_OK(result
) )
1851 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1852 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1853 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
1858 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
1859 archi_table
[i
].long_archi
, archi_table
[i
].version
);
1868 /****************************************************************************
1869 ****************************************************************************/
1871 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
1872 TALLOC_CTX
*mem_ctx
,
1873 int argc
, const char **argv
)
1875 WERROR result
= WERR_OK
;
1879 /* parse the command arguments */
1881 printf ("Usage: %s <driver>\n", argv
[0]);
1885 /* delete the driver for all architectures */
1886 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1887 /* make the call to remove the driver */
1888 status
= rpccli_spoolss_DeletePrinterDriver(cli
, mem_ctx
,
1889 cli
->srv_name_slash
,
1890 archi_table
[i
].long_archi
,
1893 if (!NT_STATUS_IS_OK(status
)) {
1896 if ( !W_ERROR_IS_OK(result
) ) {
1897 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1898 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1899 argv
[1], archi_table
[i
].long_archi
,
1903 printf ("Driver %s removed for arch [%s].\n", argv
[1],
1904 archi_table
[i
].long_archi
);
1911 /****************************************************************************
1912 ****************************************************************************/
1914 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
1915 TALLOC_CTX
*mem_ctx
,
1916 int argc
, const char **argv
)
1920 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
1923 union spoolss_PrintProcessorDirectoryInfo info
;
1926 /* parse the command arguments */
1928 printf ("Usage: %s [environment]\n", argv
[0]);
1933 environment
= argv
[1];
1936 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1937 cli
->srv_name_slash
,
1945 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1947 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1949 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1950 cli
->srv_name_slash
,
1960 if (W_ERROR_IS_OK(result
)) {
1961 printf("%s\n", info
.info1
.directory_name
);
1967 /****************************************************************************
1968 ****************************************************************************/
1970 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
1971 int argc
, const char **argv
)
1973 struct policy_handle handle
;
1976 const char *printername
;
1977 union spoolss_AddFormInfo info
;
1978 struct spoolss_AddFormInfo1 info1
;
1979 struct spoolss_AddFormInfo2 info2
;
1982 /* Parse the command arguments */
1984 if (argc
< 3 || argc
> 5) {
1985 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
1989 /* Get a printer handle */
1991 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1993 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1997 if (!W_ERROR_IS_OK(werror
))
2000 /* Dummy up some values for the form data */
2003 level
= atoi(argv
[3]);
2008 info1
.flags
= SPOOLSS_FORM_USER
;
2009 info1
.form_name
= argv
[2];
2010 info1
.size
.width
= 100;
2011 info1
.size
.height
= 100;
2012 info1
.area
.left
= 0;
2013 info1
.area
.top
= 10;
2014 info1
.area
.right
= 20;
2015 info1
.area
.bottom
= 30;
2017 info
.info1
= &info1
;
2021 info2
.flags
= SPOOLSS_FORM_USER
;
2022 info2
.form_name
= argv
[2];
2023 info2
.size
.width
= 100;
2024 info2
.size
.height
= 100;
2025 info2
.area
.left
= 0;
2026 info2
.area
.top
= 10;
2027 info2
.area
.right
= 20;
2028 info2
.area
.bottom
= 30;
2029 info2
.keyword
= argv
[2];
2030 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2031 info2
.mui_dll
= NULL
;
2032 info2
.ressource_id
= 0;
2033 info2
.display_name
= argv
[2];
2036 info
.info2
= &info2
;
2044 status
= rpccli_spoolss_AddForm(cli
, mem_ctx
,
2051 if (is_valid_policy_hnd(&handle
))
2052 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2057 /****************************************************************************
2058 ****************************************************************************/
2060 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2061 int argc
, const char **argv
)
2063 struct policy_handle handle
;
2066 const char *printername
;
2067 union spoolss_AddFormInfo info
;
2068 struct spoolss_AddFormInfo1 info1
;
2070 /* Parse the command arguments */
2073 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2077 /* Get a printer handle */
2079 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2081 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2083 SEC_FLAG_MAXIMUM_ALLOWED
,
2085 if (!W_ERROR_IS_OK(werror
))
2088 /* Dummy up some values for the form data */
2090 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2091 info1
.size
.width
= 100;
2092 info1
.size
.height
= 100;
2093 info1
.area
.left
= 0;
2094 info1
.area
.top
= 1000;
2095 info1
.area
.right
= 2000;
2096 info1
.area
.bottom
= 3000;
2097 info1
.form_name
= argv
[2];
2099 info
.info1
= &info1
;
2103 status
= rpccli_spoolss_SetForm(cli
, mem_ctx
,
2111 if (is_valid_policy_hnd(&handle
))
2112 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2117 /****************************************************************************
2118 ****************************************************************************/
2120 static const char *get_form_flag(int form_flag
)
2122 switch (form_flag
) {
2123 case SPOOLSS_FORM_USER
:
2125 case SPOOLSS_FORM_BUILTIN
:
2126 return "FORM_BUILTIN";
2127 case SPOOLSS_FORM_PRINTER
:
2128 return "FORM_PRINTER";
2134 /****************************************************************************
2135 ****************************************************************************/
2137 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2140 "\tflag: %s (%d)\n" \
2141 "\twidth: %d, length: %d\n" \
2142 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2143 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2144 r
->size
.width
, r
->size
.height
,
2145 r
->area
.left
, r
->area
.right
,
2146 r
->area
.top
, r
->area
.bottom
);
2149 /****************************************************************************
2150 ****************************************************************************/
2152 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2155 "\tflag: %s (%d)\n" \
2156 "\twidth: %d, length: %d\n" \
2157 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2158 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2159 r
->size
.width
, r
->size
.height
,
2160 r
->area
.left
, r
->area
.right
,
2161 r
->area
.top
, r
->area
.bottom
);
2162 printf("\tkeyword: %s\n", r
->keyword
);
2163 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2164 printf("\tmui_dll: %s\n", r
->mui_dll
);
2165 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2166 printf("\tdisplay_name: %s\n", r
->display_name
);
2167 printf("\tlang_id: %d\n", r
->lang_id
);
2171 /****************************************************************************
2172 ****************************************************************************/
2174 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2175 int argc
, const char **argv
)
2177 struct policy_handle handle
;
2180 const char *printername
;
2182 uint32_t offered
= 0;
2183 union spoolss_FormInfo info
;
2187 /* Parse the command arguments */
2189 if (argc
< 3 || argc
> 5) {
2190 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2194 /* Get a printer handle */
2196 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2198 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2200 SEC_FLAG_MAXIMUM_ALLOWED
,
2202 if (!W_ERROR_IS_OK(werror
))
2206 level
= atoi(argv
[3]);
2211 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2220 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2221 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2223 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2234 if (!NT_STATUS_IS_OK(status
)) {
2240 display_form_info1(&info
.info1
);
2243 display_form_info2(&info
.info2
);
2248 if (is_valid_policy_hnd(&handle
))
2249 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2254 /****************************************************************************
2255 ****************************************************************************/
2257 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2258 TALLOC_CTX
*mem_ctx
, int argc
,
2261 struct policy_handle handle
;
2264 const char *printername
;
2266 /* Parse the command arguments */
2269 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2273 /* Get a printer handle */
2275 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2277 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2279 SEC_FLAG_MAXIMUM_ALLOWED
,
2281 if (!W_ERROR_IS_OK(werror
))
2284 /* Delete the form */
2286 status
= rpccli_spoolss_DeleteForm(cli
, mem_ctx
,
2290 if (!NT_STATUS_IS_OK(status
)) {
2291 return ntstatus_to_werror(status
);
2295 if (is_valid_policy_hnd(&handle
))
2296 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2301 /****************************************************************************
2302 ****************************************************************************/
2304 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2305 TALLOC_CTX
*mem_ctx
, int argc
,
2308 struct policy_handle handle
;
2310 const char *printername
;
2311 uint32_t num_forms
, level
= 1, i
;
2312 union spoolss_FormInfo
*forms
;
2314 /* Parse the command arguments */
2316 if (argc
< 2 || argc
> 4) {
2317 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2321 /* Get a printer handle */
2323 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2325 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2327 SEC_FLAG_MAXIMUM_ALLOWED
,
2329 if (!W_ERROR_IS_OK(werror
))
2333 level
= atoi(argv
[2]);
2336 /* Enumerate forms */
2338 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2345 if (!W_ERROR_IS_OK(werror
))
2348 /* Display output */
2350 for (i
= 0; i
< num_forms
; i
++) {
2353 display_form_info1(&forms
[i
].info1
);
2356 display_form_info2(&forms
[i
].info2
);
2362 if (is_valid_policy_hnd(&handle
))
2363 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2368 /****************************************************************************
2369 ****************************************************************************/
2371 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2372 TALLOC_CTX
*mem_ctx
,
2373 int argc
, const char **argv
)
2377 const char *printername
;
2378 struct policy_handle pol
;
2379 union spoolss_PrinterInfo info
;
2380 enum winreg_Type type
;
2381 union spoolss_PrinterData data
;
2383 /* parse the command arguments */
2385 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2386 " <value> <data>\n",
2388 result
= WERR_INVALID_PARAM
;
2392 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2396 if (strequal(argv
[2], "string")) {
2400 if (strequal(argv
[2], "binary")) {
2404 if (strequal(argv
[2], "dword")) {
2408 if (strequal(argv
[2], "multistring")) {
2409 type
= REG_MULTI_SZ
;
2412 if (type
== REG_NONE
) {
2413 printf("Unknown data type: %s\n", argv
[2]);
2414 result
= WERR_INVALID_PARAM
;
2418 /* get a printer handle */
2420 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2422 SEC_FLAG_MAXIMUM_ALLOWED
,
2424 if (!W_ERROR_IS_OK(result
)) {
2428 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2433 if (!W_ERROR_IS_OK(result
)) {
2437 printf("%s\n", current_timestring(mem_ctx
, true));
2438 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2440 /* Set the printer data */
2444 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2445 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2448 data
.value
= strtoul(argv
[4], NULL
, 10);
2451 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2453 case REG_MULTI_SZ
: {
2455 const char **strings
= NULL
;
2457 for (i
=4; i
<argc
; i
++) {
2458 if (strcmp(argv
[i
], "NULL") == 0) {
2461 if (!add_string_to_array(mem_ctx
, argv
[i
],
2464 result
= WERR_NOMEM
;
2468 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2469 if (!data
.string_array
) {
2470 result
= WERR_NOMEM
;
2473 for (i
=0; i
< num_strings
; i
++) {
2474 data
.string_array
[i
] = strings
[i
];
2479 printf("Unknown data type: %s\n", argv
[2]);
2480 result
= WERR_INVALID_PARAM
;
2484 status
= rpccli_spoolss_SetPrinterData(cli
, mem_ctx
,
2486 argv
[3], /* value_name */
2489 0, /* autocalculated size */
2491 if (!W_ERROR_IS_OK(result
)) {
2492 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2495 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2497 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2502 if (!W_ERROR_IS_OK(result
)) {
2506 printf("%s\n", current_timestring(mem_ctx
, true));
2507 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2511 if (is_valid_policy_hnd(&pol
)) {
2512 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
2518 /****************************************************************************
2519 ****************************************************************************/
2521 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2523 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2524 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2528 /****************************************************************************
2529 ****************************************************************************/
2531 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2533 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2534 r
->position
, r
->job_id
,
2535 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2536 r
->total_pages
, r
->size
);
2539 /****************************************************************************
2540 ****************************************************************************/
2542 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2544 printf("jobid[%d], next_jobid[%d]\n",
2545 r
->job_id
, r
->next_job_id
);
2548 /****************************************************************************
2549 ****************************************************************************/
2551 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2553 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2554 r
->position
, r
->job_id
,
2555 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2556 r
->total_pages
, r
->size
, r
->size_high
);
2559 /****************************************************************************
2560 ****************************************************************************/
2562 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2563 TALLOC_CTX
*mem_ctx
, int argc
,
2567 uint32_t level
= 1, count
, i
;
2568 const char *printername
;
2569 struct policy_handle hnd
;
2570 union spoolss_JobInfo
*info
;
2572 if (argc
< 2 || argc
> 3) {
2573 printf("Usage: %s printername [level]\n", argv
[0]);
2578 level
= atoi(argv
[2]);
2581 /* Open printer handle */
2583 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2585 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2587 SEC_FLAG_MAXIMUM_ALLOWED
,
2589 if (!W_ERROR_IS_OK(result
))
2592 /* Enumerate ports */
2594 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2602 if (!W_ERROR_IS_OK(result
)) {
2606 for (i
= 0; i
< count
; i
++) {
2609 display_job_info1(&info
[i
].info1
);
2612 display_job_info2(&info
[i
].info2
);
2615 d_printf("unknown info level %d\n", level
);
2621 if (is_valid_policy_hnd(&hnd
)) {
2622 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2628 /****************************************************************************
2629 ****************************************************************************/
2631 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2632 TALLOC_CTX
*mem_ctx
, int argc
,
2636 const char *printername
;
2637 struct policy_handle hnd
;
2640 union spoolss_JobInfo info
;
2642 if (argc
< 3 || argc
> 4) {
2643 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2647 job_id
= atoi(argv
[2]);
2650 level
= atoi(argv
[3]);
2653 /* Open printer handle */
2655 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2657 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2659 SEC_FLAG_MAXIMUM_ALLOWED
,
2661 if (!W_ERROR_IS_OK(result
)) {
2665 /* Enumerate ports */
2667 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2674 if (!W_ERROR_IS_OK(result
)) {
2680 display_job_info1(&info
.info1
);
2683 display_job_info2(&info
.info2
);
2686 display_job_info3(&info
.info3
);
2689 display_job_info4(&info
.info4
);
2692 d_printf("unknown info level %d\n", level
);
2697 if (is_valid_policy_hnd(&hnd
)) {
2698 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2704 /****************************************************************************
2705 ****************************************************************************/
2707 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
2708 TALLOC_CTX
*mem_ctx
, int argc
,
2713 const char *printername
;
2714 struct policy_handle hnd
;
2716 enum spoolss_JobControl command
;
2719 printf("Usage: %s printername job_id command\n", argv
[0]);
2723 job_id
= atoi(argv
[2]);
2724 command
= atoi(argv
[3]);
2726 /* Open printer handle */
2728 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2730 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2732 SEC_FLAG_MAXIMUM_ALLOWED
,
2734 if (!W_ERROR_IS_OK(result
)) {
2740 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
2747 if (!W_ERROR_IS_OK(result
)) {
2752 if (is_valid_policy_hnd(&hnd
)) {
2753 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2759 /****************************************************************************
2760 ****************************************************************************/
2762 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
2763 TALLOC_CTX
*mem_ctx
, int argc
,
2769 const char *printername
;
2770 struct policy_handle hnd
;
2771 uint32_t value_offered
= 0;
2772 const char *value_name
= NULL
;
2773 uint32_t value_needed
;
2774 enum winreg_Type type
;
2775 uint8_t *data
= NULL
;
2776 uint32_t data_offered
= 0;
2777 uint32_t data_needed
;
2780 printf("Usage: %s printername\n", argv
[0]);
2784 /* Open printer handle */
2786 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2788 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2790 SEC_FLAG_MAXIMUM_ALLOWED
,
2792 if (!W_ERROR_IS_OK(result
)) {
2796 /* Enumerate data */
2798 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2810 data_offered
= data_needed
;
2811 value_offered
= value_needed
;
2812 data
= talloc_zero_array(mem_ctx
, uint8_t, data_needed
);
2813 value_name
= talloc_zero_array(mem_ctx
, char, value_needed
);
2815 while (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2817 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2828 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2829 struct regval_blob v
;
2830 fstrcpy(v
.valuename
, value_name
);
2832 v
.size
= data_offered
;
2834 display_reg_value(v
);
2838 if (W_ERROR_V(result
) == ERRnomoreitems
) {
2839 result
= W_ERROR(ERRsuccess
);
2843 if (is_valid_policy_hnd(&hnd
)) {
2844 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2850 /****************************************************************************
2851 ****************************************************************************/
2853 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
2854 TALLOC_CTX
*mem_ctx
, int argc
,
2859 const char *printername
;
2860 struct policy_handle hnd
;
2862 struct spoolss_PrinterEnumValues
*info
;
2865 printf("Usage: %s printername <keyname>\n", argv
[0]);
2869 /* Open printer handle */
2871 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2873 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2875 SEC_FLAG_MAXIMUM_ALLOWED
,
2877 if (!W_ERROR_IS_OK(result
)) {
2881 /* Enumerate subkeys */
2883 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
2889 if (!W_ERROR_IS_OK(result
)) {
2893 for (i
=0; i
< count
; i
++) {
2894 display_printer_data(info
[i
].value_name
,
2900 if (is_valid_policy_hnd(&hnd
)) {
2901 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2907 /****************************************************************************
2908 ****************************************************************************/
2910 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
2911 TALLOC_CTX
*mem_ctx
, int argc
,
2915 const char *printername
;
2916 const char *keyname
= NULL
;
2917 struct policy_handle hnd
;
2918 const char **key_buffer
= NULL
;
2921 if (argc
< 2 || argc
> 3) {
2922 printf("Usage: %s printername [keyname]\n", argv
[0]);
2932 /* Open printer handle */
2934 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2936 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2938 SEC_FLAG_MAXIMUM_ALLOWED
,
2940 if (!W_ERROR_IS_OK(result
)) {
2944 /* Enumerate subkeys */
2946 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
2952 if (!W_ERROR_IS_OK(result
)) {
2956 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
2957 printf("%s\n", key_buffer
[i
]);
2962 if (is_valid_policy_hnd(&hnd
)) {
2963 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2969 /****************************************************************************
2970 ****************************************************************************/
2972 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
2973 TALLOC_CTX
*mem_ctx
, int argc
,
2976 const char *printername
;
2977 const char *clientname
;
2978 struct policy_handle hnd
;
2981 struct spoolss_NotifyOption option
;
2984 printf("Usage: %s printername\n", argv
[0]);
2991 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2993 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2995 SEC_FLAG_MAXIMUM_ALLOWED
,
2997 if (!W_ERROR_IS_OK(result
)) {
2998 printf("Error opening %s\n", argv
[1]);
3002 /* Create spool options */
3007 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3008 if (option
.types
== NULL
) {
3009 result
= WERR_NOMEM
;
3013 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3014 option
.types
[0].count
= 1;
3015 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3016 if (option
.types
[0].fields
== NULL
) {
3017 result
= WERR_NOMEM
;
3020 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3022 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3023 option
.types
[1].count
= 1;
3024 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3025 if (option
.types
[1].fields
== NULL
) {
3026 result
= WERR_NOMEM
;
3029 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3031 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
3033 result
= WERR_NOMEM
;
3039 status
= rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli
, mem_ctx
,
3047 if (!W_ERROR_IS_OK(result
)) {
3048 printf("Error rffpcnex %s\n", argv
[1]);
3053 if (is_valid_policy_hnd(&hnd
))
3054 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3059 /****************************************************************************
3060 ****************************************************************************/
3062 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3063 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3065 union spoolss_PrinterInfo info1
, info2
;
3067 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3069 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3070 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3075 if ( !W_ERROR_IS_OK(werror
) ) {
3076 printf("failed (%s)\n", win_errstr(werror
));
3077 talloc_destroy(mem_ctx
);
3082 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3083 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3088 if ( !W_ERROR_IS_OK(werror
) ) {
3089 printf("failed (%s)\n", win_errstr(werror
));
3090 talloc_destroy(mem_ctx
);
3095 talloc_destroy(mem_ctx
);
3100 /****************************************************************************
3101 ****************************************************************************/
3103 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3104 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3106 union spoolss_PrinterInfo info1
, info2
;
3108 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3109 SEC_DESC
*sd1
, *sd2
;
3113 printf("Retrieving printer security for %s...", cli1
->desthost
);
3114 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3119 if ( !W_ERROR_IS_OK(werror
) ) {
3120 printf("failed (%s)\n", win_errstr(werror
));
3126 printf("Retrieving printer security for %s...", cli2
->desthost
);
3127 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3132 if ( !W_ERROR_IS_OK(werror
) ) {
3133 printf("failed (%s)\n", win_errstr(werror
));
3142 sd1
= info1
.info3
.secdesc
;
3143 sd2
= info2
.info3
.secdesc
;
3145 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3146 printf("NULL secdesc!\n");
3151 if (!security_descriptor_equal( sd1
, sd2
) ) {
3152 printf("Security Descriptors *not* equal!\n");
3157 printf("Security descriptors match\n");
3160 talloc_destroy(mem_ctx
);
3165 /****************************************************************************
3166 ****************************************************************************/
3168 extern struct user_auth_info
*rpcclient_auth_info
;
3170 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3171 TALLOC_CTX
*mem_ctx
, int argc
,
3174 const char *printername
;
3175 char *printername_path
= NULL
;
3176 struct cli_state
*cli_server2
= NULL
;
3177 struct rpc_pipe_client
*cli2
= NULL
;
3178 struct policy_handle hPrinter1
, hPrinter2
;
3183 printf("Usage: %s <printer> <server>\n", argv
[0]);
3187 printername
= argv
[1];
3189 /* first get the connection to the remote server */
3191 nt_status
= cli_full_connection(&cli_server2
, global_myname(), argv
[2],
3194 get_cmdline_auth_info_username(rpcclient_auth_info
),
3196 get_cmdline_auth_info_password(rpcclient_auth_info
),
3197 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info
) ? CLI_FULL_CONNECTION_USE_KERBEROS
: 0,
3198 get_cmdline_auth_info_signing_state(rpcclient_auth_info
), NULL
);
3200 if ( !NT_STATUS_IS_OK(nt_status
) )
3201 return WERR_GENERAL_FAILURE
;
3203 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
.syntax_id
,
3205 if (!NT_STATUS_IS_OK(nt_status
)) {
3206 printf("failed to open spoolss pipe on server %s (%s)\n",
3207 argv
[2], nt_errstr(nt_status
));
3208 return WERR_GENERAL_FAILURE
;
3211 /* now open up both printers */
3213 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3215 printf("Opening %s...", printername_path
);
3217 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3221 if ( !W_ERROR_IS_OK(werror
) ) {
3222 printf("failed (%s)\n", win_errstr(werror
));
3227 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3229 printf("Opening %s...", printername_path
);
3230 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3234 if ( !W_ERROR_IS_OK(werror
) ) {
3235 printf("failed (%s)\n", win_errstr(werror
));
3240 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3241 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3243 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3250 printf("Closing printers...");
3251 rpccli_spoolss_ClosePrinter( cli
, mem_ctx
, &hPrinter1
, NULL
);
3252 rpccli_spoolss_ClosePrinter( cli2
, mem_ctx
, &hPrinter2
, NULL
);
3255 /* close the second remote connection */
3257 cli_shutdown( cli_server2
);
3261 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3263 printf("print_processor_name: %s\n", r
->print_processor_name
);
3266 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3267 TALLOC_CTX
*mem_ctx
, int argc
,
3271 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3272 uint32_t num_procs
, level
= 1, i
;
3273 union spoolss_PrintProcessorInfo
*procs
;
3275 /* Parse the command arguments */
3277 if (argc
< 1 || argc
> 4) {
3278 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3283 environment
= argv
[1];
3287 level
= atoi(argv
[2]);
3290 /* Enumerate Print Processors */
3292 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3293 cli
->srv_name_slash
,
3299 if (!W_ERROR_IS_OK(werror
))
3302 /* Display output */
3304 for (i
= 0; i
< num_procs
; i
++) {
3307 display_proc_info1(&procs
[i
].info1
);
3316 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3318 printf("name_array: %s\n", r
->name_array
);
3321 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3322 TALLOC_CTX
*mem_ctx
, int argc
,
3326 const char *print_processor_name
= "winprint";
3327 uint32_t num_procs
, level
= 1, i
;
3328 union spoolss_PrintProcDataTypesInfo
*procs
;
3330 /* Parse the command arguments */
3332 if (argc
< 1 || argc
> 4) {
3333 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3338 print_processor_name
= argv
[1];
3342 level
= atoi(argv
[2]);
3345 /* Enumerate Print Processor Data Types */
3347 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3348 cli
->srv_name_slash
,
3349 print_processor_name
,
3354 if (!W_ERROR_IS_OK(werror
))
3357 /* Display output */
3359 for (i
= 0; i
< num_procs
; i
++) {
3362 display_proc_data_types_info1(&procs
[i
].info1
);
3371 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3373 printf("monitor_name: %s\n", r
->monitor_name
);
3376 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3378 printf("monitor_name: %s\n", r
->monitor_name
);
3379 printf("environment: %s\n", r
->environment
);
3380 printf("dll_name: %s\n", r
->dll_name
);
3383 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3384 TALLOC_CTX
*mem_ctx
, int argc
,
3388 uint32_t count
, level
= 1, i
;
3389 union spoolss_MonitorInfo
*info
;
3391 /* Parse the command arguments */
3394 printf("Usage: %s [level]\n", argv
[0]);
3399 level
= atoi(argv
[1]);
3402 /* Enumerate Print Monitors */
3404 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3405 cli
->srv_name_slash
,
3410 if (!W_ERROR_IS_OK(werror
)) {
3414 /* Display output */
3416 for (i
= 0; i
< count
; i
++) {
3419 display_monitor1(&info
[i
].info1
);
3422 display_monitor2(&info
[i
].info2
);
3431 static WERROR
cmd_spoolss_create_printer_ic(struct rpc_pipe_client
*cli
,
3432 TALLOC_CTX
*mem_ctx
, int argc
,
3437 struct policy_handle handle
, gdi_handle
;
3438 const char *printername
;
3439 struct spoolss_DevmodeContainer devmode_ctr
;
3441 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3443 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3445 SEC_FLAG_MAXIMUM_ALLOWED
,
3447 if (!W_ERROR_IS_OK(result
)) {
3451 ZERO_STRUCT(devmode_ctr
);
3453 status
= rpccli_spoolss_CreatePrinterIC(cli
, mem_ctx
,
3458 if (!W_ERROR_IS_OK(result
)) {
3463 if (is_valid_policy_hnd(&gdi_handle
)) {
3464 rpccli_spoolss_DeletePrinterIC(cli
, mem_ctx
, &gdi_handle
, NULL
);
3466 if (is_valid_policy_hnd(&handle
)) {
3467 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3473 /* List of commands exported by this module */
3474 struct cmd_set spoolss_commands
[] = {
3478 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a print driver", "" },
3479 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a printer", "" },
3480 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver", "" },
3481 { "deldriverex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriverex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver with files", "" },
3482 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data", "" },
3483 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data for a key", "" },
3484 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer keys", "" },
3485 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate print jobs", "" },
3486 { "getjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_get_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print job", "" },
3487 { "setjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_set_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set print job", "" },
3488 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer ports", "" },
3489 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate installed printer drivers", "" },
3490 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printers", "" },
3491 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver data", "" },
3492 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer driver data with keyname", ""},
3493 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver information", "" },
3494 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver upload directory", "" },
3495 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer info", "" },
3496 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Open printer handle", "" },
3497 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer driver", "" },
3498 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print processor directory", "" },
3499 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add form", "" },
3500 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set form", "" },
3501 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get form", "" },
3502 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete form", "" },
3503 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate forms", "" },
3504 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer comment", "" },
3505 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printername", "" },
3506 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set REG_SZ printer data", "" },
3507 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Rffpcnex test", "" },
3508 { "printercmp", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_printercmp
, &ndr_table_spoolss
.syntax_id
, NULL
, "Printer comparison test", "" },
3509 { "enumprocs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_procs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processors", "" },
3510 { "enumprocdatatypes", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_proc_data_types
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processor Data Types", "" },
3511 { "enummonitors", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_monitors
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Monitors", "" },
3512 { "createprinteric", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_create_printer_ic
, &ndr_table_spoolss
.syntax_id
, NULL
, "Create Printer IC", "" },