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 struct spoolss_SetPrinterInfo2 info2
;
466 const char *printername
, *comment
= NULL
;
467 struct spoolss_DevmodeContainer devmode_ctr
;
468 struct sec_desc_buf secdesc_ctr
;
470 if (argc
== 1 || argc
> 3) {
471 printf("Usage: %s printername comment\n", argv
[0]);
476 /* Open a printer handle */
481 ZERO_STRUCT(devmode_ctr
);
482 ZERO_STRUCT(secdesc_ctr
);
484 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
486 /* get a printer handle */
487 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
491 if (!W_ERROR_IS_OK(result
))
494 /* Get printer info */
495 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
500 if (!W_ERROR_IS_OK(result
))
504 /* Modify the comment. */
505 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
506 info2
.comment
= comment
;
509 info_ctr
.info
.info2
= &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_SetPrinterInfo2 info2
;
544 struct spoolss_DevmodeContainer devmode_ctr
;
545 struct sec_desc_buf secdesc_ctr
;
547 ZERO_STRUCT(devmode_ctr
);
548 ZERO_STRUCT(secdesc_ctr
);
550 if (argc
== 1 || argc
> 3) {
551 printf("Usage: %s printername new_printername\n", argv
[0]);
556 /* Open a printer handle */
558 new_printername
= argv
[2];
561 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
563 /* get a printer handle */
564 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
568 if (!W_ERROR_IS_OK(result
))
571 /* Get printer info */
572 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
577 if (!W_ERROR_IS_OK(result
))
580 /* Modify the printername. */
581 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
582 info2
.printername
= new_printername
;
585 info_ctr
.info
.info2
= &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
,
756 union spoolss_PrinterData r
;
757 DATA_BLOB blob
= data_blob_const(data
, length
);
760 result
= pull_spoolss_PrinterData(talloc_tos(), &blob
, &r
, type
);
761 if (!W_ERROR_IS_OK(result
)) {
767 printf("%s: REG_DWORD: 0x%08x\n", v
, r
.value
);
770 printf("%s: REG_SZ: %s\n", v
, r
.string
);
773 char *hex
= hex_encode_talloc(NULL
,
774 r
.binary
.data
, r
.binary
.length
);
776 printf("%s: REG_BINARY:", v
);
778 for (i
=0; i
<len
; i
++) {
779 if (hex
[i
] == '\0') {
792 printf("%s: REG_MULTI_SZ: ", v
);
793 for (i
=0; r
.string_array
[i
] != NULL
; i
++) {
794 printf("%s ", r
.string_array
[i
]);
799 printf("%s: unknown type 0x%02x:\n", v
, type
);
804 /****************************************************************************
805 ****************************************************************************/
807 static WERROR
cmd_spoolss_getprinterdata(struct rpc_pipe_client
*cli
,
809 int argc
, const char **argv
)
811 struct policy_handle pol
;
814 const char *valuename
;
815 enum winreg_Type type
;
820 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
821 printf("<printername> of . queries print server\n");
826 /* Open a printer handle */
828 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
829 fstrcpy(printername
, cli
->srv_name_slash
);
831 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
832 cli
->srv_name_slash
, argv
[1]);
834 /* get a printer handle */
836 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
838 SEC_FLAG_MAXIMUM_ALLOWED
,
840 if (!W_ERROR_IS_OK(result
))
843 /* Get printer info */
845 result
= rpccli_spoolss_getprinterdata(cli
, mem_ctx
,
852 if (!W_ERROR_IS_OK(result
))
855 /* Display printer data */
857 display_printer_data(valuename
, type
, data
, needed
);
860 if (is_valid_policy_hnd(&pol
))
861 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
866 /****************************************************************************
867 ****************************************************************************/
869 static WERROR
cmd_spoolss_getprinterdataex(struct rpc_pipe_client
*cli
,
871 int argc
, const char **argv
)
873 struct policy_handle pol
;
877 const char *valuename
, *keyname
;
879 enum winreg_Type type
;
880 uint8_t *data
= NULL
;
881 uint32_t offered
= 0;
885 printf("Usage: %s <printername> <keyname> <valuename>\n",
887 printf("<printername> of . queries print server\n");
893 /* Open a printer handle */
895 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
896 fstrcpy(printername
, cli
->srv_name_slash
);
898 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
899 cli
->srv_name_slash
, argv
[1]);
901 /* get a printer handle */
903 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
905 SEC_FLAG_MAXIMUM_ALLOWED
,
907 if (!W_ERROR_IS_OK(result
))
910 /* Get printer info */
912 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
917 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
926 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
928 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
932 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
943 if (!NT_STATUS_IS_OK(status
)) {
947 if (!W_ERROR_IS_OK(result
))
950 /* Display printer data */
952 display_printer_data(valuename
, type
, data
, needed
);
956 if (is_valid_policy_hnd(&pol
))
957 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
962 /****************************************************************************
963 ****************************************************************************/
965 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
971 printf("Printer Driver Info 1:\n");
972 printf("\tDriver Name: [%s]\n", r
->driver_name
);
976 /****************************************************************************
977 ****************************************************************************/
979 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
985 printf("Printer Driver Info 2:\n");
986 printf("\tVersion: [%x]\n", r
->version
);
987 printf("\tDriver Name: [%s]\n", r
->driver_name
);
988 printf("\tArchitecture: [%s]\n", r
->architecture
);
989 printf("\tDriver Path: [%s]\n", r
->driver_path
);
990 printf("\tDatafile: [%s]\n", r
->data_file
);
991 printf("\tConfigfile: [%s]\n", r
->config_file
);
995 /****************************************************************************
996 ****************************************************************************/
998 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
1006 printf("Printer Driver Info 3:\n");
1007 printf("\tVersion: [%x]\n", r
->version
);
1008 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1009 printf("\tArchitecture: [%s]\n", r
->architecture
);
1010 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1011 printf("\tDatafile: [%s]\n", r
->data_file
);
1012 printf("\tConfigfile: [%s]\n", r
->config_file
);
1013 printf("\tHelpfile: [%s]\n", r
->help_file
);
1015 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1016 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1019 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1020 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1024 /****************************************************************************
1025 ****************************************************************************/
1027 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1035 printf("Printer Driver Info 4:\n");
1036 printf("\tVersion: [%x]\n", r
->version
);
1037 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1038 printf("\tArchitecture: [%s]\n", r
->architecture
);
1039 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1040 printf("\tDatafile: [%s]\n", r
->data_file
);
1041 printf("\tConfigfile: [%s]\n", r
->config_file
);
1042 printf("\tHelpfile: [%s]\n", r
->help_file
);
1044 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1045 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1048 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1049 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1051 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1052 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1057 /****************************************************************************
1058 ****************************************************************************/
1060 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1066 printf("Printer Driver Info 5:\n");
1067 printf("\tVersion: [%x]\n", r
->version
);
1068 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1069 printf("\tArchitecture: [%s]\n", r
->architecture
);
1070 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1071 printf("\tDatafile: [%s]\n", r
->data_file
);
1072 printf("\tConfigfile: [%s]\n", r
->config_file
);
1073 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1074 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1075 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1079 /****************************************************************************
1080 ****************************************************************************/
1082 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1090 printf("Printer Driver Info 6:\n");
1091 printf("\tVersion: [%x]\n", r
->version
);
1092 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1093 printf("\tArchitecture: [%s]\n", r
->architecture
);
1094 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1095 printf("\tDatafile: [%s]\n", r
->data_file
);
1096 printf("\tConfigfile: [%s]\n", r
->config_file
);
1097 printf("\tHelpfile: [%s]\n", r
->help_file
);
1099 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1100 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1103 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1104 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1106 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1107 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1110 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1111 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1112 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1113 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1114 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1115 printf("\tProvider: [%s]\n", r
->provider
);
1120 /****************************************************************************
1121 ****************************************************************************/
1123 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1131 printf("Printer Driver Info 8:\n");
1132 printf("\tVersion: [%x]\n", r
->version
);
1133 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1134 printf("\tArchitecture: [%s]\n", r
->architecture
);
1135 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1136 printf("\tDatafile: [%s]\n", r
->data_file
);
1137 printf("\tConfigfile: [%s]\n", r
->config_file
);
1138 printf("\tHelpfile: [%s]\n", r
->help_file
);
1139 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1140 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1142 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1143 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1146 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1147 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1150 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1151 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1152 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1153 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1154 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1155 printf("\tProvider: [%s]\n", r
->provider
);
1156 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1157 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1158 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1159 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1161 printf("\tInf Path: [%s]\n", r
->inf_path
);
1162 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1163 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1164 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1166 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1167 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1168 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1173 /****************************************************************************
1174 ****************************************************************************/
1176 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1177 TALLOC_CTX
*mem_ctx
,
1178 int argc
, const char **argv
)
1180 struct policy_handle pol
;
1183 const char *printername
;
1185 bool success
= false;
1186 union spoolss_DriverInfo info
;
1187 uint32_t server_major_version
;
1188 uint32_t server_minor_version
;
1190 if ((argc
== 1) || (argc
> 3)) {
1191 printf("Usage: %s <printername> [level]\n", argv
[0]);
1195 /* get the arguments need to open the printer handle */
1197 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1200 level
= atoi(argv
[2]);
1203 /* Open a printer handle */
1205 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1209 if (!W_ERROR_IS_OK(werror
)) {
1210 printf("Error opening printer handle for %s!\n", printername
);
1214 /* loop through and print driver info level for each architecture */
1216 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1218 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1220 archi_table
[i
].long_archi
,
1223 archi_table
[i
].version
,
1226 &server_major_version
,
1227 &server_minor_version
);
1228 if (!W_ERROR_IS_OK(werror
)) {
1232 /* need at least one success */
1236 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1240 display_print_driver1(&info
.info1
);
1243 display_print_driver2(&info
.info2
);
1246 display_print_driver3(&info
.info3
);
1249 display_print_driver4(&info
.info4
);
1252 display_print_driver5(&info
.info5
);
1255 display_print_driver6(&info
.info6
);
1258 display_print_driver8(&info
.info8
);
1261 printf("unknown info level %d\n", level
);
1268 if (is_valid_policy_hnd(&pol
)) {
1269 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1279 /****************************************************************************
1280 ****************************************************************************/
1282 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1283 TALLOC_CTX
*mem_ctx
,
1284 const char *architecture
,
1289 union spoolss_DriverInfo
*info
= NULL
;
1292 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1293 cli
->srv_name_slash
,
1300 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1301 printf("Server does not support environment [%s]\n",
1310 if (!W_ERROR_IS_OK(werror
)) {
1311 printf("Error getting driver for environment [%s] - %s\n",
1312 architecture
, win_errstr(werror
));
1316 printf("\n[%s]\n", architecture
);
1320 for (j
=0; j
< count
; j
++) {
1321 display_print_driver1(&info
[j
].info1
);
1325 for (j
=0; j
< count
; j
++) {
1326 display_print_driver2(&info
[j
].info2
);
1330 for (j
=0; j
< count
; j
++) {
1331 display_print_driver3(&info
[j
].info3
);
1335 for (j
=0; j
< count
; j
++) {
1336 display_print_driver4(&info
[j
].info4
);
1340 for (j
=0; j
< count
; j
++) {
1341 display_print_driver5(&info
[j
].info5
);
1345 for (j
=0; j
< count
; j
++) {
1346 display_print_driver6(&info
[j
].info6
);
1350 for (j
=0; j
< count
; j
++) {
1351 display_print_driver8(&info
[j
].info8
);
1355 printf("unknown info level %d\n", level
);
1356 return WERR_UNKNOWN_LEVEL
;
1362 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1363 TALLOC_CTX
*mem_ctx
,
1364 int argc
, const char **argv
)
1366 WERROR werror
= WERR_OK
;
1369 const char *architecture
= NULL
;
1372 printf("Usage: enumdrivers [level] [architecture]\n");
1377 level
= atoi(argv
[1]);
1381 architecture
= argv
[2];
1385 return enum_driver_by_architecture(cli
, mem_ctx
,
1390 /* loop through and print driver info level for each architecture */
1391 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1392 /* check to see if we already asked for this architecture string */
1394 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1398 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1399 archi_table
[i
].long_archi
,
1401 if (!W_ERROR_IS_OK(werror
)) {
1409 /****************************************************************************
1410 ****************************************************************************/
1412 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1414 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1417 /****************************************************************************
1418 ****************************************************************************/
1420 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1421 TALLOC_CTX
*mem_ctx
,
1422 int argc
, const char **argv
)
1426 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1429 union spoolss_DriverDirectoryInfo info
;
1433 printf("Usage: %s [environment]\n", argv
[0]);
1437 /* Get the arguments need to open the printer handle */
1443 /* Get the directory. Only use Info level 1 */
1445 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1446 cli
->srv_name_slash
,
1454 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1456 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1458 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1459 cli
->srv_name_slash
,
1469 if (W_ERROR_IS_OK(result
)) {
1470 display_printdriverdir_1(&info
.info1
);
1476 /****************************************************************************
1477 ****************************************************************************/
1479 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1480 struct spoolss_AddDriverInfo3
*info
,
1486 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1488 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1490 info
->version
= archi_table
[i
].version
;
1491 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1496 if (archi_table
[i
].long_archi
== NULL
)
1498 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1505 /**************************************************************************
1506 wrapper for strtok to get the next parameter from a delimited list.
1507 Needed to handle the empty parameter string denoted by "NULL"
1508 *************************************************************************/
1510 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1511 const char *delim
, const char **dest
,
1516 /* get the next token */
1517 ptr
= strtok_r(str
, delim
, saveptr
);
1519 /* a string of 'NULL' is used to represent an empty
1520 parameter because two consecutive delimiters
1521 will not return an empty string. See man strtok(3)
1523 if (ptr
&& (StrCaseCmp(ptr
, "NULL") == 0)) {
1528 *dest
= talloc_strdup(mem_ctx
, ptr
);
1534 /********************************************************************************
1535 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1536 string in the form of
1537 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1538 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1539 <Default Data Type>:<Comma Separated list of Files>
1540 *******************************************************************************/
1542 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1547 char *saveptr
= NULL
;
1548 struct spoolss_StringArray
*deps
;
1549 const char **file_array
= NULL
;
1552 /* fill in the UNISTR fields */
1553 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1554 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1555 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1556 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1557 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1558 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1559 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1561 /* <Comma Separated List of Dependent Files> */
1562 /* save the beginning of the string */
1563 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1566 /* begin to strip out each filename */
1567 str
= strtok_r(str
, ",", &saveptr
);
1569 /* no dependent files, we are done */
1574 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1579 while (str
!= NULL
) {
1580 add_string_to_array(deps
, str
, &file_array
, &count
);
1581 str
= strtok_r(NULL
, ",", &saveptr
);
1584 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1585 if (!deps
->string
) {
1589 for (i
=0; i
< count
; i
++) {
1590 deps
->string
[i
] = file_array
[i
];
1593 r
->dependent_files
= deps
;
1598 /****************************************************************************
1599 ****************************************************************************/
1601 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1602 TALLOC_CTX
*mem_ctx
,
1603 int argc
, const char **argv
)
1608 struct spoolss_AddDriverInfoCtr info_ctr
;
1609 struct spoolss_AddDriverInfo3 info3
;
1613 /* parse the command arguments */
1614 if (argc
!= 3 && argc
!= 4)
1616 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1617 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1618 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1619 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1620 printf ("\t[version]\n");
1625 /* Fill in the spoolss_AddDriverInfo3 struct */
1628 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1630 printf ("Error Unknown architechture [%s]\n", argv
[1]);
1631 return WERR_INVALID_PARAM
;
1634 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1636 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1637 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1639 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1640 return WERR_INVALID_PARAM
;
1643 /* if printer driver version specified, override the default version
1644 * used by the architecture. This allows installation of Windows
1645 * 2000 (version 3) printer drivers. */
1648 info3
.version
= atoi(argv
[3]);
1652 info_ctr
.level
= level
;
1653 info_ctr
.info
.info3
= &info3
;
1655 status
= rpccli_spoolss_AddPrinterDriver(cli
, mem_ctx
,
1656 cli
->srv_name_slash
,
1659 if (!NT_STATUS_IS_OK(status
)) {
1660 return ntstatus_to_werror(status
);
1662 if (W_ERROR_IS_OK(result
)) {
1663 printf ("Printer Driver %s successfully installed.\n",
1671 /****************************************************************************
1672 ****************************************************************************/
1674 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1675 TALLOC_CTX
*mem_ctx
,
1676 int argc
, const char **argv
)
1679 struct spoolss_SetPrinterInfoCtr info_ctr
;
1680 struct spoolss_SetPrinterInfo2 info2
;
1682 /* parse the command arguments */
1685 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1689 /* Fill in the DRIVER_INFO_2 struct */
1692 info2
.printername
= argv
[1];
1693 info2
.drivername
= argv
[3];
1694 info2
.sharename
= argv
[2];
1695 info2
.portname
= argv
[4];
1696 info2
.comment
= "Created by rpcclient";
1697 info2
.printprocessor
= "winprint";
1698 info2
.datatype
= "RAW";
1699 info2
.devmode_ptr
= 0;
1700 info2
.secdesc_ptr
= 0;
1701 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1703 info2
.defaultpriority
= 0;
1704 info2
.starttime
= 0;
1705 info2
.untiltime
= 0;
1707 /* These three fields must not be used by AddPrinter()
1708 as defined in the MS Platform SDK documentation..
1712 info2.averageppm = 0;
1716 info_ctr
.info
.info2
= &info2
;
1718 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1720 if (W_ERROR_IS_OK(result
))
1721 printf ("Printer %s successfully installed.\n", argv
[1]);
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1730 TALLOC_CTX
*mem_ctx
,
1731 int argc
, const char **argv
)
1733 struct policy_handle pol
;
1737 const char *printername
;
1738 union spoolss_PrinterInfo info
;
1739 struct spoolss_SetPrinterInfoCtr info_ctr
;
1740 struct spoolss_SetPrinterInfo2 info2
;
1741 struct spoolss_DevmodeContainer devmode_ctr
;
1742 struct sec_desc_buf secdesc_ctr
;
1744 ZERO_STRUCT(devmode_ctr
);
1745 ZERO_STRUCT(secdesc_ctr
);
1747 /* parse the command arguments */
1750 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1754 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1756 /* Get a printer handle */
1758 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1762 if (!W_ERROR_IS_OK(result
))
1765 /* Get printer info */
1767 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1772 if (!W_ERROR_IS_OK(result
)) {
1773 printf ("Unable to retrieve printer information!\n");
1777 /* Set the printer driver */
1779 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
1780 info2
.drivername
= argv
[2];
1783 info_ctr
.info
.info2
= &info2
;
1785 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
1792 if (!W_ERROR_IS_OK(result
)) {
1793 printf("SetPrinter call failed!\n");
1797 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1802 if (is_valid_policy_hnd(&pol
))
1803 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1809 /****************************************************************************
1810 ****************************************************************************/
1812 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
1813 TALLOC_CTX
*mem_ctx
,
1814 int argc
, const char **argv
)
1816 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
1822 const char *arch
= NULL
;
1823 uint32_t delete_flags
= 0;
1825 /* parse the command arguments */
1826 if (argc
< 2 || argc
> 4) {
1827 printf ("Usage: %s <driver> [arch] [version]\n", argv
[0]);
1834 vers
= atoi (argv
[3]);
1837 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
1840 /* delete the driver for all architectures */
1841 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1843 if (arch
&& !strequal( archi_table
[i
].long_archi
, arch
))
1846 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
1849 /* make the call to remove the driver */
1850 status
= rpccli_spoolss_DeletePrinterDriverEx(cli
, mem_ctx
,
1851 cli
->srv_name_slash
,
1852 archi_table
[i
].long_archi
,
1855 archi_table
[i
].version
,
1858 if ( !W_ERROR_IS_OK(result
) )
1860 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1861 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1862 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
1867 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
1868 archi_table
[i
].long_archi
, archi_table
[i
].version
);
1877 /****************************************************************************
1878 ****************************************************************************/
1880 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
1881 TALLOC_CTX
*mem_ctx
,
1882 int argc
, const char **argv
)
1884 WERROR result
= WERR_OK
;
1888 /* parse the command arguments */
1890 printf ("Usage: %s <driver>\n", argv
[0]);
1894 /* delete the driver for all architectures */
1895 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1898 /* make the call to remove the driver */
1899 status
= rpccli_spoolss_DeletePrinterDriver(cli
, mem_ctx
,
1900 cli
->srv_name_slash
,
1901 archi_table
[i
].long_archi
,
1904 if (!NT_STATUS_IS_OK(status
)) {
1905 if (W_ERROR_IS_OK(result
)) {
1906 result
= ntstatus_to_werror(status
);
1909 if ( !W_ERROR_IS_OK(result
) ) {
1910 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1911 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1912 argv
[1], archi_table
[i
].long_archi
,
1916 printf ("Driver %s removed for arch [%s].\n", argv
[1],
1917 archi_table
[i
].long_archi
);
1924 /****************************************************************************
1925 ****************************************************************************/
1927 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
1928 TALLOC_CTX
*mem_ctx
,
1929 int argc
, const char **argv
)
1933 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
1936 union spoolss_PrintProcessorDirectoryInfo info
;
1939 /* parse the command arguments */
1941 printf ("Usage: %s [environment]\n", argv
[0]);
1946 environment
= argv
[1];
1949 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1950 cli
->srv_name_slash
,
1958 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1960 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1962 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1963 cli
->srv_name_slash
,
1973 if (W_ERROR_IS_OK(result
)) {
1974 printf("%s\n", info
.info1
.directory_name
);
1980 /****************************************************************************
1981 ****************************************************************************/
1983 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
1984 int argc
, const char **argv
)
1986 struct policy_handle handle
;
1989 const char *printername
;
1990 union spoolss_AddFormInfo info
;
1991 struct spoolss_AddFormInfo1 info1
;
1992 struct spoolss_AddFormInfo2 info2
;
1995 /* Parse the command arguments */
1997 if (argc
< 3 || argc
> 5) {
1998 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2002 /* Get a printer handle */
2004 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2006 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2010 if (!W_ERROR_IS_OK(werror
))
2013 /* Dummy up some values for the form data */
2016 level
= atoi(argv
[3]);
2021 info1
.flags
= SPOOLSS_FORM_USER
;
2022 info1
.form_name
= argv
[2];
2023 info1
.size
.width
= 100;
2024 info1
.size
.height
= 100;
2025 info1
.area
.left
= 0;
2026 info1
.area
.top
= 10;
2027 info1
.area
.right
= 20;
2028 info1
.area
.bottom
= 30;
2030 info
.info1
= &info1
;
2034 info2
.flags
= SPOOLSS_FORM_USER
;
2035 info2
.form_name
= argv
[2];
2036 info2
.size
.width
= 100;
2037 info2
.size
.height
= 100;
2038 info2
.area
.left
= 0;
2039 info2
.area
.top
= 10;
2040 info2
.area
.right
= 20;
2041 info2
.area
.bottom
= 30;
2042 info2
.keyword
= argv
[2];
2043 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2044 info2
.mui_dll
= NULL
;
2045 info2
.ressource_id
= 0;
2046 info2
.display_name
= argv
[2];
2049 info
.info2
= &info2
;
2057 status
= rpccli_spoolss_AddForm(cli
, mem_ctx
,
2064 if (is_valid_policy_hnd(&handle
))
2065 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2070 /****************************************************************************
2071 ****************************************************************************/
2073 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2074 int argc
, const char **argv
)
2076 struct policy_handle handle
;
2079 const char *printername
;
2080 union spoolss_AddFormInfo info
;
2081 struct spoolss_AddFormInfo1 info1
;
2083 /* Parse the command arguments */
2086 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2090 /* Get a printer handle */
2092 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2094 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2096 SEC_FLAG_MAXIMUM_ALLOWED
,
2098 if (!W_ERROR_IS_OK(werror
))
2101 /* Dummy up some values for the form data */
2103 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2104 info1
.size
.width
= 100;
2105 info1
.size
.height
= 100;
2106 info1
.area
.left
= 0;
2107 info1
.area
.top
= 1000;
2108 info1
.area
.right
= 2000;
2109 info1
.area
.bottom
= 3000;
2110 info1
.form_name
= argv
[2];
2112 info
.info1
= &info1
;
2116 status
= rpccli_spoolss_SetForm(cli
, mem_ctx
,
2124 if (is_valid_policy_hnd(&handle
))
2125 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2130 /****************************************************************************
2131 ****************************************************************************/
2133 static const char *get_form_flag(int form_flag
)
2135 switch (form_flag
) {
2136 case SPOOLSS_FORM_USER
:
2138 case SPOOLSS_FORM_BUILTIN
:
2139 return "FORM_BUILTIN";
2140 case SPOOLSS_FORM_PRINTER
:
2141 return "FORM_PRINTER";
2147 /****************************************************************************
2148 ****************************************************************************/
2150 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2153 "\tflag: %s (%d)\n" \
2154 "\twidth: %d, length: %d\n" \
2155 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2156 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2157 r
->size
.width
, r
->size
.height
,
2158 r
->area
.left
, r
->area
.right
,
2159 r
->area
.top
, r
->area
.bottom
);
2162 /****************************************************************************
2163 ****************************************************************************/
2165 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2168 "\tflag: %s (%d)\n" \
2169 "\twidth: %d, length: %d\n" \
2170 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2171 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2172 r
->size
.width
, r
->size
.height
,
2173 r
->area
.left
, r
->area
.right
,
2174 r
->area
.top
, r
->area
.bottom
);
2175 printf("\tkeyword: %s\n", r
->keyword
);
2176 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2177 printf("\tmui_dll: %s\n", r
->mui_dll
);
2178 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2179 printf("\tdisplay_name: %s\n", r
->display_name
);
2180 printf("\tlang_id: %d\n", r
->lang_id
);
2184 /****************************************************************************
2185 ****************************************************************************/
2187 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2188 int argc
, const char **argv
)
2190 struct policy_handle handle
;
2193 const char *printername
;
2195 uint32_t offered
= 0;
2196 union spoolss_FormInfo info
;
2200 /* Parse the command arguments */
2202 if (argc
< 3 || argc
> 5) {
2203 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2207 /* Get a printer handle */
2209 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2211 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2213 SEC_FLAG_MAXIMUM_ALLOWED
,
2215 if (!W_ERROR_IS_OK(werror
))
2219 level
= atoi(argv
[3]);
2224 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2233 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2234 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2236 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2247 if (!NT_STATUS_IS_OK(status
)) {
2253 display_form_info1(&info
.info1
);
2256 display_form_info2(&info
.info2
);
2261 if (is_valid_policy_hnd(&handle
))
2262 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2267 /****************************************************************************
2268 ****************************************************************************/
2270 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2271 TALLOC_CTX
*mem_ctx
, int argc
,
2274 struct policy_handle handle
;
2277 const char *printername
;
2279 /* Parse the command arguments */
2282 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2286 /* Get a printer handle */
2288 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2290 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2292 SEC_FLAG_MAXIMUM_ALLOWED
,
2294 if (!W_ERROR_IS_OK(werror
))
2297 /* Delete the form */
2299 status
= rpccli_spoolss_DeleteForm(cli
, mem_ctx
,
2303 if (!NT_STATUS_IS_OK(status
)) {
2304 return ntstatus_to_werror(status
);
2308 if (is_valid_policy_hnd(&handle
))
2309 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2314 /****************************************************************************
2315 ****************************************************************************/
2317 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2318 TALLOC_CTX
*mem_ctx
, int argc
,
2321 struct policy_handle handle
;
2323 const char *printername
;
2324 uint32_t num_forms
, level
= 1, i
;
2325 union spoolss_FormInfo
*forms
;
2327 /* Parse the command arguments */
2329 if (argc
< 2 || argc
> 4) {
2330 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2334 /* Get a printer handle */
2336 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2338 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2340 SEC_FLAG_MAXIMUM_ALLOWED
,
2342 if (!W_ERROR_IS_OK(werror
))
2346 level
= atoi(argv
[2]);
2349 /* Enumerate forms */
2351 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2358 if (!W_ERROR_IS_OK(werror
))
2361 /* Display output */
2363 for (i
= 0; i
< num_forms
; i
++) {
2366 display_form_info1(&forms
[i
].info1
);
2369 display_form_info2(&forms
[i
].info2
);
2375 if (is_valid_policy_hnd(&handle
))
2376 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2381 /****************************************************************************
2382 ****************************************************************************/
2384 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2385 TALLOC_CTX
*mem_ctx
,
2386 int argc
, const char **argv
)
2390 const char *printername
;
2391 struct policy_handle pol
;
2392 union spoolss_PrinterInfo info
;
2393 enum winreg_Type type
;
2394 union spoolss_PrinterData data
;
2397 /* parse the command arguments */
2399 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2400 " <value> <data>\n",
2402 result
= WERR_INVALID_PARAM
;
2406 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2410 if (strequal(argv
[2], "string")) {
2414 if (strequal(argv
[2], "binary")) {
2418 if (strequal(argv
[2], "dword")) {
2422 if (strequal(argv
[2], "multistring")) {
2423 type
= REG_MULTI_SZ
;
2426 if (type
== REG_NONE
) {
2427 printf("Unknown data type: %s\n", argv
[2]);
2428 result
= WERR_INVALID_PARAM
;
2432 /* get a printer handle */
2434 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2436 SEC_FLAG_MAXIMUM_ALLOWED
,
2438 if (!W_ERROR_IS_OK(result
)) {
2442 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2447 if (!W_ERROR_IS_OK(result
)) {
2451 printf("%s\n", current_timestring(mem_ctx
, true));
2452 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2454 /* Set the printer data */
2458 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2459 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2462 data
.value
= strtoul(argv
[4], NULL
, 10);
2465 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2467 case REG_MULTI_SZ
: {
2469 const char **strings
= NULL
;
2471 for (i
=4; i
<argc
; i
++) {
2472 if (strcmp(argv
[i
], "NULL") == 0) {
2475 if (!add_string_to_array(mem_ctx
, argv
[i
],
2478 result
= WERR_NOMEM
;
2482 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2483 if (!data
.string_array
) {
2484 result
= WERR_NOMEM
;
2487 for (i
=0; i
< num_strings
; i
++) {
2488 data
.string_array
[i
] = strings
[i
];
2493 printf("Unknown data type: %s\n", argv
[2]);
2494 result
= WERR_INVALID_PARAM
;
2498 result
= push_spoolss_PrinterData(mem_ctx
, &blob
, type
, &data
);
2499 if (!W_ERROR_IS_OK(result
)) {
2503 status
= rpccli_spoolss_SetPrinterData(cli
, mem_ctx
,
2505 argv
[3], /* value_name */
2510 if (!W_ERROR_IS_OK(result
)) {
2511 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2514 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2516 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2521 if (!W_ERROR_IS_OK(result
)) {
2525 printf("%s\n", current_timestring(mem_ctx
, true));
2526 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2530 if (is_valid_policy_hnd(&pol
)) {
2531 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
2537 /****************************************************************************
2538 ****************************************************************************/
2540 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2542 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2543 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2547 /****************************************************************************
2548 ****************************************************************************/
2550 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2552 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2553 r
->position
, r
->job_id
,
2554 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2555 r
->total_pages
, r
->size
);
2558 /****************************************************************************
2559 ****************************************************************************/
2561 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2563 printf("jobid[%d], next_jobid[%d]\n",
2564 r
->job_id
, r
->next_job_id
);
2567 /****************************************************************************
2568 ****************************************************************************/
2570 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2572 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2573 r
->position
, r
->job_id
,
2574 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2575 r
->total_pages
, r
->size
, r
->size_high
);
2578 /****************************************************************************
2579 ****************************************************************************/
2581 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2582 TALLOC_CTX
*mem_ctx
, int argc
,
2586 uint32_t level
= 1, count
, i
;
2587 const char *printername
;
2588 struct policy_handle hnd
;
2589 union spoolss_JobInfo
*info
;
2591 if (argc
< 2 || argc
> 3) {
2592 printf("Usage: %s printername [level]\n", argv
[0]);
2597 level
= atoi(argv
[2]);
2600 /* Open printer handle */
2602 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2604 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2606 SEC_FLAG_MAXIMUM_ALLOWED
,
2608 if (!W_ERROR_IS_OK(result
))
2611 /* Enumerate ports */
2613 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2621 if (!W_ERROR_IS_OK(result
)) {
2625 for (i
= 0; i
< count
; i
++) {
2628 display_job_info1(&info
[i
].info1
);
2631 display_job_info2(&info
[i
].info2
);
2634 d_printf("unknown info level %d\n", level
);
2640 if (is_valid_policy_hnd(&hnd
)) {
2641 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2647 /****************************************************************************
2648 ****************************************************************************/
2650 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2651 TALLOC_CTX
*mem_ctx
, int argc
,
2655 const char *printername
;
2656 struct policy_handle hnd
;
2659 union spoolss_JobInfo info
;
2661 if (argc
< 3 || argc
> 4) {
2662 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2666 job_id
= atoi(argv
[2]);
2669 level
= atoi(argv
[3]);
2672 /* Open printer handle */
2674 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2676 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2678 SEC_FLAG_MAXIMUM_ALLOWED
,
2680 if (!W_ERROR_IS_OK(result
)) {
2684 /* Enumerate ports */
2686 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2693 if (!W_ERROR_IS_OK(result
)) {
2699 display_job_info1(&info
.info1
);
2702 display_job_info2(&info
.info2
);
2705 display_job_info3(&info
.info3
);
2708 display_job_info4(&info
.info4
);
2711 d_printf("unknown info level %d\n", level
);
2716 if (is_valid_policy_hnd(&hnd
)) {
2717 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2723 /****************************************************************************
2724 ****************************************************************************/
2726 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
2727 TALLOC_CTX
*mem_ctx
, int argc
,
2732 const char *printername
;
2733 struct policy_handle hnd
;
2735 enum spoolss_JobControl command
;
2738 printf("Usage: %s printername job_id command\n", argv
[0]);
2742 job_id
= atoi(argv
[2]);
2743 command
= atoi(argv
[3]);
2745 /* Open printer handle */
2747 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2749 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2751 SEC_FLAG_MAXIMUM_ALLOWED
,
2753 if (!W_ERROR_IS_OK(result
)) {
2759 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
2766 if (!W_ERROR_IS_OK(result
)) {
2771 if (is_valid_policy_hnd(&hnd
)) {
2772 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2778 /****************************************************************************
2779 ****************************************************************************/
2781 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
2782 TALLOC_CTX
*mem_ctx
, int argc
,
2788 const char *printername
;
2789 struct policy_handle hnd
;
2790 uint32_t value_offered
= 0;
2791 const char *value_name
= NULL
;
2792 uint32_t value_needed
;
2793 enum winreg_Type type
;
2794 uint8_t *data
= NULL
;
2795 uint32_t data_offered
= 0;
2796 uint32_t data_needed
;
2799 printf("Usage: %s printername\n", argv
[0]);
2803 /* Open printer handle */
2805 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2807 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2809 SEC_FLAG_MAXIMUM_ALLOWED
,
2811 if (!W_ERROR_IS_OK(result
)) {
2815 /* Enumerate data */
2817 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2829 data_offered
= data_needed
;
2830 value_offered
= value_needed
;
2831 data
= talloc_zero_array(mem_ctx
, uint8_t, data_needed
);
2832 value_name
= talloc_zero_array(mem_ctx
, char, value_needed
);
2834 while (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2836 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2847 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2848 struct regval_blob v
;
2849 fstrcpy(v
.valuename
, value_name
);
2851 v
.size
= data_offered
;
2853 display_reg_value(v
);
2857 if (W_ERROR_V(result
) == ERRnomoreitems
) {
2858 result
= W_ERROR(ERRsuccess
);
2862 if (is_valid_policy_hnd(&hnd
)) {
2863 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2869 /****************************************************************************
2870 ****************************************************************************/
2872 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
2873 TALLOC_CTX
*mem_ctx
, int argc
,
2878 const char *printername
;
2879 struct policy_handle hnd
;
2881 struct spoolss_PrinterEnumValues
*info
;
2884 printf("Usage: %s printername <keyname>\n", argv
[0]);
2888 /* Open printer handle */
2890 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2892 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2894 SEC_FLAG_MAXIMUM_ALLOWED
,
2896 if (!W_ERROR_IS_OK(result
)) {
2900 /* Enumerate subkeys */
2902 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
2908 if (!W_ERROR_IS_OK(result
)) {
2912 for (i
=0; i
< count
; i
++) {
2913 display_printer_data(info
[i
].value_name
,
2916 info
[i
].data
->length
);
2920 if (is_valid_policy_hnd(&hnd
)) {
2921 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2927 /****************************************************************************
2928 ****************************************************************************/
2930 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
2931 TALLOC_CTX
*mem_ctx
, int argc
,
2935 const char *printername
;
2936 const char *keyname
= NULL
;
2937 struct policy_handle hnd
;
2938 const char **key_buffer
= NULL
;
2940 uint32_t offered
= 0;
2942 if (argc
< 2 || argc
> 4) {
2943 printf("Usage: %s printername [keyname] [offered]\n", argv
[0]);
2954 offered
= atoi(argv
[3]);
2957 /* Open printer handle */
2959 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2961 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2963 SEC_FLAG_MAXIMUM_ALLOWED
,
2965 if (!W_ERROR_IS_OK(result
)) {
2969 /* Enumerate subkeys */
2971 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
2977 if (!W_ERROR_IS_OK(result
)) {
2981 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
2982 printf("%s\n", key_buffer
[i
]);
2987 if (is_valid_policy_hnd(&hnd
)) {
2988 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2994 /****************************************************************************
2995 ****************************************************************************/
2997 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
2998 TALLOC_CTX
*mem_ctx
, int argc
,
3001 const char *printername
;
3002 const char *clientname
;
3003 struct policy_handle hnd
;
3006 struct spoolss_NotifyOption option
;
3009 printf("Usage: %s printername\n", argv
[0]);
3016 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3018 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3020 SEC_FLAG_MAXIMUM_ALLOWED
,
3022 if (!W_ERROR_IS_OK(result
)) {
3023 printf("Error opening %s\n", argv
[1]);
3027 /* Create spool options */
3032 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3033 if (option
.types
== NULL
) {
3034 result
= WERR_NOMEM
;
3038 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3039 option
.types
[0].count
= 1;
3040 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3041 if (option
.types
[0].fields
== NULL
) {
3042 result
= WERR_NOMEM
;
3045 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3047 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3048 option
.types
[1].count
= 1;
3049 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3050 if (option
.types
[1].fields
== NULL
) {
3051 result
= WERR_NOMEM
;
3054 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3056 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
3058 result
= WERR_NOMEM
;
3064 status
= rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli
, mem_ctx
,
3072 if (!W_ERROR_IS_OK(result
)) {
3073 printf("Error rffpcnex %s\n", argv
[1]);
3078 if (is_valid_policy_hnd(&hnd
))
3079 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3084 /****************************************************************************
3085 ****************************************************************************/
3087 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3088 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3090 union spoolss_PrinterInfo info1
, info2
;
3092 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3094 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3095 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3100 if ( !W_ERROR_IS_OK(werror
) ) {
3101 printf("failed (%s)\n", win_errstr(werror
));
3102 talloc_destroy(mem_ctx
);
3107 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3108 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3113 if ( !W_ERROR_IS_OK(werror
) ) {
3114 printf("failed (%s)\n", win_errstr(werror
));
3115 talloc_destroy(mem_ctx
);
3120 talloc_destroy(mem_ctx
);
3125 /****************************************************************************
3126 ****************************************************************************/
3128 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3129 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3131 union spoolss_PrinterInfo info1
, info2
;
3133 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3134 SEC_DESC
*sd1
, *sd2
;
3138 printf("Retrieving printer security for %s...", cli1
->desthost
);
3139 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3144 if ( !W_ERROR_IS_OK(werror
) ) {
3145 printf("failed (%s)\n", win_errstr(werror
));
3151 printf("Retrieving printer security for %s...", cli2
->desthost
);
3152 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3157 if ( !W_ERROR_IS_OK(werror
) ) {
3158 printf("failed (%s)\n", win_errstr(werror
));
3167 sd1
= info1
.info3
.secdesc
;
3168 sd2
= info2
.info3
.secdesc
;
3170 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3171 printf("NULL secdesc!\n");
3176 if (!security_descriptor_equal( sd1
, sd2
) ) {
3177 printf("Security Descriptors *not* equal!\n");
3182 printf("Security descriptors match\n");
3185 talloc_destroy(mem_ctx
);
3190 /****************************************************************************
3191 ****************************************************************************/
3193 extern struct user_auth_info
*rpcclient_auth_info
;
3195 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3196 TALLOC_CTX
*mem_ctx
, int argc
,
3199 const char *printername
;
3200 char *printername_path
= NULL
;
3201 struct cli_state
*cli_server2
= NULL
;
3202 struct rpc_pipe_client
*cli2
= NULL
;
3203 struct policy_handle hPrinter1
, hPrinter2
;
3208 printf("Usage: %s <printer> <server>\n", argv
[0]);
3212 printername
= argv
[1];
3214 /* first get the connection to the remote server */
3216 nt_status
= cli_full_connection(&cli_server2
, global_myname(), argv
[2],
3219 get_cmdline_auth_info_username(rpcclient_auth_info
),
3221 get_cmdline_auth_info_password(rpcclient_auth_info
),
3222 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info
) ? CLI_FULL_CONNECTION_USE_KERBEROS
: 0,
3223 get_cmdline_auth_info_signing_state(rpcclient_auth_info
), NULL
);
3225 if ( !NT_STATUS_IS_OK(nt_status
) )
3226 return WERR_GENERAL_FAILURE
;
3228 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
.syntax_id
,
3230 if (!NT_STATUS_IS_OK(nt_status
)) {
3231 printf("failed to open spoolss pipe on server %s (%s)\n",
3232 argv
[2], nt_errstr(nt_status
));
3233 return WERR_GENERAL_FAILURE
;
3236 /* now open up both printers */
3238 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3240 printf("Opening %s...", printername_path
);
3242 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3246 if ( !W_ERROR_IS_OK(werror
) ) {
3247 printf("failed (%s)\n", win_errstr(werror
));
3252 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3254 printf("Opening %s...", printername_path
);
3255 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3259 if ( !W_ERROR_IS_OK(werror
) ) {
3260 printf("failed (%s)\n", win_errstr(werror
));
3265 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3266 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3268 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3275 printf("Closing printers...");
3276 rpccli_spoolss_ClosePrinter( cli
, mem_ctx
, &hPrinter1
, NULL
);
3277 rpccli_spoolss_ClosePrinter( cli2
, mem_ctx
, &hPrinter2
, NULL
);
3280 /* close the second remote connection */
3282 cli_shutdown( cli_server2
);
3286 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3288 printf("print_processor_name: %s\n", r
->print_processor_name
);
3291 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3292 TALLOC_CTX
*mem_ctx
, int argc
,
3296 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3297 uint32_t num_procs
, level
= 1, i
;
3298 union spoolss_PrintProcessorInfo
*procs
;
3300 /* Parse the command arguments */
3302 if (argc
< 1 || argc
> 4) {
3303 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3308 environment
= argv
[1];
3312 level
= atoi(argv
[2]);
3315 /* Enumerate Print Processors */
3317 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3318 cli
->srv_name_slash
,
3324 if (!W_ERROR_IS_OK(werror
))
3327 /* Display output */
3329 for (i
= 0; i
< num_procs
; i
++) {
3332 display_proc_info1(&procs
[i
].info1
);
3341 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3343 printf("name_array: %s\n", r
->name_array
);
3346 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3347 TALLOC_CTX
*mem_ctx
, int argc
,
3351 const char *print_processor_name
= "winprint";
3352 uint32_t num_procs
, level
= 1, i
;
3353 union spoolss_PrintProcDataTypesInfo
*procs
;
3355 /* Parse the command arguments */
3357 if (argc
< 1 || argc
> 4) {
3358 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3363 print_processor_name
= argv
[1];
3367 level
= atoi(argv
[2]);
3370 /* Enumerate Print Processor Data Types */
3372 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3373 cli
->srv_name_slash
,
3374 print_processor_name
,
3379 if (!W_ERROR_IS_OK(werror
))
3382 /* Display output */
3384 for (i
= 0; i
< num_procs
; i
++) {
3387 display_proc_data_types_info1(&procs
[i
].info1
);
3396 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3398 printf("monitor_name: %s\n", r
->monitor_name
);
3401 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3403 printf("monitor_name: %s\n", r
->monitor_name
);
3404 printf("environment: %s\n", r
->environment
);
3405 printf("dll_name: %s\n", r
->dll_name
);
3408 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3409 TALLOC_CTX
*mem_ctx
, int argc
,
3413 uint32_t count
, level
= 1, i
;
3414 union spoolss_MonitorInfo
*info
;
3416 /* Parse the command arguments */
3419 printf("Usage: %s [level]\n", argv
[0]);
3424 level
= atoi(argv
[1]);
3427 /* Enumerate Print Monitors */
3429 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3430 cli
->srv_name_slash
,
3435 if (!W_ERROR_IS_OK(werror
)) {
3439 /* Display output */
3441 for (i
= 0; i
< count
; i
++) {
3444 display_monitor1(&info
[i
].info1
);
3447 display_monitor2(&info
[i
].info2
);
3456 static WERROR
cmd_spoolss_create_printer_ic(struct rpc_pipe_client
*cli
,
3457 TALLOC_CTX
*mem_ctx
, int argc
,
3462 struct policy_handle handle
, gdi_handle
;
3463 const char *printername
;
3464 struct spoolss_DevmodeContainer devmode_ctr
;
3466 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3468 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3470 SEC_FLAG_MAXIMUM_ALLOWED
,
3472 if (!W_ERROR_IS_OK(result
)) {
3476 ZERO_STRUCT(devmode_ctr
);
3478 status
= rpccli_spoolss_CreatePrinterIC(cli
, mem_ctx
,
3483 if (!W_ERROR_IS_OK(result
)) {
3488 if (is_valid_policy_hnd(&gdi_handle
)) {
3489 rpccli_spoolss_DeletePrinterIC(cli
, mem_ctx
, &gdi_handle
, NULL
);
3491 if (is_valid_policy_hnd(&handle
)) {
3492 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3498 /* List of commands exported by this module */
3499 struct cmd_set spoolss_commands
[] = {
3503 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a print driver", "" },
3504 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a printer", "" },
3505 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver", "" },
3506 { "deldriverex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriverex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver with files", "" },
3507 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data", "" },
3508 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data for a key", "" },
3509 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer keys", "" },
3510 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate print jobs", "" },
3511 { "getjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_get_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print job", "" },
3512 { "setjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_set_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set print job", "" },
3513 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer ports", "" },
3514 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate installed printer drivers", "" },
3515 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printers", "" },
3516 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver data", "" },
3517 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer driver data with keyname", ""},
3518 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver information", "" },
3519 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver upload directory", "" },
3520 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer info", "" },
3521 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Open printer handle", "" },
3522 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer driver", "" },
3523 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print processor directory", "" },
3524 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add form", "" },
3525 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set form", "" },
3526 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get form", "" },
3527 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete form", "" },
3528 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate forms", "" },
3529 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer comment", "" },
3530 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printername", "" },
3531 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set REG_SZ printer data", "" },
3532 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Rffpcnex test", "" },
3533 { "printercmp", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_printercmp
, &ndr_table_spoolss
.syntax_id
, NULL
, "Printer comparison test", "" },
3534 { "enumprocs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_procs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processors", "" },
3535 { "enumprocdatatypes", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_proc_data_types
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processor Data Types", "" },
3536 { "enummonitors", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_monitors
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Monitors", "" },
3537 { "createprinteric", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_create_printer_ic
, &ndr_table_spoolss
.syntax_id
, NULL
, "Create Printer IC", "" },