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/ndr_spoolss_c.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
30 #include "nt_printing.h"
31 #include "../libcli/security/display_sec.h"
32 #include "../libcli/security/security_descriptor.h"
33 #include "../libcli/registry/util_reg.h"
34 #include "libsmb/libsmb.h"
36 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
38 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
39 _cli->srv_name_slash, _arg); \
40 W_ERROR_HAVE_NO_MEMORY(_printername); \
43 /* The version int is used by getdrivers. Note that
44 all architecture strings that support mutliple
45 versions must be grouped together since enumdrivers
46 uses this property to prevent issuing multiple
47 enumdriver calls for the same arch */
50 static const struct print_architecture_table_node archi_table
[]= {
52 {"Windows 4.0", "WIN40", 0 },
53 {"Windows NT x86", "W32X86", 2 },
54 {"Windows NT x86", "W32X86", 3 },
55 {"Windows NT R4000", "W32MIPS", 2 },
56 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
57 {"Windows NT PowerPC", "W32PPC", 2 },
58 {"Windows IA64", "IA64", 3 },
59 {"Windows x64", "x64", 3 },
66 * rpcclient module for SPOOLSS rpc pipe.
68 * This generally just parses and checks command lines, and then calls
69 * a cli_spoolss function.
72 /****************************************************************************
73 function to do the mapping between the long architecture name and
75 ****************************************************************************/
77 static const char *cmd_spoolss_get_short_archi(const char *long_archi
)
81 DEBUG(107,("Getting architecture dependent directory\n"));
84 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
85 strcasecmp_m(long_archi
, archi_table
[i
].long_archi
) );
87 if (archi_table
[i
].long_archi
==NULL
) {
88 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
92 /* this might be client code - but shouldn't this be an fstrcpy etc? */
95 DEBUGADD(108,("index: [%d]\n", i
));
96 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
97 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
99 return archi_table
[i
].short_archi
;
102 /****************************************************************************
103 ****************************************************************************/
105 static WERROR
cmd_spoolss_open_printer_ex(struct rpc_pipe_client
*cli
,
107 int argc
, const char **argv
)
110 struct policy_handle hnd
;
111 uint32_t access_mask
= PRINTER_ALL_ACCESS
;
112 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
115 printf("Usage: %s <printername> [access_mask]\n", argv
[0]);
120 sscanf(argv
[2], "%x", &access_mask
);
123 /* Open the printer handle */
125 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
129 if (W_ERROR_IS_OK(werror
)) {
130 printf("Printer %s opened successfully\n", argv
[1]);
131 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &werror
);
133 if (!W_ERROR_IS_OK(werror
)) {
134 printf("Error closing printer handle! (%s)\n",
135 get_dos_error_msg(werror
));
142 /****************************************************************************
143 ****************************************************************************/
145 static WERROR
cmd_spoolss_open_printer(struct rpc_pipe_client
*cli
,
147 int argc
, const char **argv
)
150 struct policy_handle hnd
;
151 uint32_t access_mask
= PRINTER_ALL_ACCESS
;
153 struct spoolss_DevmodeContainer devmode_ctr
;
154 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
156 ZERO_STRUCT(devmode_ctr
);
159 printf("Usage: %s <printername> [access_mask]\n", argv
[0]);
164 sscanf(argv
[2], "%x", &access_mask
);
167 /* Open the printer handle */
169 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
176 if (!NT_STATUS_IS_OK(status
)) {
177 return ntstatus_to_werror(status
);
179 if (W_ERROR_IS_OK(werror
)) {
180 printf("Printer %s opened successfully\n", argv
[1]);
181 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &werror
);
183 if (!W_ERROR_IS_OK(werror
)) {
184 printf("Error closing printer handle! (%s)\n",
185 get_dos_error_msg(werror
));
192 /****************************************************************************
193 ****************************************************************************/
195 static void display_print_info0(struct spoolss_PrinterInfo0
*r
)
200 printf("\tprintername:[%s]\n", r
->printername
);
201 printf("\tservername:[%s]\n", r
->servername
);
202 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
203 printf("\ttotal_jobs:[0x%x]\n", r
->total_jobs
);
204 printf("\ttotal_bytes:[0x%x]\n", r
->total_bytes
);
205 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r
->time
.year
, r
->time
.month
,
206 r
->time
.day
, r
->time
.day_of_week
);
207 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r
->time
.hour
, r
->time
.minute
,
208 r
->time
.second
, r
->time
.millisecond
);
210 printf("\tglobal_counter:[0x%x]\n", r
->global_counter
);
211 printf("\ttotal_pages:[0x%x]\n", r
->total_pages
);
213 printf("\tversion:[0x%x]\n", r
->version
);
214 printf("\tfree_build:[0x%x]\n", r
->free_build
);
215 printf("\tspooling:[0x%x]\n", r
->spooling
);
216 printf("\tmax_spooling:[0x%x]\n", r
->max_spooling
);
217 printf("\tsession_counter:[0x%x]\n", r
->session_counter
);
218 printf("\tnum_error_out_of_paper:[0x%x]\n", r
->num_error_out_of_paper
);
219 printf("\tnum_error_not_ready:[0x%x]\n", r
->num_error_not_ready
);
220 printf("\tjob_error:[0x%x]\n", r
->job_error
);
221 printf("\tnumber_of_processors:[0x%x]\n", r
->number_of_processors
);
222 printf("\tprocessor_type:[0x%x]\n", r
->processor_type
);
223 printf("\thigh_part_total_bytes:[0x%x]\n", r
->high_part_total_bytes
);
224 printf("\tchange_id:[0x%x]\n", r
->change_id
);
225 printf("\tlast_error: %s\n", win_errstr(r
->last_error
));
226 printf("\tstatus:[0x%x]\n", r
->status
);
227 printf("\tenumerate_network_printers:[0x%x]\n", r
->enumerate_network_printers
);
228 printf("\tc_setprinter:[0x%x]\n", r
->c_setprinter
);
229 printf("\tprocessor_architecture:[0x%x]\n", r
->processor_architecture
);
230 printf("\tprocessor_level:[0x%x]\n", r
->processor_level
);
231 printf("\tref_ic:[0x%x]\n", r
->ref_ic
);
232 printf("\treserved2:[0x%x]\n", r
->reserved2
);
233 printf("\treserved3:[0x%x]\n", r
->reserved3
);
238 /****************************************************************************
239 ****************************************************************************/
241 static void display_print_info1(struct spoolss_PrinterInfo1
*r
)
243 printf("\tflags:[0x%x]\n", r
->flags
);
244 printf("\tname:[%s]\n", r
->name
);
245 printf("\tdescription:[%s]\n", r
->description
);
246 printf("\tcomment:[%s]\n", r
->comment
);
251 /****************************************************************************
252 ****************************************************************************/
254 static void display_print_info2(struct spoolss_PrinterInfo2
*r
)
256 printf("\tservername:[%s]\n", r
->servername
);
257 printf("\tprintername:[%s]\n", r
->printername
);
258 printf("\tsharename:[%s]\n", r
->sharename
);
259 printf("\tportname:[%s]\n", r
->portname
);
260 printf("\tdrivername:[%s]\n", r
->drivername
);
261 printf("\tcomment:[%s]\n", r
->comment
);
262 printf("\tlocation:[%s]\n", r
->location
);
263 printf("\tsepfile:[%s]\n", r
->sepfile
);
264 printf("\tprintprocessor:[%s]\n", r
->printprocessor
);
265 printf("\tdatatype:[%s]\n", r
->datatype
);
266 printf("\tparameters:[%s]\n", r
->parameters
);
267 printf("\tattributes:[0x%x]\n", r
->attributes
);
268 printf("\tpriority:[0x%x]\n", r
->priority
);
269 printf("\tdefaultpriority:[0x%x]\n", r
->defaultpriority
);
270 printf("\tstarttime:[0x%x]\n", r
->starttime
);
271 printf("\tuntiltime:[0x%x]\n", r
->untiltime
);
272 printf("\tstatus:[0x%x]\n", r
->status
);
273 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
274 printf("\taverageppm:[0x%x]\n", r
->averageppm
);
277 display_sec_desc(r
->secdesc
);
282 /****************************************************************************
283 ****************************************************************************/
285 static void display_print_info3(struct spoolss_PrinterInfo3
*r
)
287 display_sec_desc(r
->secdesc
);
292 /****************************************************************************
293 ****************************************************************************/
295 static void display_print_info4(struct spoolss_PrinterInfo4
*r
)
297 printf("\tservername:[%s]\n", r
->servername
);
298 printf("\tprintername:[%s]\n", r
->printername
);
299 printf("\tattributes:[0x%x]\n", r
->attributes
);
303 /****************************************************************************
304 ****************************************************************************/
306 static void display_print_info5(struct spoolss_PrinterInfo5
*r
)
308 printf("\tprintername:[%s]\n", r
->printername
);
309 printf("\tportname:[%s]\n", r
->portname
);
310 printf("\tattributes:[0x%x]\n", r
->attributes
);
311 printf("\tdevice_not_selected_timeout:[0x%x]\n", r
->device_not_selected_timeout
);
312 printf("\ttransmission_retry_timeout:[0x%x]\n", r
->transmission_retry_timeout
);
316 /****************************************************************************
317 ****************************************************************************/
319 static void display_print_info6(struct spoolss_PrinterInfo6
*r
)
321 printf("\tstatus:[0x%x]\n", r
->status
);
325 /****************************************************************************
326 ****************************************************************************/
328 static void display_print_info7(struct spoolss_PrinterInfo7
*r
)
330 printf("\tguid:[%s]\n", r
->guid
);
331 printf("\taction:[0x%x]\n", r
->action
);
335 /****************************************************************************
336 ****************************************************************************/
338 static WERROR
cmd_spoolss_enum_printers(struct rpc_pipe_client
*cli
,
340 int argc
, const char **argv
)
344 union spoolss_PrinterInfo
*info
;
347 uint32_t flags
= PRINTER_ENUM_LOCAL
;
350 printf("Usage: %s [level] [name] [flags]\n", argv
[0]);
355 level
= atoi(argv
[1]);
361 name
= cli
->srv_name_slash
;
365 flags
= atoi(argv
[3]);
368 result
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
375 if (W_ERROR_IS_OK(result
)) {
378 printf ("No printers returned.\n");
382 for (i
= 0; i
< count
; i
++) {
385 display_print_info0(&info
[i
].info0
);
388 display_print_info1(&info
[i
].info1
);
391 display_print_info2(&info
[i
].info2
);
394 display_print_info3(&info
[i
].info3
);
397 display_print_info4(&info
[i
].info4
);
400 display_print_info5(&info
[i
].info5
);
403 display_print_info6(&info
[i
].info6
);
406 printf("unknown info level %d\n", level
);
416 /****************************************************************************
417 ****************************************************************************/
419 static void display_port_info_1(struct spoolss_PortInfo1
*r
)
421 printf("\tPort Name:\t[%s]\n", r
->port_name
);
424 /****************************************************************************
425 ****************************************************************************/
427 static void display_port_info_2(struct spoolss_PortInfo2
*r
)
429 printf("\tPort Name:\t[%s]\n", r
->port_name
);
430 printf("\tMonitor Name:\t[%s]\n", r
->monitor_name
);
431 printf("\tDescription:\t[%s]\n", r
->description
);
432 printf("\tPort Type:\t" );
434 int comma
= 0; /* hack */
436 if (r
->port_type
& SPOOLSS_PORT_TYPE_READ
) {
440 if (r
->port_type
& SPOOLSS_PORT_TYPE_WRITE
) {
441 printf( "%sWrite", comma
? ", " : "" );
444 /* These two have slightly different interpretations
445 on 95/98/ME but I'm disregarding that for now */
446 if (r
->port_type
& SPOOLSS_PORT_TYPE_REDIRECTED
) {
447 printf( "%sRedirected", comma
? ", " : "" );
450 if (r
->port_type
& SPOOLSS_PORT_TYPE_NET_ATTACHED
) {
451 printf( "%sNet-Attached", comma
? ", " : "" );
455 printf( "[Unset]\n" );
457 printf("\tReserved:\t[%d]\n", r
->reserved
);
461 /****************************************************************************
462 ****************************************************************************/
464 static WERROR
cmd_spoolss_enum_ports(struct rpc_pipe_client
*cli
,
465 TALLOC_CTX
*mem_ctx
, int argc
,
471 union spoolss_PortInfo
*info
;
474 printf("Usage: %s [level]\n", argv
[0]);
479 level
= atoi(argv
[1]);
482 /* Enumerate ports */
484 result
= rpccli_spoolss_enumports(cli
, mem_ctx
,
490 if (W_ERROR_IS_OK(result
)) {
493 for (i
= 0; i
< count
; i
++) {
496 display_port_info_1(&info
[i
].info1
);
499 display_port_info_2(&info
[i
].info2
);
502 printf("unknown info level %d\n", level
);
511 /****************************************************************************
512 ****************************************************************************/
514 static WERROR
cmd_spoolss_setprinter(struct rpc_pipe_client
*cli
,
516 int argc
, const char **argv
)
518 struct policy_handle pol
;
521 uint32_t info_level
= 2;
522 union spoolss_PrinterInfo info
;
523 struct spoolss_SetPrinterInfoCtr info_ctr
;
524 struct spoolss_SetPrinterInfo2 info2
;
525 const char *printername
, *comment
= NULL
;
526 struct spoolss_DevmodeContainer devmode_ctr
;
527 struct sec_desc_buf secdesc_ctr
;
528 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
530 if (argc
== 1 || argc
> 3) {
531 printf("Usage: %s printername comment\n", argv
[0]);
536 /* Open a printer handle */
541 ZERO_STRUCT(devmode_ctr
);
542 ZERO_STRUCT(secdesc_ctr
);
544 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
546 /* get a printer handle */
547 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
551 if (!W_ERROR_IS_OK(result
))
554 /* Get printer info */
555 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
560 if (!W_ERROR_IS_OK(result
))
564 /* Modify the comment. */
565 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
566 info2
.comment
= comment
;
569 info_ctr
.info
.info2
= &info2
;
571 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
578 if (!NT_STATUS_IS_OK(status
)) {
579 result
= ntstatus_to_werror(status
);
582 if (W_ERROR_IS_OK(result
))
583 printf("Success in setting comment.\n");
586 if (is_valid_policy_hnd(&pol
)) {
588 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
594 /****************************************************************************
595 ****************************************************************************/
597 static WERROR
cmd_spoolss_setprintername(struct rpc_pipe_client
*cli
,
599 int argc
, const char **argv
)
601 struct policy_handle pol
;
604 uint32_t info_level
= 2;
605 union spoolss_PrinterInfo info
;
606 const char *printername
,
607 *new_printername
= NULL
;
608 struct spoolss_SetPrinterInfoCtr info_ctr
;
609 struct spoolss_SetPrinterInfo2 info2
;
610 struct spoolss_DevmodeContainer devmode_ctr
;
611 struct sec_desc_buf secdesc_ctr
;
612 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
614 ZERO_STRUCT(devmode_ctr
);
615 ZERO_STRUCT(secdesc_ctr
);
617 if (argc
== 1 || argc
> 3) {
618 printf("Usage: %s printername new_printername\n", argv
[0]);
623 /* Open a printer handle */
625 new_printername
= argv
[2];
628 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
630 /* get a printer handle */
631 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
635 if (!W_ERROR_IS_OK(result
))
638 /* Get printer info */
639 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
644 if (!W_ERROR_IS_OK(result
))
647 /* Modify the printername. */
648 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
649 info2
.printername
= new_printername
;
652 info_ctr
.info
.info2
= &info2
;
654 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
661 if (!NT_STATUS_IS_OK(status
)) {
662 result
= ntstatus_to_werror(status
);
665 if (W_ERROR_IS_OK(result
))
666 printf("Success in setting printername.\n");
669 if (is_valid_policy_hnd(&pol
)) {
671 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
677 /****************************************************************************
678 ****************************************************************************/
680 static WERROR
cmd_spoolss_getprinter(struct rpc_pipe_client
*cli
,
682 int argc
, const char **argv
)
684 struct policy_handle pol
;
687 const char *printername
;
688 union spoolss_PrinterInfo info
;
689 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
691 if (argc
== 1 || argc
> 3) {
692 printf("Usage: %s <printername> [level]\n", argv
[0]);
696 /* Open a printer handle */
698 level
= atoi(argv
[2]);
701 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
703 /* get a printer handle */
705 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
707 SEC_FLAG_MAXIMUM_ALLOWED
,
709 if (!W_ERROR_IS_OK(result
)) {
713 /* Get printer info */
715 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
720 if (!W_ERROR_IS_OK(result
)) {
724 /* Display printer info */
727 display_print_info0(&info
.info0
);
730 display_print_info1(&info
.info1
);
733 display_print_info2(&info
.info2
);
736 display_print_info3(&info
.info3
);
739 display_print_info4(&info
.info4
);
742 display_print_info5(&info
.info5
);
745 display_print_info6(&info
.info6
);
748 display_print_info7(&info
.info7
);
751 printf("unknown info level %d\n", level
);
755 if (is_valid_policy_hnd(&pol
)) {
757 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
763 /****************************************************************************
764 ****************************************************************************/
766 static void display_reg_value(const char *name
, enum winreg_Type type
, DATA_BLOB blob
)
768 const char *text
= NULL
;
772 if (blob
.length
== sizeof(uint32
)) {
773 printf("%s: REG_DWORD: 0x%08x\n", name
, IVAL(blob
.data
,0));
775 printf("%s: REG_DWORD: <invalid>\n", name
);
779 pull_reg_sz(talloc_tos(), &blob
, &text
);
780 printf("%s: REG_SZ: %s\n", name
, text
? text
: "");
783 char *hex
= hex_encode_talloc(NULL
, blob
.data
, blob
.length
);
785 printf("%s: REG_BINARY:", name
);
787 for (i
=0; i
<len
; i
++) {
788 if (hex
[i
] == '\0') {
804 if (!pull_reg_multi_sz(NULL
, &blob
, &values
)) {
805 d_printf("pull_reg_multi_sz failed\n");
809 printf("%s: REG_MULTI_SZ: \n", name
);
810 for (i
=0; values
[i
] != NULL
; i
++) {
811 d_printf("%s\n", values
[i
]);
817 printf("%s: unknown type %d\n", name
, type
);
822 /****************************************************************************
823 ****************************************************************************/
825 static void display_printer_data(const char *v
,
826 enum winreg_Type type
,
831 union spoolss_PrinterData r
;
832 DATA_BLOB blob
= data_blob_const(data
, length
);
835 result
= pull_spoolss_PrinterData(talloc_tos(), &blob
, &r
, type
);
836 if (!W_ERROR_IS_OK(result
)) {
842 printf("%s: REG_DWORD: 0x%08x\n", v
, r
.value
);
845 printf("%s: REG_SZ: %s\n", v
, r
.string
);
848 char *hex
= hex_encode_talloc(NULL
,
849 r
.binary
.data
, r
.binary
.length
);
851 printf("%s: REG_BINARY:", v
);
853 for (i
=0; i
<len
; i
++) {
854 if (hex
[i
] == '\0') {
867 printf("%s: REG_MULTI_SZ: ", v
);
868 for (i
=0; r
.string_array
[i
] != NULL
; i
++) {
869 printf("%s ", r
.string_array
[i
]);
874 printf("%s: unknown type 0x%02x:\n", v
, type
);
879 /****************************************************************************
880 ****************************************************************************/
882 static WERROR
cmd_spoolss_getprinterdata(struct rpc_pipe_client
*cli
,
884 int argc
, const char **argv
)
886 struct policy_handle pol
;
889 const char *valuename
;
890 enum winreg_Type type
;
893 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
896 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
897 printf("<printername> of . queries print server\n");
902 /* Open a printer handle */
904 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
905 fstrcpy(printername
, cli
->srv_name_slash
);
907 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
908 cli
->srv_name_slash
, argv
[1]);
910 /* get a printer handle */
912 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
914 SEC_FLAG_MAXIMUM_ALLOWED
,
916 if (!W_ERROR_IS_OK(result
))
919 /* Get printer info */
921 result
= rpccli_spoolss_getprinterdata(cli
, mem_ctx
,
928 if (!W_ERROR_IS_OK(result
))
931 /* Display printer data */
933 display_printer_data(valuename
, type
, data
, needed
);
936 if (is_valid_policy_hnd(&pol
)) {
938 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
944 /****************************************************************************
945 ****************************************************************************/
947 static WERROR
cmd_spoolss_getprinterdataex(struct rpc_pipe_client
*cli
,
949 int argc
, const char **argv
)
951 struct policy_handle pol
;
955 const char *valuename
, *keyname
;
957 enum winreg_Type type
;
958 uint8_t *data
= NULL
;
959 uint32_t offered
= 0;
961 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
964 printf("Usage: %s <printername> <keyname> <valuename>\n",
966 printf("<printername> of . queries print server\n");
972 /* Open a printer handle */
974 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
975 fstrcpy(printername
, cli
->srv_name_slash
);
977 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
978 cli
->srv_name_slash
, argv
[1]);
980 /* get a printer handle */
982 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
984 SEC_FLAG_MAXIMUM_ALLOWED
,
986 if (!W_ERROR_IS_OK(result
))
989 /* Get printer info */
991 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
996 status
= dcerpc_spoolss_GetPrinterDataEx(b
, mem_ctx
,
1005 if (!NT_STATUS_IS_OK(status
)) {
1006 result
= ntstatus_to_werror(status
);
1009 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
1011 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
1015 status
= dcerpc_spoolss_GetPrinterDataEx(b
, mem_ctx
,
1026 if (!NT_STATUS_IS_OK(status
)) {
1027 result
= ntstatus_to_werror(status
);
1031 if (!W_ERROR_IS_OK(result
))
1034 /* Display printer data */
1036 display_printer_data(valuename
, type
, data
, needed
);
1040 if (is_valid_policy_hnd(&pol
)) {
1042 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
1048 /****************************************************************************
1049 ****************************************************************************/
1051 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
1057 printf("Printer Driver Info 1:\n");
1058 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1062 /****************************************************************************
1063 ****************************************************************************/
1065 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
1071 printf("Printer Driver Info 2:\n");
1072 printf("\tVersion: [%x]\n", r
->version
);
1073 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1074 printf("\tArchitecture: [%s]\n", r
->architecture
);
1075 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1076 printf("\tDatafile: [%s]\n", r
->data_file
);
1077 printf("\tConfigfile: [%s]\n", r
->config_file
);
1081 /****************************************************************************
1082 ****************************************************************************/
1084 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
1092 printf("Printer Driver Info 3:\n");
1093 printf("\tVersion: [%x]\n", r
->version
);
1094 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1095 printf("\tArchitecture: [%s]\n", r
->architecture
);
1096 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1097 printf("\tDatafile: [%s]\n", r
->data_file
);
1098 printf("\tConfigfile: [%s]\n", r
->config_file
);
1099 printf("\tHelpfile: [%s]\n", r
->help_file
);
1101 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1102 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1105 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1106 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1110 /****************************************************************************
1111 ****************************************************************************/
1113 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1121 printf("Printer Driver Info 4:\n");
1122 printf("\tVersion: [%x]\n", r
->version
);
1123 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1124 printf("\tArchitecture: [%s]\n", r
->architecture
);
1125 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1126 printf("\tDatafile: [%s]\n", r
->data_file
);
1127 printf("\tConfigfile: [%s]\n", r
->config_file
);
1128 printf("\tHelpfile: [%s]\n", r
->help_file
);
1130 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1131 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1134 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1135 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1137 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1138 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1143 /****************************************************************************
1144 ****************************************************************************/
1146 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1152 printf("Printer Driver Info 5:\n");
1153 printf("\tVersion: [%x]\n", r
->version
);
1154 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1155 printf("\tArchitecture: [%s]\n", r
->architecture
);
1156 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1157 printf("\tDatafile: [%s]\n", r
->data_file
);
1158 printf("\tConfigfile: [%s]\n", r
->config_file
);
1159 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1160 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1161 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1165 /****************************************************************************
1166 ****************************************************************************/
1168 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1176 printf("Printer Driver Info 6:\n");
1177 printf("\tVersion: [%x]\n", r
->version
);
1178 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1179 printf("\tArchitecture: [%s]\n", r
->architecture
);
1180 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1181 printf("\tDatafile: [%s]\n", r
->data_file
);
1182 printf("\tConfigfile: [%s]\n", r
->config_file
);
1183 printf("\tHelpfile: [%s]\n", r
->help_file
);
1185 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1186 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1189 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1190 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1192 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1193 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1196 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1197 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1198 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1199 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1200 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1201 printf("\tProvider: [%s]\n", r
->provider
);
1206 /****************************************************************************
1207 ****************************************************************************/
1209 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1217 printf("Printer Driver Info 8:\n");
1218 printf("\tVersion: [%x]\n", r
->version
);
1219 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1220 printf("\tArchitecture: [%s]\n", r
->architecture
);
1221 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1222 printf("\tDatafile: [%s]\n", r
->data_file
);
1223 printf("\tConfigfile: [%s]\n", r
->config_file
);
1224 printf("\tHelpfile: [%s]\n", r
->help_file
);
1225 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1226 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1228 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1229 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1232 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1233 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1236 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1237 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1238 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1239 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1240 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1241 printf("\tProvider: [%s]\n", r
->provider
);
1242 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1243 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1244 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1245 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1247 printf("\tInf Path: [%s]\n", r
->inf_path
);
1248 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1249 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1250 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1252 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1253 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1254 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1259 /****************************************************************************
1260 ****************************************************************************/
1262 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1263 TALLOC_CTX
*mem_ctx
,
1264 int argc
, const char **argv
)
1266 struct policy_handle pol
;
1269 const char *printername
;
1271 bool success
= false;
1272 union spoolss_DriverInfo info
;
1273 uint32_t server_major_version
;
1274 uint32_t server_minor_version
;
1275 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1277 if ((argc
== 1) || (argc
> 3)) {
1278 printf("Usage: %s <printername> [level]\n", argv
[0]);
1282 /* get the arguments need to open the printer handle */
1284 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1287 level
= atoi(argv
[2]);
1290 /* Open a printer handle */
1292 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1296 if (!W_ERROR_IS_OK(werror
)) {
1297 printf("Error opening printer handle for %s!\n", printername
);
1301 /* loop through and print driver info level for each architecture */
1303 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1305 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1307 archi_table
[i
].long_archi
,
1310 archi_table
[i
].version
,
1313 &server_major_version
,
1314 &server_minor_version
);
1315 if (!W_ERROR_IS_OK(werror
)) {
1319 /* need at least one success */
1323 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1327 display_print_driver1(&info
.info1
);
1330 display_print_driver2(&info
.info2
);
1333 display_print_driver3(&info
.info3
);
1336 display_print_driver4(&info
.info4
);
1339 display_print_driver5(&info
.info5
);
1342 display_print_driver6(&info
.info6
);
1345 display_print_driver8(&info
.info8
);
1348 printf("unknown info level %d\n", level
);
1355 if (is_valid_policy_hnd(&pol
)) {
1357 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
1367 /****************************************************************************
1368 ****************************************************************************/
1370 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1371 TALLOC_CTX
*mem_ctx
,
1372 const char *architecture
,
1377 union spoolss_DriverInfo
*info
= NULL
;
1380 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1381 cli
->srv_name_slash
,
1388 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1389 printf("Server does not support environment [%s]\n",
1398 if (!W_ERROR_IS_OK(werror
)) {
1399 printf("Error getting driver for environment [%s] - %s\n",
1400 architecture
, win_errstr(werror
));
1404 printf("\n[%s]\n", architecture
);
1408 for (j
=0; j
< count
; j
++) {
1409 display_print_driver1(&info
[j
].info1
);
1413 for (j
=0; j
< count
; j
++) {
1414 display_print_driver2(&info
[j
].info2
);
1418 for (j
=0; j
< count
; j
++) {
1419 display_print_driver3(&info
[j
].info3
);
1423 for (j
=0; j
< count
; j
++) {
1424 display_print_driver4(&info
[j
].info4
);
1428 for (j
=0; j
< count
; j
++) {
1429 display_print_driver5(&info
[j
].info5
);
1433 for (j
=0; j
< count
; j
++) {
1434 display_print_driver6(&info
[j
].info6
);
1438 for (j
=0; j
< count
; j
++) {
1439 display_print_driver8(&info
[j
].info8
);
1443 printf("unknown info level %d\n", level
);
1444 return WERR_UNKNOWN_LEVEL
;
1450 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1451 TALLOC_CTX
*mem_ctx
,
1452 int argc
, const char **argv
)
1454 WERROR werror
= WERR_OK
;
1457 const char *architecture
= NULL
;
1460 printf("Usage: enumdrivers [level] [architecture]\n");
1465 level
= atoi(argv
[1]);
1469 architecture
= argv
[2];
1473 return enum_driver_by_architecture(cli
, mem_ctx
,
1478 /* loop through and print driver info level for each architecture */
1479 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1480 /* check to see if we already asked for this architecture string */
1482 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1486 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1487 archi_table
[i
].long_archi
,
1489 if (!W_ERROR_IS_OK(werror
)) {
1497 /****************************************************************************
1498 ****************************************************************************/
1500 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1502 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1505 /****************************************************************************
1506 ****************************************************************************/
1508 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1509 TALLOC_CTX
*mem_ctx
,
1510 int argc
, const char **argv
)
1514 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1517 union spoolss_DriverDirectoryInfo info
;
1519 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1522 printf("Usage: %s [environment]\n", argv
[0]);
1526 /* Get the arguments need to open the printer handle */
1532 /* Get the directory. Only use Info level 1 */
1534 status
= dcerpc_spoolss_GetPrinterDriverDirectory(b
, mem_ctx
,
1535 cli
->srv_name_slash
,
1543 if (!NT_STATUS_IS_OK(status
)) {
1544 return ntstatus_to_werror(status
);
1546 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1548 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1550 status
= dcerpc_spoolss_GetPrinterDriverDirectory(b
, mem_ctx
,
1551 cli
->srv_name_slash
,
1559 if (!NT_STATUS_IS_OK(status
)) {
1560 return ntstatus_to_werror(status
);
1564 if (W_ERROR_IS_OK(result
)) {
1565 display_printdriverdir_1(&info
.info1
);
1571 /****************************************************************************
1572 ****************************************************************************/
1574 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1575 struct spoolss_AddDriverInfo3
*info
,
1581 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1583 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1585 info
->version
= archi_table
[i
].version
;
1586 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1591 if (archi_table
[i
].long_archi
== NULL
)
1593 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1600 /**************************************************************************
1601 wrapper for strtok to get the next parameter from a delimited list.
1602 Needed to handle the empty parameter string denoted by "NULL"
1603 *************************************************************************/
1605 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1606 const char *delim
, const char **dest
,
1611 /* get the next token */
1612 ptr
= strtok_r(str
, delim
, saveptr
);
1614 /* a string of 'NULL' is used to represent an empty
1615 parameter because two consecutive delimiters
1616 will not return an empty string. See man strtok(3)
1618 if (ptr
&& (strcasecmp_m(ptr
, "NULL") == 0)) {
1623 *dest
= talloc_strdup(mem_ctx
, ptr
);
1629 /********************************************************************************
1630 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1631 string in the form of
1632 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1633 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1634 <Default Data Type>:<Comma Separated list of Files>
1635 *******************************************************************************/
1637 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1642 char *saveptr
= NULL
;
1643 struct spoolss_StringArray
*deps
;
1644 const char **file_array
= NULL
;
1647 /* fill in the UNISTR fields */
1648 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1649 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1650 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1651 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1652 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1653 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1654 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1656 /* <Comma Separated List of Dependent Files> */
1657 /* save the beginning of the string */
1658 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1661 /* begin to strip out each filename */
1662 str
= strtok_r(str
, ",", &saveptr
);
1664 /* no dependent files, we are done */
1669 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1674 while (str
!= NULL
) {
1675 add_string_to_array(deps
, str
, &file_array
, &count
);
1676 str
= strtok_r(NULL
, ",", &saveptr
);
1679 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1680 if (!deps
->string
) {
1684 for (i
=0; i
< count
; i
++) {
1685 deps
->string
[i
] = file_array
[i
];
1688 r
->dependent_files
= deps
;
1693 /****************************************************************************
1694 ****************************************************************************/
1696 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1697 TALLOC_CTX
*mem_ctx
,
1698 int argc
, const char **argv
)
1703 struct spoolss_AddDriverInfoCtr info_ctr
;
1704 struct spoolss_AddDriverInfo3 info3
;
1707 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1709 /* parse the command arguments */
1710 if (argc
!= 3 && argc
!= 4)
1712 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1713 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1714 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1715 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1716 printf ("\t[version]\n");
1721 /* Fill in the spoolss_AddDriverInfo3 struct */
1724 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1726 printf ("Error Unknown architecture [%s]\n", argv
[1]);
1727 return WERR_INVALID_PARAM
;
1730 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1732 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1733 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1735 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1736 return WERR_INVALID_PARAM
;
1739 /* if printer driver version specified, override the default version
1740 * used by the architecture. This allows installation of Windows
1741 * 2000 (version 3) printer drivers. */
1744 info3
.version
= atoi(argv
[3]);
1748 info_ctr
.level
= level
;
1749 info_ctr
.info
.info3
= &info3
;
1751 status
= dcerpc_spoolss_AddPrinterDriver(b
, mem_ctx
,
1752 cli
->srv_name_slash
,
1755 if (!NT_STATUS_IS_OK(status
)) {
1756 return ntstatus_to_werror(status
);
1758 if (W_ERROR_IS_OK(result
)) {
1759 printf ("Printer Driver %s successfully installed.\n",
1767 /****************************************************************************
1768 ****************************************************************************/
1770 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1771 TALLOC_CTX
*mem_ctx
,
1772 int argc
, const char **argv
)
1775 struct spoolss_SetPrinterInfoCtr info_ctr
;
1776 struct spoolss_SetPrinterInfo2 info2
;
1778 /* parse the command arguments */
1781 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1785 /* Fill in the DRIVER_INFO_2 struct */
1788 info2
.printername
= argv
[1];
1789 info2
.drivername
= argv
[3];
1790 info2
.sharename
= argv
[2];
1791 info2
.portname
= argv
[4];
1792 info2
.comment
= "Created by rpcclient";
1793 info2
.printprocessor
= "winprint";
1794 info2
.datatype
= "RAW";
1795 info2
.devmode_ptr
= 0;
1796 info2
.secdesc_ptr
= 0;
1797 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1799 info2
.defaultpriority
= 0;
1800 info2
.starttime
= 0;
1801 info2
.untiltime
= 0;
1803 /* These three fields must not be used by AddPrinter()
1804 as defined in the MS Platform SDK documentation..
1808 info2.averageppm = 0;
1812 info_ctr
.info
.info2
= &info2
;
1814 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1816 if (W_ERROR_IS_OK(result
))
1817 printf ("Printer %s successfully installed.\n", argv
[1]);
1822 /****************************************************************************
1823 ****************************************************************************/
1825 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1826 TALLOC_CTX
*mem_ctx
,
1827 int argc
, const char **argv
)
1829 struct policy_handle pol
;
1833 const char *printername
;
1834 union spoolss_PrinterInfo info
;
1835 struct spoolss_SetPrinterInfoCtr info_ctr
;
1836 struct spoolss_SetPrinterInfo2 info2
;
1837 struct spoolss_DevmodeContainer devmode_ctr
;
1838 struct sec_desc_buf secdesc_ctr
;
1839 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1841 ZERO_STRUCT(devmode_ctr
);
1842 ZERO_STRUCT(secdesc_ctr
);
1844 /* parse the command arguments */
1847 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1851 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1853 /* Get a printer handle */
1855 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1859 if (!W_ERROR_IS_OK(result
))
1862 /* Get printer info */
1864 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1869 if (!W_ERROR_IS_OK(result
)) {
1870 printf ("Unable to retrieve printer information!\n");
1874 /* Set the printer driver */
1876 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
1877 info2
.drivername
= argv
[2];
1880 info_ctr
.info
.info2
= &info2
;
1882 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
1889 if (!NT_STATUS_IS_OK(status
)) {
1890 result
= ntstatus_to_werror(status
);
1893 if (!W_ERROR_IS_OK(result
)) {
1894 printf("SetPrinter call failed!\n");
1898 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1903 if (is_valid_policy_hnd(&pol
)) {
1905 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
1912 /****************************************************************************
1913 ****************************************************************************/
1915 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
1916 TALLOC_CTX
*mem_ctx
,
1917 int argc
, const char **argv
)
1919 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
1921 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1926 const char *arch
= NULL
;
1927 uint32_t delete_flags
= 0;
1929 /* parse the command arguments */
1930 if (argc
< 2 || argc
> 5) {
1931 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv
[0]);
1938 vers
= atoi(argv
[3]);
1939 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
1942 delete_flags
= atoi(argv
[4]);
1944 /* delete the driver for all architectures */
1945 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1947 if (arch
&& !strequal(archi_table
[i
].long_archi
, arch
))
1950 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
1953 /* make the call to remove the driver */
1954 status
= dcerpc_spoolss_DeletePrinterDriverEx(b
, mem_ctx
,
1955 cli
->srv_name_slash
,
1956 archi_table
[i
].long_archi
,
1959 archi_table
[i
].version
,
1961 if (!NT_STATUS_IS_OK(status
)) {
1962 return ntstatus_to_werror(status
);
1964 if ( !W_ERROR_IS_OK(result
) )
1966 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1967 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1968 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
1973 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
1974 archi_table
[i
].long_archi
, archi_table
[i
].version
);
1983 /****************************************************************************
1984 ****************************************************************************/
1986 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
1987 TALLOC_CTX
*mem_ctx
,
1988 int argc
, const char **argv
)
1990 WERROR result
= WERR_OK
;
1993 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1995 /* parse the command arguments */
1997 printf ("Usage: %s <driver>\n", argv
[0]);
2001 /* delete the driver for all architectures */
2002 for (i
=0; archi_table
[i
].long_archi
; i
++) {
2005 /* make the call to remove the driver */
2006 status
= dcerpc_spoolss_DeletePrinterDriver(b
, mem_ctx
,
2007 cli
->srv_name_slash
,
2008 archi_table
[i
].long_archi
,
2011 if (!NT_STATUS_IS_OK(status
)) {
2012 result
= ntstatus_to_werror(status
);
2015 if ( !W_ERROR_IS_OK(result
) ) {
2016 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
2017 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2018 argv
[1], archi_table
[i
].long_archi
,
2019 win_errstr(result
));
2022 printf ("Driver %s removed for arch [%s].\n", argv
[1],
2023 archi_table
[i
].long_archi
);
2030 /****************************************************************************
2031 ****************************************************************************/
2033 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
2034 TALLOC_CTX
*mem_ctx
,
2035 int argc
, const char **argv
)
2039 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
2042 union spoolss_PrintProcessorDirectoryInfo info
;
2044 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2046 /* parse the command arguments */
2048 printf ("Usage: %s [environment]\n", argv
[0]);
2053 environment
= argv
[1];
2056 status
= dcerpc_spoolss_GetPrintProcessorDirectory(b
, mem_ctx
,
2057 cli
->srv_name_slash
,
2065 if (!NT_STATUS_IS_OK(status
)) {
2066 return ntstatus_to_werror(status
);
2068 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
2070 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2072 status
= dcerpc_spoolss_GetPrintProcessorDirectory(b
, mem_ctx
,
2073 cli
->srv_name_slash
,
2081 if (!NT_STATUS_IS_OK(status
)) {
2082 return ntstatus_to_werror(status
);
2086 if (W_ERROR_IS_OK(result
)) {
2087 printf("%s\n", info
.info1
.directory_name
);
2093 /****************************************************************************
2094 ****************************************************************************/
2096 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2097 int argc
, const char **argv
)
2099 struct policy_handle handle
;
2102 const char *printername
;
2103 union spoolss_AddFormInfo info
;
2104 struct spoolss_AddFormInfo1 info1
;
2105 struct spoolss_AddFormInfo2 info2
;
2107 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2109 /* Parse the command arguments */
2111 if (argc
< 3 || argc
> 5) {
2112 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2116 /* Get a printer handle */
2118 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2120 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2124 if (!W_ERROR_IS_OK(werror
))
2127 /* Dummy up some values for the form data */
2130 level
= atoi(argv
[3]);
2135 info1
.flags
= SPOOLSS_FORM_USER
;
2136 info1
.form_name
= argv
[2];
2137 info1
.size
.width
= 100;
2138 info1
.size
.height
= 100;
2139 info1
.area
.left
= 0;
2140 info1
.area
.top
= 10;
2141 info1
.area
.right
= 20;
2142 info1
.area
.bottom
= 30;
2144 info
.info1
= &info1
;
2148 info2
.flags
= SPOOLSS_FORM_USER
;
2149 info2
.form_name
= argv
[2];
2150 info2
.size
.width
= 100;
2151 info2
.size
.height
= 100;
2152 info2
.area
.left
= 0;
2153 info2
.area
.top
= 10;
2154 info2
.area
.right
= 20;
2155 info2
.area
.bottom
= 30;
2156 info2
.keyword
= argv
[2];
2157 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2158 info2
.mui_dll
= NULL
;
2159 info2
.ressource_id
= 0;
2160 info2
.display_name
= argv
[2];
2163 info
.info2
= &info2
;
2167 werror
= WERR_INVALID_PARAM
;
2174 status
= dcerpc_spoolss_AddForm(b
, mem_ctx
,
2179 if (!NT_STATUS_IS_OK(status
)) {
2180 werror
= ntstatus_to_werror(status
);
2184 if (is_valid_policy_hnd(&handle
)) {
2186 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2192 /****************************************************************************
2193 ****************************************************************************/
2195 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2196 int argc
, const char **argv
)
2198 struct policy_handle handle
;
2201 const char *printername
;
2202 union spoolss_AddFormInfo info
;
2203 struct spoolss_AddFormInfo1 info1
;
2204 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2206 /* Parse the command arguments */
2209 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2213 /* Get a printer handle */
2215 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2217 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2219 SEC_FLAG_MAXIMUM_ALLOWED
,
2221 if (!W_ERROR_IS_OK(werror
))
2224 /* Dummy up some values for the form data */
2226 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2227 info1
.size
.width
= 100;
2228 info1
.size
.height
= 100;
2229 info1
.area
.left
= 0;
2230 info1
.area
.top
= 1000;
2231 info1
.area
.right
= 2000;
2232 info1
.area
.bottom
= 3000;
2233 info1
.form_name
= argv
[2];
2235 info
.info1
= &info1
;
2239 status
= dcerpc_spoolss_SetForm(b
, mem_ctx
,
2245 if (!NT_STATUS_IS_OK(status
)) {
2246 werror
= ntstatus_to_werror(status
);
2250 if (is_valid_policy_hnd(&handle
)) {
2252 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2258 /****************************************************************************
2259 ****************************************************************************/
2261 static const char *get_form_flag(int form_flag
)
2263 switch (form_flag
) {
2264 case SPOOLSS_FORM_USER
:
2266 case SPOOLSS_FORM_BUILTIN
:
2267 return "FORM_BUILTIN";
2268 case SPOOLSS_FORM_PRINTER
:
2269 return "FORM_PRINTER";
2275 /****************************************************************************
2276 ****************************************************************************/
2278 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2281 "\tflag: %s (%d)\n" \
2282 "\twidth: %d, length: %d\n" \
2283 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2284 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2285 r
->size
.width
, r
->size
.height
,
2286 r
->area
.left
, r
->area
.right
,
2287 r
->area
.top
, r
->area
.bottom
);
2290 /****************************************************************************
2291 ****************************************************************************/
2293 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2296 "\tflag: %s (%d)\n" \
2297 "\twidth: %d, length: %d\n" \
2298 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2299 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2300 r
->size
.width
, r
->size
.height
,
2301 r
->area
.left
, r
->area
.right
,
2302 r
->area
.top
, r
->area
.bottom
);
2303 printf("\tkeyword: %s\n", r
->keyword
);
2304 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2305 printf("\tmui_dll: %s\n", r
->mui_dll
);
2306 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2307 printf("\tdisplay_name: %s\n", r
->display_name
);
2308 printf("\tlang_id: %d\n", r
->lang_id
);
2312 /****************************************************************************
2313 ****************************************************************************/
2315 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2316 int argc
, const char **argv
)
2318 struct policy_handle handle
;
2321 const char *printername
;
2323 uint32_t offered
= 0;
2324 union spoolss_FormInfo info
;
2327 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2329 /* Parse the command arguments */
2331 if (argc
< 3 || argc
> 5) {
2332 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2336 /* Get a printer handle */
2338 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2340 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2342 SEC_FLAG_MAXIMUM_ALLOWED
,
2344 if (!W_ERROR_IS_OK(werror
))
2348 level
= atoi(argv
[3]);
2353 status
= dcerpc_spoolss_GetForm(b
, mem_ctx
,
2362 if (!NT_STATUS_IS_OK(status
)) {
2363 werror
= ntstatus_to_werror(status
);
2366 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2367 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2369 status
= dcerpc_spoolss_GetForm(b
, mem_ctx
,
2378 if (!NT_STATUS_IS_OK(status
)) {
2379 werror
= ntstatus_to_werror(status
);
2384 if (!W_ERROR_IS_OK(werror
)) {
2390 display_form_info1(&info
.info1
);
2393 display_form_info2(&info
.info2
);
2398 if (is_valid_policy_hnd(&handle
)) {
2400 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2406 /****************************************************************************
2407 ****************************************************************************/
2409 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2410 TALLOC_CTX
*mem_ctx
, int argc
,
2413 struct policy_handle handle
;
2416 const char *printername
;
2417 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2419 /* Parse the command arguments */
2422 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2426 /* Get a printer handle */
2428 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2430 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2432 SEC_FLAG_MAXIMUM_ALLOWED
,
2434 if (!W_ERROR_IS_OK(werror
))
2437 /* Delete the form */
2439 status
= dcerpc_spoolss_DeleteForm(b
, mem_ctx
,
2443 if (!NT_STATUS_IS_OK(status
)) {
2444 werror
= ntstatus_to_werror(status
);
2449 if (is_valid_policy_hnd(&handle
)) {
2451 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2457 /****************************************************************************
2458 ****************************************************************************/
2460 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2461 TALLOC_CTX
*mem_ctx
, int argc
,
2464 struct policy_handle handle
;
2466 const char *printername
;
2467 uint32_t num_forms
, level
= 1, i
;
2468 union spoolss_FormInfo
*forms
;
2469 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2471 /* Parse the command arguments */
2473 if (argc
< 2 || argc
> 4) {
2474 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2478 /* Get a printer handle */
2480 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2482 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2484 SEC_FLAG_MAXIMUM_ALLOWED
,
2486 if (!W_ERROR_IS_OK(werror
))
2490 level
= atoi(argv
[2]);
2493 /* Enumerate forms */
2495 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2502 if (!W_ERROR_IS_OK(werror
))
2505 /* Display output */
2507 for (i
= 0; i
< num_forms
; i
++) {
2510 display_form_info1(&forms
[i
].info1
);
2513 display_form_info2(&forms
[i
].info2
);
2519 if (is_valid_policy_hnd(&handle
)) {
2521 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2527 /****************************************************************************
2528 ****************************************************************************/
2530 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2531 TALLOC_CTX
*mem_ctx
,
2532 int argc
, const char **argv
)
2536 const char *printername
;
2537 struct policy_handle pol
= { 0, };
2538 union spoolss_PrinterInfo info
;
2539 enum winreg_Type type
;
2540 union spoolss_PrinterData data
;
2542 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2544 /* parse the command arguments */
2546 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2547 " <value> <data>\n",
2552 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2556 if (strequal(argv
[2], "string")) {
2560 if (strequal(argv
[2], "binary")) {
2564 if (strequal(argv
[2], "dword")) {
2568 if (strequal(argv
[2], "multistring")) {
2569 type
= REG_MULTI_SZ
;
2572 if (type
== REG_NONE
) {
2573 printf("Unknown data type: %s\n", argv
[2]);
2574 result
= WERR_INVALID_PARAM
;
2578 /* get a printer handle */
2580 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2582 SEC_FLAG_MAXIMUM_ALLOWED
,
2584 if (!W_ERROR_IS_OK(result
)) {
2588 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2593 if (!W_ERROR_IS_OK(result
)) {
2597 printf("%s\n", current_timestring(mem_ctx
, true));
2598 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2600 /* Set the printer data */
2604 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2605 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2608 data
.value
= strtoul(argv
[4], NULL
, 10);
2611 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2613 case REG_MULTI_SZ
: {
2615 const char **strings
= NULL
;
2617 for (i
=4; i
<argc
; i
++) {
2618 if (strcmp(argv
[i
], "NULL") == 0) {
2621 if (!add_string_to_array(mem_ctx
, argv
[i
],
2624 result
= WERR_NOMEM
;
2628 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2629 if (!data
.string_array
) {
2630 result
= WERR_NOMEM
;
2633 for (i
=0; i
< num_strings
; i
++) {
2634 data
.string_array
[i
] = strings
[i
];
2639 printf("Unknown data type: %s\n", argv
[2]);
2640 result
= WERR_INVALID_PARAM
;
2644 result
= push_spoolss_PrinterData(mem_ctx
, &blob
, type
, &data
);
2645 if (!W_ERROR_IS_OK(result
)) {
2649 status
= dcerpc_spoolss_SetPrinterData(b
, mem_ctx
,
2651 argv
[3], /* value_name */
2656 if (!NT_STATUS_IS_OK(status
)) {
2657 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2658 result
= ntstatus_to_werror(status
);
2661 if (!W_ERROR_IS_OK(result
)) {
2662 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2665 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2667 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2672 if (!W_ERROR_IS_OK(result
)) {
2676 printf("%s\n", current_timestring(mem_ctx
, true));
2677 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2681 if (is_valid_policy_hnd(&pol
)) {
2683 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
2689 /****************************************************************************
2690 ****************************************************************************/
2692 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2694 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2695 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2699 /****************************************************************************
2700 ****************************************************************************/
2702 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2704 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2705 r
->position
, r
->job_id
,
2706 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2707 r
->total_pages
, r
->size
);
2710 /****************************************************************************
2711 ****************************************************************************/
2713 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2715 printf("jobid[%d], next_jobid[%d]\n",
2716 r
->job_id
, r
->next_job_id
);
2719 /****************************************************************************
2720 ****************************************************************************/
2722 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2724 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2725 r
->position
, r
->job_id
,
2726 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2727 r
->total_pages
, r
->size
, r
->size_high
);
2730 /****************************************************************************
2731 ****************************************************************************/
2733 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2734 TALLOC_CTX
*mem_ctx
, int argc
,
2738 uint32_t level
= 1, count
, i
;
2739 const char *printername
;
2740 struct policy_handle hnd
;
2741 union spoolss_JobInfo
*info
;
2742 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2744 if (argc
< 2 || argc
> 3) {
2745 printf("Usage: %s printername [level]\n", argv
[0]);
2750 level
= atoi(argv
[2]);
2753 /* Open printer handle */
2755 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2757 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2759 SEC_FLAG_MAXIMUM_ALLOWED
,
2761 if (!W_ERROR_IS_OK(result
))
2764 /* Enumerate ports */
2766 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2774 if (!W_ERROR_IS_OK(result
)) {
2778 for (i
= 0; i
< count
; i
++) {
2781 display_job_info1(&info
[i
].info1
);
2784 display_job_info2(&info
[i
].info2
);
2787 d_printf("unknown info level %d\n", level
);
2793 if (is_valid_policy_hnd(&hnd
)) {
2795 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
2801 /****************************************************************************
2802 ****************************************************************************/
2804 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2805 TALLOC_CTX
*mem_ctx
, int argc
,
2809 const char *printername
;
2810 struct policy_handle hnd
;
2813 union spoolss_JobInfo info
;
2814 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2816 if (argc
< 3 || argc
> 4) {
2817 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2821 job_id
= atoi(argv
[2]);
2824 level
= atoi(argv
[3]);
2827 /* Open printer handle */
2829 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2831 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2833 SEC_FLAG_MAXIMUM_ALLOWED
,
2835 if (!W_ERROR_IS_OK(result
)) {
2839 /* Enumerate ports */
2841 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2848 if (!W_ERROR_IS_OK(result
)) {
2854 display_job_info1(&info
.info1
);
2857 display_job_info2(&info
.info2
);
2860 display_job_info3(&info
.info3
);
2863 display_job_info4(&info
.info4
);
2866 d_printf("unknown info level %d\n", level
);
2871 if (is_valid_policy_hnd(&hnd
)) {
2873 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
2879 /****************************************************************************
2880 ****************************************************************************/
2884 enum spoolss_JobControl val
;
2886 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE
},
2887 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME
},
2888 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL
},
2889 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART
},
2890 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE
},
2891 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
},
2892 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
},
2893 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN
},
2894 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE
}
2897 static enum spoolss_JobControl
parse_setjob_command(const char *cmd
)
2901 for (i
= 0; i
< sizeof(cmdvals
)/sizeof(cmdvals
[0]); i
++) {
2902 if (strequal(cmdvals
[i
].name
, cmd
)) {
2903 return cmdvals
[i
].val
;
2906 return (enum spoolss_JobControl
)atoi(cmd
);
2909 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
2910 TALLOC_CTX
*mem_ctx
, int argc
,
2915 const char *printername
;
2916 struct policy_handle hnd
;
2918 enum spoolss_JobControl command
;
2919 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2922 printf("Usage: %s printername job_id command\n", argv
[0]);
2923 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2924 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2928 job_id
= atoi(argv
[2]);
2929 command
= parse_setjob_command(argv
[3]);
2931 /* Open printer handle */
2933 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2935 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2937 SEC_FLAG_MAXIMUM_ALLOWED
,
2939 if (!W_ERROR_IS_OK(result
)) {
2945 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
2951 if (!NT_STATUS_IS_OK(status
)) {
2952 result
= ntstatus_to_werror(status
);
2955 if (!W_ERROR_IS_OK(result
)) {
2960 if (is_valid_policy_hnd(&hnd
)) {
2962 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
2968 /****************************************************************************
2969 ****************************************************************************/
2971 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
2972 TALLOC_CTX
*mem_ctx
, int argc
,
2977 const char *printername
;
2978 struct policy_handle hnd
;
2979 uint32_t value_needed
;
2980 enum winreg_Type type
;
2981 uint32_t data_needed
;
2982 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2983 struct spoolss_EnumPrinterData r
;
2986 printf("Usage: %s printername\n", argv
[0]);
2990 /* Open printer handle */
2992 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2994 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2996 SEC_FLAG_MAXIMUM_ALLOWED
,
2998 if (!W_ERROR_IS_OK(result
)) {
3002 /* Enumerate data */
3005 r
.in
.enum_index
= 0;
3006 r
.in
.value_offered
= 0;
3007 r
.in
.data_offered
= 0;
3008 r
.out
.value_name
= NULL
;
3009 r
.out
.value_needed
= &value_needed
;
3012 r
.out
.data_needed
= &data_needed
;
3014 status
= dcerpc_spoolss_EnumPrinterData_r(b
, mem_ctx
, &r
);
3015 if (!NT_STATUS_IS_OK(status
)) {
3016 result
= ntstatus_to_werror(status
);
3020 if (!W_ERROR_IS_OK(r
.out
.result
)) {
3021 result
= r
.out
.result
;
3025 r
.in
.data_offered
= *r
.out
.data_needed
;
3026 r
.in
.value_offered
= *r
.out
.value_needed
;
3027 r
.out
.data
= talloc_zero_array(mem_ctx
, uint8_t, r
.in
.data_offered
);
3028 r
.out
.value_name
= talloc_zero_array(mem_ctx
, char, r
.in
.value_offered
);
3032 status
= dcerpc_spoolss_EnumPrinterData_r(b
, mem_ctx
, &r
);
3033 if (!NT_STATUS_IS_OK(status
)) {
3034 result
= ntstatus_to_werror(status
);
3038 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
3045 display_reg_value(r
.out
.value_name
, *r
.out
.type
,
3046 data_blob_const(r
.out
.data
, r
.in
.data_offered
));
3048 } while (W_ERROR_IS_OK(r
.out
.result
));
3051 if (is_valid_policy_hnd(&hnd
)) {
3053 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3059 /****************************************************************************
3060 ****************************************************************************/
3062 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
3063 TALLOC_CTX
*mem_ctx
, int argc
,
3068 const char *printername
;
3069 struct policy_handle hnd
;
3071 struct spoolss_PrinterEnumValues
*info
;
3072 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3075 printf("Usage: %s printername <keyname>\n", argv
[0]);
3079 /* Open printer handle */
3081 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3083 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3085 SEC_FLAG_MAXIMUM_ALLOWED
,
3087 if (!W_ERROR_IS_OK(result
)) {
3091 /* Enumerate subkeys */
3093 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
3099 if (!W_ERROR_IS_OK(result
)) {
3103 for (i
=0; i
< count
; i
++) {
3104 display_printer_data(info
[i
].value_name
,
3107 info
[i
].data
->length
);
3111 if (is_valid_policy_hnd(&hnd
)) {
3113 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3119 /****************************************************************************
3120 ****************************************************************************/
3122 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
3123 TALLOC_CTX
*mem_ctx
, int argc
,
3127 const char *printername
;
3128 const char *keyname
= NULL
;
3129 struct policy_handle hnd
;
3130 const char **key_buffer
= NULL
;
3132 uint32_t offered
= 0;
3133 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3135 if (argc
< 2 || argc
> 4) {
3136 printf("Usage: %s printername [keyname] [offered]\n", argv
[0]);
3147 offered
= atoi(argv
[3]);
3150 /* Open printer handle */
3152 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3154 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3156 SEC_FLAG_MAXIMUM_ALLOWED
,
3158 if (!W_ERROR_IS_OK(result
)) {
3162 /* Enumerate subkeys */
3164 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
3170 if (!W_ERROR_IS_OK(result
)) {
3174 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
3175 printf("%s\n", key_buffer
[i
]);
3180 if (is_valid_policy_hnd(&hnd
)) {
3182 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3188 /****************************************************************************
3189 ****************************************************************************/
3191 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
3192 TALLOC_CTX
*mem_ctx
, int argc
,
3195 const char *printername
;
3196 const char *clientname
;
3197 struct policy_handle hnd
;
3200 struct spoolss_NotifyOption option
;
3201 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3204 printf("Usage: %s printername\n", argv
[0]);
3211 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3213 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3215 SEC_FLAG_MAXIMUM_ALLOWED
,
3217 if (!W_ERROR_IS_OK(result
)) {
3218 printf("Error opening %s\n", argv
[1]);
3222 /* Create spool options */
3227 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3228 if (option
.types
== NULL
) {
3229 result
= WERR_NOMEM
;
3233 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3234 option
.types
[0].count
= 1;
3235 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3236 if (option
.types
[0].fields
== NULL
) {
3237 result
= WERR_NOMEM
;
3240 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3242 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3243 option
.types
[1].count
= 1;
3244 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3245 if (option
.types
[1].fields
== NULL
) {
3246 result
= WERR_NOMEM
;
3249 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3251 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", lp_netbios_name());
3253 result
= WERR_NOMEM
;
3259 status
= dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b
, mem_ctx
,
3267 if (!NT_STATUS_IS_OK(status
)) {
3268 result
= ntstatus_to_werror(status
);
3271 if (!W_ERROR_IS_OK(result
)) {
3272 printf("Error rffpcnex %s\n", argv
[1]);
3277 if (is_valid_policy_hnd(&hnd
)) {
3279 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3285 /****************************************************************************
3286 ****************************************************************************/
3288 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3289 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3291 union spoolss_PrinterInfo info1
, info2
;
3293 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3295 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3296 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3301 if ( !W_ERROR_IS_OK(werror
) ) {
3302 printf("failed (%s)\n", win_errstr(werror
));
3303 talloc_destroy(mem_ctx
);
3308 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3309 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3314 if ( !W_ERROR_IS_OK(werror
) ) {
3315 printf("failed (%s)\n", win_errstr(werror
));
3316 talloc_destroy(mem_ctx
);
3321 talloc_destroy(mem_ctx
);
3326 /****************************************************************************
3327 ****************************************************************************/
3329 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3330 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3332 union spoolss_PrinterInfo info1
, info2
;
3334 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3335 struct security_descriptor
*sd1
, *sd2
;
3339 printf("Retrieving printer security for %s...", cli1
->desthost
);
3340 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3345 if ( !W_ERROR_IS_OK(werror
) ) {
3346 printf("failed (%s)\n", win_errstr(werror
));
3352 printf("Retrieving printer security for %s...", cli2
->desthost
);
3353 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3358 if ( !W_ERROR_IS_OK(werror
) ) {
3359 printf("failed (%s)\n", win_errstr(werror
));
3368 sd1
= info1
.info3
.secdesc
;
3369 sd2
= info2
.info3
.secdesc
;
3371 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3372 printf("NULL secdesc!\n");
3377 if (!security_descriptor_equal( sd1
, sd2
) ) {
3378 printf("Security Descriptors *not* equal!\n");
3383 printf("Security descriptors match\n");
3386 talloc_destroy(mem_ctx
);
3391 /****************************************************************************
3392 ****************************************************************************/
3394 extern struct user_auth_info
*rpcclient_auth_info
;
3396 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3397 TALLOC_CTX
*mem_ctx
, int argc
,
3400 const char *printername
;
3401 char *printername_path
= NULL
;
3402 struct cli_state
*cli_server2
= NULL
;
3403 struct rpc_pipe_client
*cli2
= NULL
;
3404 struct policy_handle hPrinter1
, hPrinter2
;
3409 printf("Usage: %s <printer> <server>\n", argv
[0]);
3413 printername
= argv
[1];
3415 /* first get the connection to the remote server */
3417 nt_status
= cli_full_connection(&cli_server2
, lp_netbios_name(), argv
[2],
3420 get_cmdline_auth_info_username(rpcclient_auth_info
),
3422 get_cmdline_auth_info_password(rpcclient_auth_info
),
3423 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info
) ? CLI_FULL_CONNECTION_USE_KERBEROS
: 0,
3424 get_cmdline_auth_info_signing_state(rpcclient_auth_info
));
3426 if ( !NT_STATUS_IS_OK(nt_status
) )
3427 return WERR_GENERAL_FAILURE
;
3429 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
.syntax_id
,
3431 if (!NT_STATUS_IS_OK(nt_status
)) {
3432 printf("failed to open spoolss pipe on server %s (%s)\n",
3433 argv
[2], nt_errstr(nt_status
));
3434 return WERR_GENERAL_FAILURE
;
3437 /* now open up both printers */
3439 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3441 printf("Opening %s...", printername_path
);
3443 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3447 if ( !W_ERROR_IS_OK(werror
) ) {
3448 printf("failed (%s)\n", win_errstr(werror
));
3453 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3455 printf("Opening %s...", printername_path
);
3456 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3460 if ( !W_ERROR_IS_OK(werror
) ) {
3461 printf("failed (%s)\n", win_errstr(werror
));
3466 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3467 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3469 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3476 printf("Closing printers...");
3479 dcerpc_spoolss_ClosePrinter(cli
->binding_handle
, mem_ctx
, &hPrinter1
, &_result
);
3480 dcerpc_spoolss_ClosePrinter(cli2
->binding_handle
, mem_ctx
, &hPrinter2
, &_result
);
3484 /* close the second remote connection */
3486 cli_shutdown( cli_server2
);
3490 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3492 printf("print_processor_name: %s\n", r
->print_processor_name
);
3495 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3496 TALLOC_CTX
*mem_ctx
, int argc
,
3500 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3501 uint32_t num_procs
, level
= 1, i
;
3502 union spoolss_PrintProcessorInfo
*procs
;
3504 /* Parse the command arguments */
3506 if (argc
< 1 || argc
> 4) {
3507 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3512 environment
= argv
[1];
3516 level
= atoi(argv
[2]);
3519 /* Enumerate Print Processors */
3521 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3522 cli
->srv_name_slash
,
3528 if (!W_ERROR_IS_OK(werror
))
3531 /* Display output */
3533 for (i
= 0; i
< num_procs
; i
++) {
3536 display_proc_info1(&procs
[i
].info1
);
3545 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3547 printf("name_array: %s\n", r
->name_array
);
3550 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3551 TALLOC_CTX
*mem_ctx
, int argc
,
3555 const char *print_processor_name
= "winprint";
3556 uint32_t num_procs
, level
= 1, i
;
3557 union spoolss_PrintProcDataTypesInfo
*procs
;
3559 /* Parse the command arguments */
3561 if (argc
< 1 || argc
> 4) {
3562 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3567 print_processor_name
= argv
[1];
3571 level
= atoi(argv
[2]);
3574 /* Enumerate Print Processor Data Types */
3576 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3577 cli
->srv_name_slash
,
3578 print_processor_name
,
3583 if (!W_ERROR_IS_OK(werror
))
3586 /* Display output */
3588 for (i
= 0; i
< num_procs
; i
++) {
3591 display_proc_data_types_info1(&procs
[i
].info1
);
3600 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3602 printf("monitor_name: %s\n", r
->monitor_name
);
3605 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3607 printf("monitor_name: %s\n", r
->monitor_name
);
3608 printf("environment: %s\n", r
->environment
);
3609 printf("dll_name: %s\n", r
->dll_name
);
3612 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3613 TALLOC_CTX
*mem_ctx
, int argc
,
3617 uint32_t count
, level
= 1, i
;
3618 union spoolss_MonitorInfo
*info
;
3620 /* Parse the command arguments */
3623 printf("Usage: %s [level]\n", argv
[0]);
3628 level
= atoi(argv
[1]);
3631 /* Enumerate Print Monitors */
3633 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3634 cli
->srv_name_slash
,
3639 if (!W_ERROR_IS_OK(werror
)) {
3643 /* Display output */
3645 for (i
= 0; i
< count
; i
++) {
3648 display_monitor1(&info
[i
].info1
);
3651 display_monitor2(&info
[i
].info2
);
3660 static WERROR
cmd_spoolss_create_printer_ic(struct rpc_pipe_client
*cli
,
3661 TALLOC_CTX
*mem_ctx
, int argc
,
3666 struct policy_handle handle
, gdi_handle
;
3667 const char *printername
;
3668 struct spoolss_DevmodeContainer devmode_ctr
;
3669 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3671 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3673 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3675 SEC_FLAG_MAXIMUM_ALLOWED
,
3677 if (!W_ERROR_IS_OK(result
)) {
3681 ZERO_STRUCT(devmode_ctr
);
3683 status
= dcerpc_spoolss_CreatePrinterIC(b
, mem_ctx
,
3688 if (!NT_STATUS_IS_OK(status
)) {
3689 result
= ntstatus_to_werror(status
);
3692 if (!W_ERROR_IS_OK(result
)) {
3697 if (is_valid_policy_hnd(&gdi_handle
)) {
3699 dcerpc_spoolss_DeletePrinterIC(b
, mem_ctx
, &gdi_handle
, &_result
);
3701 if (is_valid_policy_hnd(&handle
)) {
3703 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
3709 /* List of commands exported by this module */
3710 struct cmd_set spoolss_commands
[] = {
3714 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, &ndr_table_spoolss
, NULL
, "Add a print driver", "" },
3715 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, &ndr_table_spoolss
, NULL
, "Add a printer", "" },
3716 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, &ndr_table_spoolss
, NULL
, "Delete a printer driver", "" },
3717 { "deldriverex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriverex
, &ndr_table_spoolss
, NULL
, "Delete a printer driver with files", "" },
3718 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, &ndr_table_spoolss
, NULL
, "Enumerate printer data", "" },
3719 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, &ndr_table_spoolss
, NULL
, "Enumerate printer data for a key", "" },
3720 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, &ndr_table_spoolss
, NULL
, "Enumerate printer keys", "" },
3721 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, &ndr_table_spoolss
, NULL
, "Enumerate print jobs", "" },
3722 { "getjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_get_job
, &ndr_table_spoolss
, NULL
, "Get print job", "" },
3723 { "setjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_set_job
, &ndr_table_spoolss
, NULL
, "Set print job", "" },
3724 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, &ndr_table_spoolss
, NULL
, "Enumerate printer ports", "" },
3725 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, &ndr_table_spoolss
, NULL
, "Enumerate installed printer drivers", "" },
3726 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, &ndr_table_spoolss
, NULL
, "Enumerate printers", "" },
3727 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, &ndr_table_spoolss
, NULL
, "Get print driver data", "" },
3728 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, &ndr_table_spoolss
, NULL
, "Get printer driver data with keyname", ""},
3729 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, &ndr_table_spoolss
, NULL
, "Get print driver information", "" },
3730 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, &ndr_table_spoolss
, NULL
, "Get print driver upload directory", "" },
3731 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, &ndr_table_spoolss
, NULL
, "Get printer info", "" },
3732 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer
, &ndr_table_spoolss
, NULL
, "Open printer handle", "" },
3733 { "openprinter_ex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, &ndr_table_spoolss
, NULL
, "Open printer handle", "" },
3734 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, &ndr_table_spoolss
, NULL
, "Set printer driver", "" },
3735 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, &ndr_table_spoolss
, NULL
, "Get print processor directory", "" },
3736 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, &ndr_table_spoolss
, NULL
, "Add form", "" },
3737 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, &ndr_table_spoolss
, NULL
, "Set form", "" },
3738 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, &ndr_table_spoolss
, NULL
, "Get form", "" },
3739 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, &ndr_table_spoolss
, NULL
, "Delete form", "" },
3740 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, &ndr_table_spoolss
, NULL
, "Enumerate forms", "" },
3741 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, &ndr_table_spoolss
, NULL
, "Set printer comment", "" },
3742 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, &ndr_table_spoolss
, NULL
, "Set printername", "" },
3743 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, &ndr_table_spoolss
, NULL
, "Set REG_SZ printer data", "" },
3744 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, &ndr_table_spoolss
, NULL
, "Rffpcnex test", "" },
3745 { "printercmp", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_printercmp
, &ndr_table_spoolss
, NULL
, "Printer comparison test", "" },
3746 { "enumprocs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_procs
, &ndr_table_spoolss
, NULL
, "Enumerate Print Processors", "" },
3747 { "enumprocdatatypes", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_proc_data_types
, &ndr_table_spoolss
, NULL
, "Enumerate Print Processor Data Types", "" },
3748 { "enummonitors", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_monitors
, &ndr_table_spoolss
, NULL
, "Enumerate Print Monitors", "" },
3749 { "createprinteric", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_create_printer_ic
, &ndr_table_spoolss
, NULL
, "Create Printer IC", "" },