2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "rpcclient.h"
28 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
30 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
31 _cli->srv_name_slash, _arg); \
32 W_ERROR_HAVE_NO_MEMORY(_printername); \
35 /* The version int is used by getdrivers. Note that
36 all architecture strings that support mutliple
37 versions must be grouped together since enumdrivers
38 uses this property to prevent issuing multiple
39 enumdriver calls for the same arch */
42 static const struct print_architecture_table_node archi_table
[]= {
44 {"Windows 4.0", "WIN40", 0 },
45 {"Windows NT x86", "W32X86", 2 },
46 {"Windows NT x86", "W32X86", 3 },
47 {"Windows NT R4000", "W32MIPS", 2 },
48 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
49 {"Windows NT PowerPC", "W32PPC", 2 },
50 {"Windows IA64", "IA64", 3 },
51 {"Windows x64", "x64", 3 },
58 * rpcclient module for SPOOLSS rpc pipe.
60 * This generally just parses and checks command lines, and then calls
61 * a cli_spoolss function.
64 /****************************************************************************
65 function to do the mapping between the long architecture name and
67 ****************************************************************************/
69 static const char *cmd_spoolss_get_short_archi(const char *long_archi
)
73 DEBUG(107,("Getting architecture dependant directory\n"));
76 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
77 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
79 if (archi_table
[i
].long_archi
==NULL
) {
80 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
84 /* this might be client code - but shouldn't this be an fstrcpy etc? */
87 DEBUGADD(108,("index: [%d]\n", i
));
88 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
89 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
91 return archi_table
[i
].short_archi
;
94 /****************************************************************************
95 ****************************************************************************/
97 static WERROR
cmd_spoolss_open_printer_ex(struct rpc_pipe_client
*cli
,
99 int argc
, const char **argv
)
102 struct policy_handle hnd
;
105 printf("Usage: %s <printername>\n", argv
[0]);
110 return WERR_GENERAL_FAILURE
;
112 /* Open the printer handle */
114 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
118 if (W_ERROR_IS_OK(werror
)) {
119 printf("Printer %s opened successfully\n", argv
[1]);
120 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, &werror
);
122 if (!W_ERROR_IS_OK(werror
)) {
123 printf("Error closing printer handle! (%s)\n",
124 get_dos_error_msg(werror
));
132 /****************************************************************************
133 ****************************************************************************/
135 static void display_print_info0(struct spoolss_PrinterInfo0
*r
)
140 printf("\tprintername:[%s]\n", r
->printername
);
141 printf("\tservername:[%s]\n", r
->servername
);
142 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
143 printf("\ttotal_jobs:[0x%x]\n", r
->total_jobs
);
144 printf("\ttotal_bytes:[0x%x]\n", r
->total_bytes
);
145 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r
->time
.year
, r
->time
.month
,
146 r
->time
.day
, r
->time
.day_of_week
);
147 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r
->time
.hour
, r
->time
.minute
,
148 r
->time
.second
, r
->time
.millisecond
);
150 printf("\tglobal_counter:[0x%x]\n", r
->global_counter
);
151 printf("\ttotal_pages:[0x%x]\n", r
->total_pages
);
153 printf("\tversion:[0x%x]\n", r
->version
);
154 printf("\tfree_build:[0x%x]\n", r
->free_build
);
155 printf("\tspooling:[0x%x]\n", r
->spooling
);
156 printf("\tmax_spooling:[0x%x]\n", r
->max_spooling
);
157 printf("\tsession_counter:[0x%x]\n", r
->session_counter
);
158 printf("\tnum_error_out_of_paper:[0x%x]\n", r
->num_error_out_of_paper
);
159 printf("\tnum_error_not_ready:[0x%x]\n", r
->num_error_not_ready
);
160 printf("\tjob_error:[0x%x]\n", r
->job_error
);
161 printf("\tnumber_of_processors:[0x%x]\n", r
->number_of_processors
);
162 printf("\tprocessor_type:[0x%x]\n", r
->processor_type
);
163 printf("\thigh_part_total_bytes:[0x%x]\n", r
->high_part_total_bytes
);
164 printf("\tchange_id:[0x%x]\n", r
->change_id
);
165 printf("\tlast_error: %s\n", win_errstr(r
->last_error
));
166 printf("\tstatus:[0x%x]\n", r
->status
);
167 printf("\tenumerate_network_printers:[0x%x]\n", r
->enumerate_network_printers
);
168 printf("\tc_setprinter:[0x%x]\n", r
->c_setprinter
);
169 printf("\tprocessor_architecture:[0x%x]\n", r
->processor_architecture
);
170 printf("\tprocessor_level:[0x%x]\n", r
->processor_level
);
171 printf("\tref_ic:[0x%x]\n", r
->ref_ic
);
172 printf("\treserved2:[0x%x]\n", r
->reserved2
);
173 printf("\treserved3:[0x%x]\n", r
->reserved3
);
178 /****************************************************************************
179 ****************************************************************************/
181 static void display_print_info1(struct spoolss_PrinterInfo1
*r
)
183 printf("\tflags:[0x%x]\n", r
->flags
);
184 printf("\tname:[%s]\n", r
->name
);
185 printf("\tdescription:[%s]\n", r
->description
);
186 printf("\tcomment:[%s]\n", r
->comment
);
191 /****************************************************************************
192 ****************************************************************************/
194 static void display_print_info2(struct spoolss_PrinterInfo2
*r
)
196 printf("\tservername:[%s]\n", r
->servername
);
197 printf("\tprintername:[%s]\n", r
->printername
);
198 printf("\tsharename:[%s]\n", r
->sharename
);
199 printf("\tportname:[%s]\n", r
->portname
);
200 printf("\tdrivername:[%s]\n", r
->drivername
);
201 printf("\tcomment:[%s]\n", r
->comment
);
202 printf("\tlocation:[%s]\n", r
->location
);
203 printf("\tsepfile:[%s]\n", r
->sepfile
);
204 printf("\tprintprocessor:[%s]\n", r
->printprocessor
);
205 printf("\tdatatype:[%s]\n", r
->datatype
);
206 printf("\tparameters:[%s]\n", r
->parameters
);
207 printf("\tattributes:[0x%x]\n", r
->attributes
);
208 printf("\tpriority:[0x%x]\n", r
->priority
);
209 printf("\tdefaultpriority:[0x%x]\n", r
->defaultpriority
);
210 printf("\tstarttime:[0x%x]\n", r
->starttime
);
211 printf("\tuntiltime:[0x%x]\n", r
->untiltime
);
212 printf("\tstatus:[0x%x]\n", r
->status
);
213 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
214 printf("\taverageppm:[0x%x]\n", r
->averageppm
);
217 display_sec_desc(r
->secdesc
);
222 /****************************************************************************
223 ****************************************************************************/
225 static void display_print_info3(struct spoolss_PrinterInfo3
*r
)
227 display_sec_desc(r
->secdesc
);
232 /****************************************************************************
233 ****************************************************************************/
235 static void display_print_info4(struct spoolss_PrinterInfo4
*r
)
237 printf("\tservername:[%s]\n", r
->servername
);
238 printf("\tprintername:[%s]\n", r
->printername
);
239 printf("\tattributes:[0x%x]\n", r
->attributes
);
243 /****************************************************************************
244 ****************************************************************************/
246 static void display_print_info5(struct spoolss_PrinterInfo5
*r
)
248 printf("\tprintername:[%s]\n", r
->printername
);
249 printf("\tportname:[%s]\n", r
->portname
);
250 printf("\tattributes:[0x%x]\n", r
->attributes
);
251 printf("\tdevice_not_selected_timeout:[0x%x]\n", r
->device_not_selected_timeout
);
252 printf("\ttransmission_retry_timeout:[0x%x]\n", r
->transmission_retry_timeout
);
256 /****************************************************************************
257 ****************************************************************************/
259 static void display_print_info6(struct spoolss_PrinterInfo6
*r
)
261 printf("\tstatus:[0x%x]\n", r
->status
);
265 /****************************************************************************
266 ****************************************************************************/
268 static void display_print_info7(struct spoolss_PrinterInfo7
*r
)
270 printf("\tguid:[%s]\n", r
->guid
);
271 printf("\taction:[0x%x]\n", r
->action
);
275 /****************************************************************************
276 ****************************************************************************/
278 static WERROR
cmd_spoolss_enum_printers(struct rpc_pipe_client
*cli
,
280 int argc
, const char **argv
)
284 union spoolss_PrinterInfo
*info
;
287 uint32_t flags
= PRINTER_ENUM_LOCAL
;
290 printf("Usage: %s [level] [name] [flags]\n", argv
[0]);
295 level
= atoi(argv
[1]);
301 name
= cli
->srv_name_slash
;
305 flags
= atoi(argv
[3]);
308 result
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
315 if (W_ERROR_IS_OK(result
)) {
318 printf ("No printers returned.\n");
322 for (i
= 0; i
< count
; i
++) {
325 display_print_info0(&info
[i
].info0
);
328 display_print_info1(&info
[i
].info1
);
331 display_print_info2(&info
[i
].info2
);
334 display_print_info3(&info
[i
].info3
);
337 display_print_info4(&info
[i
].info4
);
340 display_print_info5(&info
[i
].info5
);
343 display_print_info6(&info
[i
].info6
);
346 printf("unknown info level %d\n", level
);
356 /****************************************************************************
357 ****************************************************************************/
359 static void display_port_info_1(struct spoolss_PortInfo1
*r
)
361 printf("\tPort Name:\t[%s]\n", r
->port_name
);
364 /****************************************************************************
365 ****************************************************************************/
367 static void display_port_info_2(struct spoolss_PortInfo2
*r
)
369 printf("\tPort Name:\t[%s]\n", r
->port_name
);
370 printf("\tMonitor Name:\t[%s]\n", r
->monitor_name
);
371 printf("\tDescription:\t[%s]\n", r
->description
);
372 printf("\tPort Type:\t" );
374 int comma
= 0; /* hack */
376 if (r
->port_type
& SPOOLSS_PORT_TYPE_READ
) {
380 if (r
->port_type
& SPOOLSS_PORT_TYPE_WRITE
) {
381 printf( "%sWrite", comma
? ", " : "" );
384 /* These two have slightly different interpretations
385 on 95/98/ME but I'm disregarding that for now */
386 if (r
->port_type
& SPOOLSS_PORT_TYPE_REDIRECTED
) {
387 printf( "%sRedirected", comma
? ", " : "" );
390 if (r
->port_type
& SPOOLSS_PORT_TYPE_NET_ATTACHED
) {
391 printf( "%sNet-Attached", comma
? ", " : "" );
395 printf( "[Unset]\n" );
397 printf("\tReserved:\t[%d]\n", r
->reserved
);
401 /****************************************************************************
402 ****************************************************************************/
404 static WERROR
cmd_spoolss_enum_ports(struct rpc_pipe_client
*cli
,
405 TALLOC_CTX
*mem_ctx
, int argc
,
411 union spoolss_PortInfo
*info
;
414 printf("Usage: %s [level]\n", argv
[0]);
419 level
= atoi(argv
[1]);
422 /* Enumerate ports */
424 result
= rpccli_spoolss_enumports(cli
, mem_ctx
,
430 if (W_ERROR_IS_OK(result
)) {
433 for (i
= 0; i
< count
; i
++) {
436 display_port_info_1(&info
[i
].info1
);
439 display_port_info_2(&info
[i
].info2
);
442 printf("unknown info level %d\n", level
);
451 /****************************************************************************
452 ****************************************************************************/
454 static WERROR
cmd_spoolss_setprinter(struct rpc_pipe_client
*cli
,
456 int argc
, const char **argv
)
458 struct policy_handle pol
;
461 uint32_t info_level
= 2;
462 union spoolss_PrinterInfo info
;
463 struct spoolss_SetPrinterInfoCtr info_ctr
;
464 const char *printername
, *comment
= NULL
;
465 struct spoolss_DevmodeContainer devmode_ctr
;
466 struct sec_desc_buf secdesc_ctr
;
468 if (argc
== 1 || argc
> 3) {
469 printf("Usage: %s printername comment\n", argv
[0]);
474 /* Open a printer handle */
479 ZERO_STRUCT(devmode_ctr
);
480 ZERO_STRUCT(secdesc_ctr
);
482 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
484 /* get a printer handle */
485 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
489 if (!W_ERROR_IS_OK(result
))
492 /* Get printer info */
493 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
498 if (!W_ERROR_IS_OK(result
))
502 /* Modify the comment. */
503 info
.info2
.comment
= comment
;
504 info
.info2
.secdesc
= NULL
;
505 info
.info2
.devmode
= NULL
;
508 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
510 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
517 if (W_ERROR_IS_OK(result
))
518 printf("Success in setting comment.\n");
521 if (is_valid_policy_hnd(&pol
))
522 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
527 /****************************************************************************
528 ****************************************************************************/
530 static WERROR
cmd_spoolss_setprintername(struct rpc_pipe_client
*cli
,
532 int argc
, const char **argv
)
534 struct policy_handle pol
;
537 uint32_t info_level
= 2;
538 union spoolss_PrinterInfo info
;
539 const char *printername
,
540 *new_printername
= NULL
;
541 struct spoolss_SetPrinterInfoCtr info_ctr
;
542 struct spoolss_DevmodeContainer devmode_ctr
;
543 struct sec_desc_buf secdesc_ctr
;
545 ZERO_STRUCT(devmode_ctr
);
546 ZERO_STRUCT(secdesc_ctr
);
548 if (argc
== 1 || argc
> 3) {
549 printf("Usage: %s printername new_printername\n", argv
[0]);
554 /* Open a printer handle */
556 new_printername
= argv
[2];
559 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
561 /* get a printer handle */
562 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
566 if (!W_ERROR_IS_OK(result
))
569 /* Get printer info */
570 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
575 if (!W_ERROR_IS_OK(result
))
578 /* Modify the printername. */
579 info
.info2
.printername
= new_printername
;
580 info
.info2
.devmode
= NULL
;
581 info
.info2
.secdesc
= NULL
;
583 info_ctr
.level
= info_level
;
584 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
586 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
593 if (W_ERROR_IS_OK(result
))
594 printf("Success in setting printername.\n");
597 if (is_valid_policy_hnd(&pol
))
598 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
603 /****************************************************************************
604 ****************************************************************************/
606 static WERROR
cmd_spoolss_getprinter(struct rpc_pipe_client
*cli
,
608 int argc
, const char **argv
)
610 struct policy_handle pol
;
613 const char *printername
;
614 union spoolss_PrinterInfo info
;
616 if (argc
== 1 || argc
> 3) {
617 printf("Usage: %s <printername> [level]\n", argv
[0]);
621 /* Open a printer handle */
623 level
= atoi(argv
[2]);
626 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
628 /* get a printer handle */
630 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
632 SEC_FLAG_MAXIMUM_ALLOWED
,
634 if (!W_ERROR_IS_OK(result
)) {
638 /* Get printer info */
640 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
645 if (!W_ERROR_IS_OK(result
)) {
649 /* Display printer info */
652 display_print_info0(&info
.info0
);
655 display_print_info1(&info
.info1
);
658 display_print_info2(&info
.info2
);
661 display_print_info3(&info
.info3
);
664 display_print_info4(&info
.info4
);
667 display_print_info5(&info
.info5
);
670 display_print_info6(&info
.info6
);
673 display_print_info7(&info
.info7
);
676 printf("unknown info level %d\n", level
);
680 if (is_valid_policy_hnd(&pol
)) {
681 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
687 /****************************************************************************
688 ****************************************************************************/
690 static void display_reg_value(REGISTRY_VALUE value
)
696 printf("%s: REG_DWORD: 0x%08x\n", value
.valuename
,
697 *((uint32_t *) value
.data_p
));
700 rpcstr_pull_talloc(talloc_tos(),
705 printf("%s: REG_SZ: %s\n", value
.valuename
, text
? text
: "");
708 char *hex
= hex_encode_talloc(NULL
, value
.data_p
, value
.size
);
710 printf("%s: REG_BINARY:", value
.valuename
);
712 for (i
=0; i
<len
; i
++) {
713 if (hex
[i
] == '\0') {
726 uint32_t i
, num_values
;
729 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL
, value
.data_p
,
730 value
.size
, &num_values
,
732 d_printf("reg_pull_multi_sz failed\n");
736 printf("%s: REG_MULTI_SZ: \n", value
.valuename
);
737 for (i
=0; i
<num_values
; i
++) {
738 d_printf("%s\n", values
[i
]);
744 printf("%s: unknown type %d\n", value
.valuename
, value
.type
);
749 /****************************************************************************
750 ****************************************************************************/
752 static void display_printer_data(const char *v
,
753 enum winreg_Type type
,
754 union spoolss_PrinterData
*r
)
760 printf("%s: REG_DWORD: 0x%08x\n", v
, r
->value
);
763 printf("%s: REG_SZ: %s\n", v
, r
->string
);
766 char *hex
= hex_encode_talloc(NULL
,
767 r
->binary
.data
, r
->binary
.length
);
769 printf("%s: REG_BINARY:", v
);
771 for (i
=0; i
<len
; i
++) {
772 if (hex
[i
] == '\0') {
785 printf("%s: REG_MULTI_SZ: ", v
);
786 for (i
=0; r
->string_array
[i
] != NULL
; i
++) {
787 printf("%s ", r
->string_array
[i
]);
792 printf("%s: unknown type 0x%02x:\n", v
, type
);
797 /****************************************************************************
798 ****************************************************************************/
800 static WERROR
cmd_spoolss_getprinterdata(struct rpc_pipe_client
*cli
,
802 int argc
, const char **argv
)
804 struct policy_handle pol
;
807 const char *valuename
;
808 enum winreg_Type type
;
809 union spoolss_PrinterData data
;
812 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
813 printf("<printername> of . queries print server\n");
818 /* Open a printer handle */
820 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
821 fstrcpy(printername
, cli
->srv_name_slash
);
823 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
824 cli
->srv_name_slash
, argv
[1]);
826 /* get a printer handle */
828 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
830 SEC_FLAG_MAXIMUM_ALLOWED
,
832 if (!W_ERROR_IS_OK(result
))
835 /* Get printer info */
837 result
= rpccli_spoolss_getprinterdata(cli
, mem_ctx
,
843 if (!W_ERROR_IS_OK(result
))
846 /* Display printer data */
848 display_printer_data(valuename
, type
, &data
);
851 if (is_valid_policy_hnd(&pol
))
852 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
857 /****************************************************************************
858 ****************************************************************************/
860 static WERROR
cmd_spoolss_getprinterdataex(struct rpc_pipe_client
*cli
,
862 int argc
, const char **argv
)
864 struct policy_handle pol
;
868 const char *valuename
, *keyname
;
869 REGISTRY_VALUE value
;
871 enum winreg_Type type
;
872 uint8_t *buffer
= NULL
;
873 uint32_t offered
= 0;
877 printf("Usage: %s <printername> <keyname> <valuename>\n",
879 printf("<printername> of . queries print server\n");
885 /* Open a printer handle */
887 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
888 fstrcpy(printername
, cli
->srv_name_slash
);
890 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
891 cli
->srv_name_slash
, argv
[1]);
893 /* get a printer handle */
895 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
897 SEC_FLAG_MAXIMUM_ALLOWED
,
899 if (!W_ERROR_IS_OK(result
))
902 /* Get printer info */
904 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
913 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
915 buffer
= talloc_array(mem_ctx
, uint8_t, needed
);
916 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
927 if (!NT_STATUS_IS_OK(status
)) {
931 if (!W_ERROR_IS_OK(result
)) {
936 if (!W_ERROR_IS_OK(result
))
939 /* Display printer data */
941 fstrcpy(value
.valuename
, valuename
);
944 value
.data_p
= buffer
;
946 display_reg_value(value
);
949 if (is_valid_policy_hnd(&pol
))
950 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
955 /****************************************************************************
956 ****************************************************************************/
958 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
964 printf("Printer Driver Info 1:\n");
965 printf("\tDriver Name: [%s]\n", r
->driver_name
);
969 /****************************************************************************
970 ****************************************************************************/
972 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
978 printf("Printer Driver Info 2:\n");
979 printf("\tVersion: [%x]\n", r
->version
);
980 printf("\tDriver Name: [%s]\n", r
->driver_name
);
981 printf("\tArchitecture: [%s]\n", r
->architecture
);
982 printf("\tDriver Path: [%s]\n", r
->driver_path
);
983 printf("\tDatafile: [%s]\n", r
->data_file
);
984 printf("\tConfigfile: [%s]\n", r
->config_file
);
988 /****************************************************************************
989 ****************************************************************************/
991 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
999 printf("Printer Driver Info 3:\n");
1000 printf("\tVersion: [%x]\n", r
->version
);
1001 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1002 printf("\tArchitecture: [%s]\n", r
->architecture
);
1003 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1004 printf("\tDatafile: [%s]\n", r
->data_file
);
1005 printf("\tConfigfile: [%s]\n", r
->config_file
);
1006 printf("\tHelpfile: [%s]\n", r
->help_file
);
1008 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1009 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1012 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1013 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1017 /****************************************************************************
1018 ****************************************************************************/
1020 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1028 printf("Printer Driver Info 4:\n");
1029 printf("\tVersion: [%x]\n", r
->version
);
1030 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1031 printf("\tArchitecture: [%s]\n", r
->architecture
);
1032 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1033 printf("\tDatafile: [%s]\n", r
->data_file
);
1034 printf("\tConfigfile: [%s]\n", r
->config_file
);
1035 printf("\tHelpfile: [%s]\n", r
->help_file
);
1037 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1038 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1041 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1042 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1044 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1045 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1050 /****************************************************************************
1051 ****************************************************************************/
1053 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1059 printf("Printer Driver Info 5:\n");
1060 printf("\tVersion: [%x]\n", r
->version
);
1061 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1062 printf("\tArchitecture: [%s]\n", r
->architecture
);
1063 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1064 printf("\tDatafile: [%s]\n", r
->data_file
);
1065 printf("\tConfigfile: [%s]\n", r
->config_file
);
1066 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1067 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1068 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1072 /****************************************************************************
1073 ****************************************************************************/
1075 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1083 printf("Printer Driver Info 6:\n");
1084 printf("\tVersion: [%x]\n", r
->version
);
1085 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1086 printf("\tArchitecture: [%s]\n", r
->architecture
);
1087 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1088 printf("\tDatafile: [%s]\n", r
->data_file
);
1089 printf("\tConfigfile: [%s]\n", r
->config_file
);
1090 printf("\tHelpfile: [%s]\n", r
->help_file
);
1092 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1093 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1096 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1097 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1099 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1100 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1103 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1104 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1105 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1106 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1107 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1108 printf("\tProvider: [%s]\n", r
->provider
);
1113 /****************************************************************************
1114 ****************************************************************************/
1116 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1124 printf("Printer Driver Info 8:\n");
1125 printf("\tVersion: [%x]\n", r
->version
);
1126 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1127 printf("\tArchitecture: [%s]\n", r
->architecture
);
1128 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1129 printf("\tDatafile: [%s]\n", r
->data_file
);
1130 printf("\tConfigfile: [%s]\n", r
->config_file
);
1131 printf("\tHelpfile: [%s]\n", r
->help_file
);
1132 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1133 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1135 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1136 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1139 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1140 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1143 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1144 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1145 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1146 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1147 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1148 printf("\tProvider: [%s]\n", r
->provider
);
1149 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1150 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1151 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1152 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1154 printf("\tInf Path: [%s]\n", r
->inf_path
);
1155 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1156 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1157 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1159 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1160 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1161 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1166 /****************************************************************************
1167 ****************************************************************************/
1169 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1170 TALLOC_CTX
*mem_ctx
,
1171 int argc
, const char **argv
)
1173 struct policy_handle pol
;
1176 const char *printername
;
1178 bool success
= false;
1179 union spoolss_DriverInfo info
;
1180 uint32_t server_major_version
;
1181 uint32_t server_minor_version
;
1183 if ((argc
== 1) || (argc
> 3)) {
1184 printf("Usage: %s <printername> [level]\n", argv
[0]);
1188 /* get the arguments need to open the printer handle */
1190 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1193 level
= atoi(argv
[2]);
1196 /* Open a printer handle */
1198 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1202 if (!W_ERROR_IS_OK(werror
)) {
1203 printf("Error opening printer handle for %s!\n", printername
);
1207 /* loop through and print driver info level for each architecture */
1209 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1211 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1213 archi_table
[i
].long_archi
,
1216 archi_table
[i
].version
,
1219 &server_major_version
,
1220 &server_minor_version
);
1221 if (!W_ERROR_IS_OK(werror
)) {
1225 /* need at least one success */
1229 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1233 display_print_driver1(&info
.info1
);
1236 display_print_driver2(&info
.info2
);
1239 display_print_driver3(&info
.info3
);
1242 display_print_driver4(&info
.info4
);
1245 display_print_driver5(&info
.info5
);
1248 display_print_driver6(&info
.info6
);
1251 display_print_driver8(&info
.info8
);
1254 printf("unknown info level %d\n", level
);
1261 if (is_valid_policy_hnd(&pol
)) {
1262 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1272 /****************************************************************************
1273 ****************************************************************************/
1275 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1276 TALLOC_CTX
*mem_ctx
,
1277 const char *architecture
,
1282 union spoolss_DriverInfo
*info
= NULL
;
1285 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1286 cli
->srv_name_slash
,
1293 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1294 printf("Server does not support environment [%s]\n",
1303 if (!W_ERROR_IS_OK(werror
)) {
1304 printf("Error getting driver for environment [%s] - %s\n",
1305 architecture
, win_errstr(werror
));
1309 printf("\n[%s]\n", architecture
);
1313 for (j
=0; j
< count
; j
++) {
1314 display_print_driver1(&info
[j
].info1
);
1318 for (j
=0; j
< count
; j
++) {
1319 display_print_driver2(&info
[j
].info2
);
1323 for (j
=0; j
< count
; j
++) {
1324 display_print_driver3(&info
[j
].info3
);
1328 for (j
=0; j
< count
; j
++) {
1329 display_print_driver4(&info
[j
].info4
);
1333 for (j
=0; j
< count
; j
++) {
1334 display_print_driver5(&info
[j
].info5
);
1338 for (j
=0; j
< count
; j
++) {
1339 display_print_driver6(&info
[j
].info6
);
1343 for (j
=0; j
< count
; j
++) {
1344 display_print_driver8(&info
[j
].info8
);
1348 printf("unknown info level %d\n", level
);
1349 return WERR_UNKNOWN_LEVEL
;
1355 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1356 TALLOC_CTX
*mem_ctx
,
1357 int argc
, const char **argv
)
1359 WERROR werror
= WERR_OK
;
1362 const char *architecture
= NULL
;
1365 printf("Usage: enumdrivers [level] [architecture]\n");
1370 level
= atoi(argv
[1]);
1374 architecture
= argv
[2];
1378 return enum_driver_by_architecture(cli
, mem_ctx
,
1383 /* loop through and print driver info level for each architecture */
1384 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1385 /* check to see if we already asked for this architecture string */
1387 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1391 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1392 archi_table
[i
].long_archi
,
1394 if (!W_ERROR_IS_OK(werror
)) {
1402 /****************************************************************************
1403 ****************************************************************************/
1405 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1407 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1410 /****************************************************************************
1411 ****************************************************************************/
1413 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1414 TALLOC_CTX
*mem_ctx
,
1415 int argc
, const char **argv
)
1419 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1422 union spoolss_DriverDirectoryInfo info
;
1426 printf("Usage: %s [environment]\n", argv
[0]);
1430 /* Get the arguments need to open the printer handle */
1436 /* Get the directory. Only use Info level 1 */
1438 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1439 cli
->srv_name_slash
,
1447 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1449 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1451 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1452 cli
->srv_name_slash
,
1462 if (W_ERROR_IS_OK(result
)) {
1463 display_printdriverdir_1(&info
.info1
);
1469 /****************************************************************************
1470 ****************************************************************************/
1472 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1473 struct spoolss_AddDriverInfo3
*info
,
1479 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1481 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1483 info
->version
= archi_table
[i
].version
;
1484 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1489 if (archi_table
[i
].long_archi
== NULL
)
1491 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1498 /**************************************************************************
1499 wrapper for strtok to get the next parameter from a delimited list.
1500 Needed to handle the empty parameter string denoted by "NULL"
1501 *************************************************************************/
1503 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1504 const char *delim
, const char **dest
,
1509 /* get the next token */
1510 ptr
= strtok_r(str
, delim
, saveptr
);
1512 /* a string of 'NULL' is used to represent an empty
1513 parameter because two consecutive delimiters
1514 will not return an empty string. See man strtok(3)
1516 if (ptr
&& (StrCaseCmp(ptr
, "NULL") == 0)) {
1521 *dest
= talloc_strdup(mem_ctx
, ptr
);
1527 /********************************************************************************
1528 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1529 string in the form of
1530 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1531 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1532 <Default Data Type>:<Comma Separated list of Files>
1533 *******************************************************************************/
1535 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1540 char *saveptr
= NULL
;
1541 struct spoolss_StringArray
*deps
;
1542 const char **file_array
= NULL
;
1545 /* fill in the UNISTR fields */
1546 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1547 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1548 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1549 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1550 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1551 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1552 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1554 /* <Comma Separated List of Dependent Files> */
1555 /* save the beginning of the string */
1556 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1559 /* begin to strip out each filename */
1560 str
= strtok_r(str
, ",", &saveptr
);
1562 /* no dependent files, we are done */
1567 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1572 while (str
!= NULL
) {
1573 add_string_to_array(deps
, str
, &file_array
, &count
);
1574 str
= strtok_r(NULL
, ",", &saveptr
);
1577 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1578 if (!deps
->string
) {
1582 for (i
=0; i
< count
; i
++) {
1583 deps
->string
[i
] = file_array
[i
];
1586 r
->dependent_files
= deps
;
1591 /****************************************************************************
1592 ****************************************************************************/
1594 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1595 TALLOC_CTX
*mem_ctx
,
1596 int argc
, const char **argv
)
1601 struct spoolss_AddDriverInfoCtr info_ctr
;
1602 struct spoolss_AddDriverInfo3 info3
;
1606 /* parse the command arguments */
1607 if (argc
!= 3 && argc
!= 4)
1609 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1610 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1611 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1612 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1613 printf ("\t[version]\n");
1618 /* Fill in the spoolss_AddDriverInfo3 struct */
1621 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1623 printf ("Error Unknown architechture [%s]\n", argv
[1]);
1624 return WERR_INVALID_PARAM
;
1627 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1629 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1630 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1632 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1633 return WERR_INVALID_PARAM
;
1636 /* if printer driver version specified, override the default version
1637 * used by the architecture. This allows installation of Windows
1638 * 2000 (version 3) printer drivers. */
1641 info3
.version
= atoi(argv
[3]);
1645 info_ctr
.level
= level
;
1646 info_ctr
.info
.info3
= &info3
;
1648 status
= rpccli_spoolss_AddPrinterDriver(cli
, mem_ctx
,
1649 cli
->srv_name_slash
,
1652 if (!NT_STATUS_IS_OK(status
)) {
1653 return ntstatus_to_werror(status
);
1655 if (W_ERROR_IS_OK(result
)) {
1656 printf ("Printer Driver %s successfully installed.\n",
1664 /****************************************************************************
1665 ****************************************************************************/
1667 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1668 TALLOC_CTX
*mem_ctx
,
1669 int argc
, const char **argv
)
1672 struct spoolss_SetPrinterInfoCtr info_ctr
;
1673 struct spoolss_SetPrinterInfo2 info2
;
1675 /* parse the command arguments */
1678 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1682 /* Fill in the DRIVER_INFO_2 struct */
1685 info2
.printername
= argv
[1];
1686 info2
.drivername
= argv
[3];
1687 info2
.sharename
= argv
[2];
1688 info2
.portname
= argv
[4];
1689 info2
.comment
= "Created by rpcclient";
1690 info2
.printprocessor
= "winprint";
1691 info2
.datatype
= "RAW";
1692 info2
.devmode
= NULL
;
1693 info2
.secdesc
= NULL
;
1694 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1696 info2
.defaultpriority
= 0;
1697 info2
.starttime
= 0;
1698 info2
.untiltime
= 0;
1700 /* These three fields must not be used by AddPrinter()
1701 as defined in the MS Platform SDK documentation..
1705 info2.averageppm = 0;
1709 info_ctr
.info
.info2
= &info2
;
1711 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1713 if (W_ERROR_IS_OK(result
))
1714 printf ("Printer %s successfully installed.\n", argv
[1]);
1719 /****************************************************************************
1720 ****************************************************************************/
1722 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1723 TALLOC_CTX
*mem_ctx
,
1724 int argc
, const char **argv
)
1726 struct policy_handle pol
;
1730 const char *printername
;
1731 union spoolss_PrinterInfo info
;
1732 struct spoolss_SetPrinterInfoCtr info_ctr
;
1733 struct spoolss_DevmodeContainer devmode_ctr
;
1734 struct sec_desc_buf secdesc_ctr
;
1736 ZERO_STRUCT(devmode_ctr
);
1737 ZERO_STRUCT(secdesc_ctr
);
1739 /* parse the command arguments */
1742 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1746 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1748 /* Get a printer handle */
1750 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1754 if (!W_ERROR_IS_OK(result
))
1757 /* Get printer info */
1759 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1764 if (!W_ERROR_IS_OK(result
)) {
1765 printf ("Unable to retrieve printer information!\n");
1769 /* Set the printer driver */
1771 info
.info2
.drivername
= argv
[2];
1772 info
.info2
.devmode
= NULL
;
1773 info
.info2
.secdesc
= NULL
;
1776 info_ctr
.info
.info2
= (struct spoolss_SetPrinterInfo2
*)&info
.info2
;
1778 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
1785 if (!W_ERROR_IS_OK(result
)) {
1786 printf("SetPrinter call failed!\n");
1790 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1795 if (is_valid_policy_hnd(&pol
))
1796 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1802 /****************************************************************************
1803 ****************************************************************************/
1805 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
1806 TALLOC_CTX
*mem_ctx
,
1807 int argc
, const char **argv
)
1809 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
1815 const char *arch
= NULL
;
1816 uint32_t delete_flags
= 0;
1818 /* parse the command arguments */
1819 if (argc
< 2 || argc
> 4) {
1820 printf ("Usage: %s <driver> [arch] [version]\n", argv
[0]);
1827 vers
= atoi (argv
[3]);
1830 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
1833 /* delete the driver for all architectures */
1834 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1836 if (arch
&& !strequal( archi_table
[i
].long_archi
, arch
))
1839 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
1842 /* make the call to remove the driver */
1843 status
= rpccli_spoolss_DeletePrinterDriverEx(cli
, mem_ctx
,
1844 cli
->srv_name_slash
,
1845 archi_table
[i
].long_archi
,
1848 archi_table
[i
].version
,
1851 if ( !W_ERROR_IS_OK(result
) )
1853 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1854 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1855 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
1860 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
1861 archi_table
[i
].long_archi
, archi_table
[i
].version
);
1870 /****************************************************************************
1871 ****************************************************************************/
1873 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
1874 TALLOC_CTX
*mem_ctx
,
1875 int argc
, const char **argv
)
1877 WERROR result
= WERR_OK
;
1881 /* parse the command arguments */
1883 printf ("Usage: %s <driver>\n", argv
[0]);
1887 /* delete the driver for all architectures */
1888 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1889 /* make the call to remove the driver */
1890 status
= rpccli_spoolss_DeletePrinterDriver(cli
, mem_ctx
,
1891 cli
->srv_name_slash
,
1892 archi_table
[i
].long_archi
,
1895 if (!NT_STATUS_IS_OK(status
)) {
1898 if ( !W_ERROR_IS_OK(result
) ) {
1899 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1900 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1901 argv
[1], archi_table
[i
].long_archi
,
1905 printf ("Driver %s removed for arch [%s].\n", argv
[1],
1906 archi_table
[i
].long_archi
);
1913 /****************************************************************************
1914 ****************************************************************************/
1916 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
1917 TALLOC_CTX
*mem_ctx
,
1918 int argc
, const char **argv
)
1922 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
1925 union spoolss_PrintProcessorDirectoryInfo info
;
1928 /* parse the command arguments */
1930 printf ("Usage: %s [environment]\n", argv
[0]);
1935 environment
= argv
[1];
1938 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1939 cli
->srv_name_slash
,
1947 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1949 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1951 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
1952 cli
->srv_name_slash
,
1962 if (W_ERROR_IS_OK(result
)) {
1963 printf("%s\n", info
.info1
.directory_name
);
1969 /****************************************************************************
1970 ****************************************************************************/
1972 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
1973 int argc
, const char **argv
)
1975 struct policy_handle handle
;
1978 const char *printername
;
1979 union spoolss_AddFormInfo info
;
1980 struct spoolss_AddFormInfo1 info1
;
1981 struct spoolss_AddFormInfo2 info2
;
1984 /* Parse the command arguments */
1986 if (argc
< 3 || argc
> 5) {
1987 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
1991 /* Get a printer handle */
1993 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1995 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1999 if (!W_ERROR_IS_OK(werror
))
2002 /* Dummy up some values for the form data */
2005 level
= atoi(argv
[3]);
2010 info1
.flags
= SPOOLSS_FORM_USER
;
2011 info1
.form_name
= argv
[2];
2012 info1
.size
.width
= 100;
2013 info1
.size
.height
= 100;
2014 info1
.area
.left
= 0;
2015 info1
.area
.top
= 10;
2016 info1
.area
.right
= 20;
2017 info1
.area
.bottom
= 30;
2019 info
.info1
= &info1
;
2023 info2
.flags
= SPOOLSS_FORM_USER
;
2024 info2
.form_name
= argv
[2];
2025 info2
.size
.width
= 100;
2026 info2
.size
.height
= 100;
2027 info2
.area
.left
= 0;
2028 info2
.area
.top
= 10;
2029 info2
.area
.right
= 20;
2030 info2
.area
.bottom
= 30;
2031 info2
.keyword
= argv
[2];
2032 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2033 info2
.mui_dll
= NULL
;
2034 info2
.ressource_id
= 0;
2035 info2
.display_name
= argv
[2];
2038 info
.info2
= &info2
;
2046 status
= rpccli_spoolss_AddForm(cli
, mem_ctx
,
2053 if (is_valid_policy_hnd(&handle
))
2054 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2059 /****************************************************************************
2060 ****************************************************************************/
2062 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2063 int argc
, const char **argv
)
2065 struct policy_handle handle
;
2068 const char *printername
;
2069 union spoolss_AddFormInfo info
;
2070 struct spoolss_AddFormInfo1 info1
;
2072 /* Parse the command arguments */
2075 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2079 /* Get a printer handle */
2081 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2083 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2085 SEC_FLAG_MAXIMUM_ALLOWED
,
2087 if (!W_ERROR_IS_OK(werror
))
2090 /* Dummy up some values for the form data */
2092 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2093 info1
.size
.width
= 100;
2094 info1
.size
.height
= 100;
2095 info1
.area
.left
= 0;
2096 info1
.area
.top
= 1000;
2097 info1
.area
.right
= 2000;
2098 info1
.area
.bottom
= 3000;
2099 info1
.form_name
= argv
[2];
2101 info
.info1
= &info1
;
2105 status
= rpccli_spoolss_SetForm(cli
, mem_ctx
,
2113 if (is_valid_policy_hnd(&handle
))
2114 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2119 /****************************************************************************
2120 ****************************************************************************/
2122 static const char *get_form_flag(int form_flag
)
2124 switch (form_flag
) {
2125 case SPOOLSS_FORM_USER
:
2127 case SPOOLSS_FORM_BUILTIN
:
2128 return "FORM_BUILTIN";
2129 case SPOOLSS_FORM_PRINTER
:
2130 return "FORM_PRINTER";
2136 /****************************************************************************
2137 ****************************************************************************/
2139 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2142 "\tflag: %s (%d)\n" \
2143 "\twidth: %d, length: %d\n" \
2144 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2145 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2146 r
->size
.width
, r
->size
.height
,
2147 r
->area
.left
, r
->area
.right
,
2148 r
->area
.top
, r
->area
.bottom
);
2151 /****************************************************************************
2152 ****************************************************************************/
2154 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2157 "\tflag: %s (%d)\n" \
2158 "\twidth: %d, length: %d\n" \
2159 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2160 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2161 r
->size
.width
, r
->size
.height
,
2162 r
->area
.left
, r
->area
.right
,
2163 r
->area
.top
, r
->area
.bottom
);
2164 printf("\tkeyword: %s\n", r
->keyword
);
2165 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2166 printf("\tmui_dll: %s\n", r
->mui_dll
);
2167 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2168 printf("\tdisplay_name: %s\n", r
->display_name
);
2169 printf("\tlang_id: %d\n", r
->lang_id
);
2173 /****************************************************************************
2174 ****************************************************************************/
2176 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2177 int argc
, const char **argv
)
2179 struct policy_handle handle
;
2182 const char *printername
;
2184 uint32_t offered
= 0;
2185 union spoolss_FormInfo info
;
2189 /* Parse the command arguments */
2191 if (argc
< 3 || argc
> 5) {
2192 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2196 /* Get a printer handle */
2198 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2200 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2202 SEC_FLAG_MAXIMUM_ALLOWED
,
2204 if (!W_ERROR_IS_OK(werror
))
2208 level
= atoi(argv
[3]);
2213 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2222 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2223 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2225 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2236 if (!NT_STATUS_IS_OK(status
)) {
2242 display_form_info1(&info
.info1
);
2245 display_form_info2(&info
.info2
);
2250 if (is_valid_policy_hnd(&handle
))
2251 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2256 /****************************************************************************
2257 ****************************************************************************/
2259 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2260 TALLOC_CTX
*mem_ctx
, int argc
,
2263 struct policy_handle handle
;
2266 const char *printername
;
2268 /* Parse the command arguments */
2271 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2275 /* Get a printer handle */
2277 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2279 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2281 SEC_FLAG_MAXIMUM_ALLOWED
,
2283 if (!W_ERROR_IS_OK(werror
))
2286 /* Delete the form */
2288 status
= rpccli_spoolss_DeleteForm(cli
, mem_ctx
,
2292 if (!NT_STATUS_IS_OK(status
)) {
2293 return ntstatus_to_werror(status
);
2297 if (is_valid_policy_hnd(&handle
))
2298 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2303 /****************************************************************************
2304 ****************************************************************************/
2306 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2307 TALLOC_CTX
*mem_ctx
, int argc
,
2310 struct policy_handle handle
;
2312 const char *printername
;
2313 uint32_t num_forms
, level
= 1, i
;
2314 union spoolss_FormInfo
*forms
;
2316 /* Parse the command arguments */
2318 if (argc
< 2 || argc
> 4) {
2319 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2323 /* Get a printer handle */
2325 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2327 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2329 SEC_FLAG_MAXIMUM_ALLOWED
,
2331 if (!W_ERROR_IS_OK(werror
))
2335 level
= atoi(argv
[2]);
2338 /* Enumerate forms */
2340 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2347 if (!W_ERROR_IS_OK(werror
))
2350 /* Display output */
2352 for (i
= 0; i
< num_forms
; i
++) {
2355 display_form_info1(&forms
[i
].info1
);
2358 display_form_info2(&forms
[i
].info2
);
2364 if (is_valid_policy_hnd(&handle
))
2365 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2370 /****************************************************************************
2371 ****************************************************************************/
2373 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2374 TALLOC_CTX
*mem_ctx
,
2375 int argc
, const char **argv
)
2379 const char *printername
;
2380 struct policy_handle pol
;
2381 union spoolss_PrinterInfo info
;
2382 enum winreg_Type type
;
2383 union spoolss_PrinterData data
;
2385 /* parse the command arguments */
2387 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2388 " <value> <data>\n",
2390 result
= WERR_INVALID_PARAM
;
2394 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2398 if (strequal(argv
[2], "string")) {
2402 if (strequal(argv
[2], "binary")) {
2406 if (strequal(argv
[2], "dword")) {
2410 if (strequal(argv
[2], "multistring")) {
2411 type
= REG_MULTI_SZ
;
2414 if (type
== REG_NONE
) {
2415 printf("Unknown data type: %s\n", argv
[2]);
2416 result
= WERR_INVALID_PARAM
;
2420 /* get a printer handle */
2422 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2424 SEC_FLAG_MAXIMUM_ALLOWED
,
2426 if (!W_ERROR_IS_OK(result
)) {
2430 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2435 if (!W_ERROR_IS_OK(result
)) {
2439 printf("%s\n", current_timestring(mem_ctx
, true));
2440 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2442 /* Set the printer data */
2446 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2447 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2450 data
.value
= strtoul(argv
[4], NULL
, 10);
2453 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2455 case REG_MULTI_SZ
: {
2457 const char **strings
= NULL
;
2459 for (i
=4; i
<argc
; i
++) {
2460 if (strcmp(argv
[i
], "NULL") == 0) {
2463 if (!add_string_to_array(mem_ctx
, argv
[i
],
2466 result
= WERR_NOMEM
;
2470 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2471 if (!data
.string_array
) {
2472 result
= WERR_NOMEM
;
2475 for (i
=0; i
< num_strings
; i
++) {
2476 data
.string_array
[i
] = strings
[i
];
2481 printf("Unknown data type: %s\n", argv
[2]);
2482 result
= WERR_INVALID_PARAM
;
2486 status
= rpccli_spoolss_SetPrinterData(cli
, mem_ctx
,
2488 argv
[3], /* value_name */
2491 0, /* autocalculated size */
2493 if (!W_ERROR_IS_OK(result
)) {
2494 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2497 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2499 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2504 if (!W_ERROR_IS_OK(result
)) {
2508 printf("%s\n", current_timestring(mem_ctx
, true));
2509 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2513 if (is_valid_policy_hnd(&pol
)) {
2514 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
2520 /****************************************************************************
2521 ****************************************************************************/
2523 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2525 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2526 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2530 /****************************************************************************
2531 ****************************************************************************/
2533 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2535 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2536 r
->position
, r
->job_id
,
2537 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2538 r
->total_pages
, r
->size
);
2541 /****************************************************************************
2542 ****************************************************************************/
2544 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2546 printf("jobid[%d], next_jobid[%d]\n",
2547 r
->job_id
, r
->next_job_id
);
2550 /****************************************************************************
2551 ****************************************************************************/
2553 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2555 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2556 r
->position
, r
->job_id
,
2557 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2558 r
->total_pages
, r
->size
, r
->size_high
);
2561 /****************************************************************************
2562 ****************************************************************************/
2564 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2565 TALLOC_CTX
*mem_ctx
, int argc
,
2569 uint32_t level
= 1, count
, i
;
2570 const char *printername
;
2571 struct policy_handle hnd
;
2572 union spoolss_JobInfo
*info
;
2574 if (argc
< 2 || argc
> 3) {
2575 printf("Usage: %s printername [level]\n", argv
[0]);
2580 level
= atoi(argv
[2]);
2583 /* Open printer handle */
2585 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2587 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2589 SEC_FLAG_MAXIMUM_ALLOWED
,
2591 if (!W_ERROR_IS_OK(result
))
2594 /* Enumerate ports */
2596 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2604 if (!W_ERROR_IS_OK(result
)) {
2608 for (i
= 0; i
< count
; i
++) {
2611 display_job_info1(&info
[i
].info1
);
2614 display_job_info2(&info
[i
].info2
);
2617 d_printf("unknown info level %d\n", level
);
2623 if (is_valid_policy_hnd(&hnd
)) {
2624 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2630 /****************************************************************************
2631 ****************************************************************************/
2633 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2634 TALLOC_CTX
*mem_ctx
, int argc
,
2638 const char *printername
;
2639 struct policy_handle hnd
;
2642 union spoolss_JobInfo info
;
2644 if (argc
< 3 || argc
> 4) {
2645 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2649 job_id
= atoi(argv
[2]);
2652 level
= atoi(argv
[3]);
2655 /* Open printer handle */
2657 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2659 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2661 SEC_FLAG_MAXIMUM_ALLOWED
,
2663 if (!W_ERROR_IS_OK(result
)) {
2667 /* Enumerate ports */
2669 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2676 if (!W_ERROR_IS_OK(result
)) {
2682 display_job_info1(&info
.info1
);
2685 display_job_info2(&info
.info2
);
2688 display_job_info3(&info
.info3
);
2691 display_job_info4(&info
.info4
);
2694 d_printf("unknown info level %d\n", level
);
2699 if (is_valid_policy_hnd(&hnd
)) {
2700 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2706 /****************************************************************************
2707 ****************************************************************************/
2709 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
2710 TALLOC_CTX
*mem_ctx
, int argc
,
2715 const char *printername
;
2716 struct policy_handle hnd
;
2718 enum spoolss_JobControl command
;
2721 printf("Usage: %s printername job_id command\n", argv
[0]);
2725 job_id
= atoi(argv
[2]);
2726 command
= atoi(argv
[3]);
2728 /* Open printer handle */
2730 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2732 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2734 SEC_FLAG_MAXIMUM_ALLOWED
,
2736 if (!W_ERROR_IS_OK(result
)) {
2742 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
2749 if (!W_ERROR_IS_OK(result
)) {
2754 if (is_valid_policy_hnd(&hnd
)) {
2755 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2761 /****************************************************************************
2762 ****************************************************************************/
2764 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
2765 TALLOC_CTX
*mem_ctx
, int argc
,
2771 const char *printername
;
2772 struct policy_handle hnd
;
2773 uint32_t value_offered
= 0;
2774 const char *value_name
= NULL
;
2775 uint32_t value_needed
;
2776 enum winreg_Type type
;
2777 uint8_t *data
= NULL
;
2778 uint32_t data_offered
= 0;
2779 uint32_t data_needed
;
2782 printf("Usage: %s printername\n", argv
[0]);
2786 /* Open printer handle */
2788 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2790 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2792 SEC_FLAG_MAXIMUM_ALLOWED
,
2794 if (!W_ERROR_IS_OK(result
)) {
2798 /* Enumerate data */
2800 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2812 data_offered
= data_needed
;
2813 value_offered
= value_needed
;
2814 data
= talloc_zero_array(mem_ctx
, uint8_t, data_needed
);
2815 value_name
= talloc_zero_array(mem_ctx
, char, value_needed
);
2817 while (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2819 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2830 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2832 fstrcpy(v
.valuename
, value_name
);
2834 v
.size
= data_offered
;
2836 display_reg_value(v
);
2840 if (W_ERROR_V(result
) == ERRnomoreitems
) {
2841 result
= W_ERROR(ERRsuccess
);
2845 if (is_valid_policy_hnd(&hnd
)) {
2846 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2852 /****************************************************************************
2853 ****************************************************************************/
2855 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
2856 TALLOC_CTX
*mem_ctx
, int argc
,
2861 const char *printername
;
2862 struct policy_handle hnd
;
2864 struct spoolss_PrinterEnumValues
*info
;
2867 printf("Usage: %s printername <keyname>\n", argv
[0]);
2871 /* Open printer handle */
2873 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2875 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2877 SEC_FLAG_MAXIMUM_ALLOWED
,
2879 if (!W_ERROR_IS_OK(result
)) {
2883 /* Enumerate subkeys */
2885 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
2891 if (!W_ERROR_IS_OK(result
)) {
2895 for (i
=0; i
< count
; i
++) {
2896 display_printer_data(info
[i
].value_name
,
2902 if (is_valid_policy_hnd(&hnd
)) {
2903 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2909 /****************************************************************************
2910 ****************************************************************************/
2912 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
2913 TALLOC_CTX
*mem_ctx
, int argc
,
2917 const char *printername
;
2918 const char *keyname
= NULL
;
2919 struct policy_handle hnd
;
2920 const char **key_buffer
= NULL
;
2923 if (argc
< 2 || argc
> 3) {
2924 printf("Usage: %s printername [keyname]\n", argv
[0]);
2934 /* Open printer handle */
2936 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2938 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2940 SEC_FLAG_MAXIMUM_ALLOWED
,
2942 if (!W_ERROR_IS_OK(result
)) {
2946 /* Enumerate subkeys */
2948 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
2954 if (!W_ERROR_IS_OK(result
)) {
2958 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
2959 printf("%s\n", key_buffer
[i
]);
2964 if (is_valid_policy_hnd(&hnd
)) {
2965 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2971 /****************************************************************************
2972 ****************************************************************************/
2974 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
2975 TALLOC_CTX
*mem_ctx
, int argc
,
2978 const char *printername
;
2979 const char *clientname
;
2980 struct policy_handle hnd
;
2983 struct spoolss_NotifyOption option
;
2986 printf("Usage: %s printername\n", argv
[0]);
2993 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2995 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2997 SEC_FLAG_MAXIMUM_ALLOWED
,
2999 if (!W_ERROR_IS_OK(result
)) {
3000 printf("Error opening %s\n", argv
[1]);
3004 /* Create spool options */
3009 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3010 if (option
.types
== NULL
) {
3011 result
= WERR_NOMEM
;
3015 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3016 option
.types
[0].count
= 1;
3017 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3018 if (option
.types
[0].fields
== NULL
) {
3019 result
= WERR_NOMEM
;
3022 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3024 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3025 option
.types
[1].count
= 1;
3026 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3027 if (option
.types
[1].fields
== NULL
) {
3028 result
= WERR_NOMEM
;
3031 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3033 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
3035 result
= WERR_NOMEM
;
3041 status
= rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli
, mem_ctx
,
3049 if (!W_ERROR_IS_OK(result
)) {
3050 printf("Error rffpcnex %s\n", argv
[1]);
3055 if (is_valid_policy_hnd(&hnd
))
3056 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3061 /****************************************************************************
3062 ****************************************************************************/
3064 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3065 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3067 union spoolss_PrinterInfo info1
, info2
;
3069 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3071 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3072 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3077 if ( !W_ERROR_IS_OK(werror
) ) {
3078 printf("failed (%s)\n", win_errstr(werror
));
3079 talloc_destroy(mem_ctx
);
3084 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3085 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3090 if ( !W_ERROR_IS_OK(werror
) ) {
3091 printf("failed (%s)\n", win_errstr(werror
));
3092 talloc_destroy(mem_ctx
);
3097 talloc_destroy(mem_ctx
);
3102 /****************************************************************************
3103 ****************************************************************************/
3105 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3106 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3108 union spoolss_PrinterInfo info1
, info2
;
3110 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3111 SEC_DESC
*sd1
, *sd2
;
3115 printf("Retrieving printer security for %s...", cli1
->desthost
);
3116 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3121 if ( !W_ERROR_IS_OK(werror
) ) {
3122 printf("failed (%s)\n", win_errstr(werror
));
3128 printf("Retrieving printer security for %s...", cli2
->desthost
);
3129 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3134 if ( !W_ERROR_IS_OK(werror
) ) {
3135 printf("failed (%s)\n", win_errstr(werror
));
3144 sd1
= info1
.info3
.secdesc
;
3145 sd2
= info2
.info3
.secdesc
;
3147 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3148 printf("NULL secdesc!\n");
3153 if (!sec_desc_equal( sd1
, sd2
) ) {
3154 printf("Security Descriptors *not* equal!\n");
3159 printf("Security descriptors match\n");
3162 talloc_destroy(mem_ctx
);
3167 /****************************************************************************
3168 ****************************************************************************/
3170 extern struct user_auth_info
*rpcclient_auth_info
;
3172 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3173 TALLOC_CTX
*mem_ctx
, int argc
,
3176 const char *printername
;
3177 char *printername_path
= NULL
;
3178 struct cli_state
*cli_server2
= NULL
;
3179 struct rpc_pipe_client
*cli2
= NULL
;
3180 struct policy_handle hPrinter1
, hPrinter2
;
3185 printf("Usage: %s <printer> <server>\n", argv
[0]);
3189 printername
= argv
[1];
3191 /* first get the connection to the remote server */
3193 nt_status
= cli_full_connection(&cli_server2
, global_myname(), argv
[2],
3196 get_cmdline_auth_info_username(rpcclient_auth_info
),
3198 get_cmdline_auth_info_password(rpcclient_auth_info
),
3199 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info
) ? CLI_FULL_CONNECTION_USE_KERBEROS
: 0,
3200 get_cmdline_auth_info_signing_state(rpcclient_auth_info
), NULL
);
3202 if ( !NT_STATUS_IS_OK(nt_status
) )
3203 return WERR_GENERAL_FAILURE
;
3205 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
.syntax_id
,
3207 if (!NT_STATUS_IS_OK(nt_status
)) {
3208 printf("failed to open spoolss pipe on server %s (%s)\n",
3209 argv
[2], nt_errstr(nt_status
));
3210 return WERR_GENERAL_FAILURE
;
3213 /* now open up both printers */
3215 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3217 printf("Opening %s...", printername_path
);
3219 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3223 if ( !W_ERROR_IS_OK(werror
) ) {
3224 printf("failed (%s)\n", win_errstr(werror
));
3229 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3231 printf("Opening %s...", printername_path
);
3232 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3236 if ( !W_ERROR_IS_OK(werror
) ) {
3237 printf("failed (%s)\n", win_errstr(werror
));
3242 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3243 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3245 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3252 printf("Closing printers...");
3253 rpccli_spoolss_ClosePrinter( cli
, mem_ctx
, &hPrinter1
, NULL
);
3254 rpccli_spoolss_ClosePrinter( cli2
, mem_ctx
, &hPrinter2
, NULL
);
3257 /* close the second remote connection */
3259 cli_shutdown( cli_server2
);
3263 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3265 printf("print_processor_name: %s\n", r
->print_processor_name
);
3268 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3269 TALLOC_CTX
*mem_ctx
, int argc
,
3273 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3274 uint32_t num_procs
, level
= 1, i
;
3275 union spoolss_PrintProcessorInfo
*procs
;
3277 /* Parse the command arguments */
3279 if (argc
< 1 || argc
> 4) {
3280 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3285 environment
= argv
[1];
3289 level
= atoi(argv
[2]);
3292 /* Enumerate Print Processors */
3294 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3295 cli
->srv_name_slash
,
3301 if (!W_ERROR_IS_OK(werror
))
3304 /* Display output */
3306 for (i
= 0; i
< num_procs
; i
++) {
3309 display_proc_info1(&procs
[i
].info1
);
3318 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3320 printf("name_array: %s\n", r
->name_array
);
3323 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3324 TALLOC_CTX
*mem_ctx
, int argc
,
3328 const char *print_processor_name
= "winprint";
3329 uint32_t num_procs
, level
= 1, i
;
3330 union spoolss_PrintProcDataTypesInfo
*procs
;
3332 /* Parse the command arguments */
3334 if (argc
< 1 || argc
> 4) {
3335 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3340 print_processor_name
= argv
[1];
3344 level
= atoi(argv
[2]);
3347 /* Enumerate Print Processor Data Types */
3349 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3350 cli
->srv_name_slash
,
3351 print_processor_name
,
3356 if (!W_ERROR_IS_OK(werror
))
3359 /* Display output */
3361 for (i
= 0; i
< num_procs
; i
++) {
3364 display_proc_data_types_info1(&procs
[i
].info1
);
3373 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3375 printf("monitor_name: %s\n", r
->monitor_name
);
3378 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3380 printf("monitor_name: %s\n", r
->monitor_name
);
3381 printf("environment: %s\n", r
->environment
);
3382 printf("dll_name: %s\n", r
->dll_name
);
3385 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3386 TALLOC_CTX
*mem_ctx
, int argc
,
3390 uint32_t count
, level
= 1, i
;
3391 union spoolss_MonitorInfo
*info
;
3393 /* Parse the command arguments */
3396 printf("Usage: %s [level]\n", argv
[0]);
3401 level
= atoi(argv
[1]);
3404 /* Enumerate Print Monitors */
3406 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3407 cli
->srv_name_slash
,
3412 if (!W_ERROR_IS_OK(werror
)) {
3416 /* Display output */
3418 for (i
= 0; i
< count
; i
++) {
3421 display_monitor1(&info
[i
].info1
);
3424 display_monitor2(&info
[i
].info2
);
3433 /* List of commands exported by this module */
3434 struct cmd_set spoolss_commands
[] = {
3438 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a print driver", "" },
3439 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a printer", "" },
3440 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver", "" },
3441 { "deldriverex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriverex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver with files", "" },
3442 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data", "" },
3443 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data for a key", "" },
3444 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer keys", "" },
3445 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate print jobs", "" },
3446 { "getjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_get_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print job", "" },
3447 { "setjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_set_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set print job", "" },
3448 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer ports", "" },
3449 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate installed printer drivers", "" },
3450 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printers", "" },
3451 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver data", "" },
3452 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer driver data with keyname", ""},
3453 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver information", "" },
3454 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver upload directory", "" },
3455 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer info", "" },
3456 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Open printer handle", "" },
3457 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer driver", "" },
3458 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print processor directory", "" },
3459 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add form", "" },
3460 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set form", "" },
3461 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get form", "" },
3462 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete form", "" },
3463 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate forms", "" },
3464 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer comment", "" },
3465 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printername", "" },
3466 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set REG_SZ printer data", "" },
3467 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Rffpcnex test", "" },
3468 { "printercmp", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_printercmp
, &ndr_table_spoolss
.syntax_id
, NULL
, "Printer comparison test", "" },
3469 { "enumprocs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_procs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processors", "" },
3470 { "enumprocdatatypes", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_proc_data_types
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processor Data Types", "" },
3471 { "enummonitors", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_monitors
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Monitors", "" },