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 "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
31 #include "nt_printing.h"
32 #include "../libcli/security/display_sec.h"
33 #include "../libcli/security/security_descriptor.h"
34 #include "../libcli/registry/util_reg.h"
35 #include "libsmb/libsmb.h"
36 #include "lib/util/smb_strtox.h"
37 #include "lib/util/string_wrappers.h"
38 #include "lib/cmdline/cmdline.h"
40 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
42 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
43 _cli->srv_name_slash, _arg); \
44 W_ERROR_HAVE_NO_MEMORY(_printername); \
51 * rpcclient module for SPOOLSS rpc pipe.
53 * This generally just parses and checks command lines, and then calls
54 * a cli_spoolss function.
57 /****************************************************************************
58 function to do the mapping between the long architecture name and
60 ****************************************************************************/
62 static const char *cmd_spoolss_get_short_archi(const char *long_archi
)
66 DEBUG(107,("Getting architecture dependent directory\n"));
69 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
70 strcasecmp_m(long_archi
, archi_table
[i
].long_archi
) );
72 if (archi_table
[i
].long_archi
==NULL
) {
73 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
77 /* this might be client code - but shouldn't this be an fstrcpy etc? */
80 DEBUGADD(108,("index: [%d]\n", i
));
81 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
82 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
84 return archi_table
[i
].short_archi
;
87 /****************************************************************************
88 ****************************************************************************/
90 static WERROR
cmd_spoolss_open_printer_ex(struct rpc_pipe_client
*cli
,
92 int argc
, const char **argv
)
95 struct policy_handle hnd
;
96 uint32_t access_mask
= PRINTER_ALL_ACCESS
;
97 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
100 printf("Usage: %s <printername> [access_mask]\n", argv
[0]);
105 sscanf(argv
[2], "%x", &access_mask
);
108 /* Open the printer handle */
110 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
114 if (W_ERROR_IS_OK(werror
)) {
115 printf("Printer %s opened successfully\n", argv
[1]);
116 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &werror
);
118 if (!W_ERROR_IS_OK(werror
)) {
119 printf("Error closing printer handle! (%s)\n",
120 get_dos_error_msg(werror
));
127 /****************************************************************************
128 ****************************************************************************/
130 static WERROR
cmd_spoolss_open_printer(struct rpc_pipe_client
*cli
,
132 int argc
, const char **argv
)
135 struct policy_handle hnd
;
136 uint32_t access_mask
= PRINTER_ALL_ACCESS
;
138 struct spoolss_DevmodeContainer devmode_ctr
;
139 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
141 ZERO_STRUCT(devmode_ctr
);
144 printf("Usage: %s <printername> [access_mask]\n", argv
[0]);
149 sscanf(argv
[2], "%x", &access_mask
);
152 /* Open the printer handle */
154 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
161 if (!NT_STATUS_IS_OK(status
)) {
162 return ntstatus_to_werror(status
);
164 if (W_ERROR_IS_OK(werror
)) {
165 printf("Printer %s opened successfully\n", argv
[1]);
166 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &werror
);
168 if (!W_ERROR_IS_OK(werror
)) {
169 printf("Error closing printer handle! (%s)\n",
170 get_dos_error_msg(werror
));
177 /****************************************************************************
178 ****************************************************************************/
180 static void display_print_info0(struct spoolss_PrinterInfo0
*r
)
185 printf("\tprintername:[%s]\n", r
->printername
);
186 printf("\tservername:[%s]\n", r
->servername
);
187 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
188 printf("\ttotal_jobs:[0x%x]\n", r
->total_jobs
);
189 printf("\ttotal_bytes:[0x%x]\n", r
->total_bytes
);
190 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r
->time
.year
, r
->time
.month
,
191 r
->time
.day
, r
->time
.day_of_week
);
192 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r
->time
.hour
, r
->time
.minute
,
193 r
->time
.second
, r
->time
.millisecond
);
195 printf("\tglobal_counter:[0x%x]\n", r
->global_counter
);
196 printf("\ttotal_pages:[0x%x]\n", r
->total_pages
);
198 printf("\tversion:[0x%x]\n", r
->version
);
199 printf("\tfree_build:[0x%x]\n", r
->free_build
);
200 printf("\tspooling:[0x%x]\n", r
->spooling
);
201 printf("\tmax_spooling:[0x%x]\n", r
->max_spooling
);
202 printf("\tsession_counter:[0x%x]\n", r
->session_counter
);
203 printf("\tnum_error_out_of_paper:[0x%x]\n", r
->num_error_out_of_paper
);
204 printf("\tnum_error_not_ready:[0x%x]\n", r
->num_error_not_ready
);
205 printf("\tjob_error:[0x%x]\n", r
->job_error
);
206 printf("\tnumber_of_processors:[0x%x]\n", r
->number_of_processors
);
207 printf("\tprocessor_type:[0x%x]\n", r
->processor_type
);
208 printf("\thigh_part_total_bytes:[0x%x]\n", r
->high_part_total_bytes
);
209 printf("\tchange_id:[0x%x]\n", r
->change_id
);
210 printf("\tlast_error: %s\n", win_errstr(r
->last_error
));
211 printf("\tstatus:[0x%x]\n", r
->status
);
212 printf("\tenumerate_network_printers:[0x%x]\n", r
->enumerate_network_printers
);
213 printf("\tc_setprinter:[0x%x]\n", r
->c_setprinter
);
214 printf("\tprocessor_architecture:[0x%x]\n", r
->processor_architecture
);
215 printf("\tprocessor_level:[0x%x]\n", r
->processor_level
);
216 printf("\tref_ic:[0x%x]\n", r
->ref_ic
);
217 printf("\treserved2:[0x%x]\n", r
->reserved2
);
218 printf("\treserved3:[0x%x]\n", r
->reserved3
);
223 /****************************************************************************
224 ****************************************************************************/
226 static void display_print_info1(struct spoolss_PrinterInfo1
*r
)
228 printf("\tflags:[0x%x]\n", r
->flags
);
229 printf("\tname:[%s]\n", r
->name
);
230 printf("\tdescription:[%s]\n", r
->description
);
231 printf("\tcomment:[%s]\n", r
->comment
);
236 /****************************************************************************
237 ****************************************************************************/
239 static void display_print_info2(struct spoolss_PrinterInfo2
*r
)
241 printf("\tservername:[%s]\n", r
->servername
);
242 printf("\tprintername:[%s]\n", r
->printername
);
243 printf("\tsharename:[%s]\n", r
->sharename
);
244 printf("\tportname:[%s]\n", r
->portname
);
245 printf("\tdrivername:[%s]\n", r
->drivername
);
246 printf("\tcomment:[%s]\n", r
->comment
);
247 printf("\tlocation:[%s]\n", r
->location
);
248 printf("\tsepfile:[%s]\n", r
->sepfile
);
249 printf("\tprintprocessor:[%s]\n", r
->printprocessor
);
250 printf("\tdatatype:[%s]\n", r
->datatype
);
251 printf("\tparameters:[%s]\n", r
->parameters
);
252 printf("\tattributes:[0x%x]\n", r
->attributes
);
253 printf("\tpriority:[0x%x]\n", r
->priority
);
254 printf("\tdefaultpriority:[0x%x]\n", r
->defaultpriority
);
255 printf("\tstarttime:[0x%x]\n", r
->starttime
);
256 printf("\tuntiltime:[0x%x]\n", r
->untiltime
);
257 printf("\tstatus:[0x%x]\n", r
->status
);
258 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
259 printf("\taverageppm:[0x%x]\n", r
->averageppm
);
262 display_sec_desc(r
->secdesc
);
267 /****************************************************************************
268 ****************************************************************************/
270 static void display_print_info3(struct spoolss_PrinterInfo3
*r
)
272 display_sec_desc(r
->secdesc
);
277 /****************************************************************************
278 ****************************************************************************/
280 static void display_print_info4(struct spoolss_PrinterInfo4
*r
)
282 printf("\tservername:[%s]\n", r
->servername
);
283 printf("\tprintername:[%s]\n", r
->printername
);
284 printf("\tattributes:[0x%x]\n", r
->attributes
);
288 /****************************************************************************
289 ****************************************************************************/
291 static void display_print_info5(struct spoolss_PrinterInfo5
*r
)
293 printf("\tprintername:[%s]\n", r
->printername
);
294 printf("\tportname:[%s]\n", r
->portname
);
295 printf("\tattributes:[0x%x]\n", r
->attributes
);
296 printf("\tdevice_not_selected_timeout:[0x%x]\n", r
->device_not_selected_timeout
);
297 printf("\ttransmission_retry_timeout:[0x%x]\n", r
->transmission_retry_timeout
);
301 /****************************************************************************
302 ****************************************************************************/
304 static void display_print_info6(struct spoolss_PrinterInfo6
*r
)
306 printf("\tstatus:[0x%x]\n", r
->status
);
310 /****************************************************************************
311 ****************************************************************************/
313 static void display_print_info7(struct spoolss_PrinterInfo7
*r
)
315 printf("\tguid:[%s]\n", r
->guid
);
316 printf("\taction:[0x%x]\n", r
->action
);
320 /****************************************************************************
321 ****************************************************************************/
323 static WERROR
cmd_spoolss_enum_printers(struct rpc_pipe_client
*cli
,
325 int argc
, const char **argv
)
329 union spoolss_PrinterInfo
*info
;
332 uint32_t flags
= PRINTER_ENUM_LOCAL
;
335 printf("Usage: %s [level] [name] [flags]\n", argv
[0]);
340 level
= atoi(argv
[1]);
346 name
= cli
->srv_name_slash
;
350 flags
= atoi(argv
[3]);
353 result
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
360 if (W_ERROR_IS_OK(result
)) {
363 printf ("No printers returned.\n");
367 for (i
= 0; i
< count
; i
++) {
370 display_print_info0(&info
[i
].info0
);
373 display_print_info1(&info
[i
].info1
);
376 display_print_info2(&info
[i
].info2
);
379 display_print_info3(&info
[i
].info3
);
382 display_print_info4(&info
[i
].info4
);
385 display_print_info5(&info
[i
].info5
);
388 display_print_info6(&info
[i
].info6
);
391 printf("unknown info level %d\n", level
);
401 /****************************************************************************
402 ****************************************************************************/
404 static void display_port_info_1(struct spoolss_PortInfo1
*r
)
406 printf("\tPort Name:\t[%s]\n", r
->port_name
);
409 /****************************************************************************
410 ****************************************************************************/
412 static void display_port_info_2(struct spoolss_PortInfo2
*r
)
414 printf("\tPort Name:\t[%s]\n", r
->port_name
);
415 printf("\tMonitor Name:\t[%s]\n", r
->monitor_name
);
416 printf("\tDescription:\t[%s]\n", r
->description
);
417 printf("\tPort Type:\t" );
419 int comma
= 0; /* hack */
421 if (r
->port_type
& SPOOLSS_PORT_TYPE_READ
) {
425 if (r
->port_type
& SPOOLSS_PORT_TYPE_WRITE
) {
426 printf( "%sWrite", comma
? ", " : "" );
429 /* These two have slightly different interpretations
430 on 95/98/ME but I'm disregarding that for now */
431 if (r
->port_type
& SPOOLSS_PORT_TYPE_REDIRECTED
) {
432 printf( "%sRedirected", comma
? ", " : "" );
435 if (r
->port_type
& SPOOLSS_PORT_TYPE_NET_ATTACHED
) {
436 printf( "%sNet-Attached", comma
? ", " : "" );
440 printf( "[Unset]\n" );
442 printf("\tReserved:\t[%d]\n", r
->reserved
);
446 /****************************************************************************
447 ****************************************************************************/
449 static WERROR
cmd_spoolss_enum_ports(struct rpc_pipe_client
*cli
,
450 TALLOC_CTX
*mem_ctx
, int argc
,
456 union spoolss_PortInfo
*info
;
459 printf("Usage: %s [level]\n", argv
[0]);
464 level
= atoi(argv
[1]);
467 /* Enumerate ports */
469 result
= rpccli_spoolss_enumports(cli
, mem_ctx
,
475 if (W_ERROR_IS_OK(result
)) {
478 for (i
= 0; i
< count
; i
++) {
481 display_port_info_1(&info
[i
].info1
);
484 display_port_info_2(&info
[i
].info2
);
487 printf("unknown info level %d\n", level
);
496 /****************************************************************************
497 ****************************************************************************/
499 static WERROR
cmd_spoolss_setprinter(struct rpc_pipe_client
*cli
,
501 int argc
, const char **argv
)
503 struct policy_handle pol
;
506 uint32_t info_level
= 2;
507 union spoolss_PrinterInfo info
;
508 struct spoolss_SetPrinterInfoCtr info_ctr
;
509 struct spoolss_SetPrinterInfo2 info2
;
510 const char *printername
, *comment
= NULL
;
511 struct spoolss_DevmodeContainer devmode_ctr
;
512 struct sec_desc_buf secdesc_ctr
;
513 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
515 if (argc
== 1 || argc
> 3) {
516 printf("Usage: %s printername comment\n", argv
[0]);
521 /* Open a printer handle */
526 ZERO_STRUCT(devmode_ctr
);
527 ZERO_STRUCT(secdesc_ctr
);
529 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
531 /* get a printer handle */
532 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
536 if (!W_ERROR_IS_OK(result
))
539 /* Get printer info */
540 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
545 if (!W_ERROR_IS_OK(result
))
549 /* Modify the comment. */
550 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
551 info2
.comment
= comment
;
554 info_ctr
.info
.info2
= &info2
;
556 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
563 if (!NT_STATUS_IS_OK(status
)) {
564 result
= ntstatus_to_werror(status
);
567 if (W_ERROR_IS_OK(result
))
568 printf("Success in setting comment.\n");
571 if (is_valid_policy_hnd(&pol
)) {
573 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
579 /****************************************************************************
580 ****************************************************************************/
582 static WERROR
cmd_spoolss_setprintername(struct rpc_pipe_client
*cli
,
584 int argc
, const char **argv
)
586 struct policy_handle pol
;
589 uint32_t info_level
= 2;
590 union spoolss_PrinterInfo info
;
591 const char *printername
,
592 *new_printername
= NULL
;
593 struct spoolss_SetPrinterInfoCtr info_ctr
;
594 struct spoolss_SetPrinterInfo2 info2
;
595 struct spoolss_DevmodeContainer devmode_ctr
;
596 struct sec_desc_buf secdesc_ctr
;
597 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
599 ZERO_STRUCT(devmode_ctr
);
600 ZERO_STRUCT(secdesc_ctr
);
602 if (argc
== 1 || argc
> 3) {
603 printf("Usage: %s printername new_printername\n", argv
[0]);
608 /* Open a printer handle */
610 new_printername
= argv
[2];
613 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
615 /* get a printer handle */
616 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
620 if (!W_ERROR_IS_OK(result
))
623 /* Get printer info */
624 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
629 if (!W_ERROR_IS_OK(result
))
632 /* Modify the printername. */
633 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
634 info2
.printername
= new_printername
;
637 info_ctr
.info
.info2
= &info2
;
639 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
646 if (!NT_STATUS_IS_OK(status
)) {
647 result
= ntstatus_to_werror(status
);
650 if (W_ERROR_IS_OK(result
))
651 printf("Success in setting printername.\n");
654 if (is_valid_policy_hnd(&pol
)) {
656 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
662 /****************************************************************************
663 ****************************************************************************/
665 static WERROR
cmd_spoolss_getprinter(struct rpc_pipe_client
*cli
,
667 int argc
, const char **argv
)
669 struct policy_handle pol
;
672 const char *printername
;
673 union spoolss_PrinterInfo info
;
674 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
676 if (argc
== 1 || argc
> 3) {
677 printf("Usage: %s <printername> [level]\n", argv
[0]);
681 /* Open a printer handle */
683 level
= atoi(argv
[2]);
686 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
688 /* get a printer handle */
690 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
692 SEC_FLAG_MAXIMUM_ALLOWED
,
694 if (!W_ERROR_IS_OK(result
)) {
698 /* Get printer info */
700 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
705 if (!W_ERROR_IS_OK(result
)) {
709 /* Display printer info */
712 display_print_info0(&info
.info0
);
715 display_print_info1(&info
.info1
);
718 display_print_info2(&info
.info2
);
721 display_print_info3(&info
.info3
);
724 display_print_info4(&info
.info4
);
727 display_print_info5(&info
.info5
);
730 display_print_info6(&info
.info6
);
733 display_print_info7(&info
.info7
);
736 printf("unknown info level %d\n", level
);
740 if (is_valid_policy_hnd(&pol
)) {
742 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
748 /****************************************************************************
749 ****************************************************************************/
751 static void display_reg_value(const char *name
, enum winreg_Type type
, DATA_BLOB blob
)
753 const char *text
= NULL
;
757 if (blob
.length
>= sizeof(uint32_t)) {
758 printf("%s: REG_DWORD: 0x%08x\n", name
, IVAL(blob
.data
,0));
760 printf("%s: REG_DWORD: <invalid>\n", name
);
764 pull_reg_sz(talloc_tos(), &blob
, &text
);
765 printf("%s: REG_SZ: %s\n", name
, text
? text
: "");
768 char *hex
= hex_encode_talloc(NULL
, blob
.data
, blob
.length
);
770 printf("%s: REG_BINARY:", name
);
772 for (i
=0; i
<len
; i
++) {
773 if (hex
[i
] == '\0') {
789 if (!pull_reg_multi_sz(NULL
, &blob
, &values
)) {
790 d_printf("pull_reg_multi_sz failed\n");
794 printf("%s: REG_MULTI_SZ: \n", name
);
795 for (i
=0; values
[i
] != NULL
; i
++) {
796 d_printf("%s\n", values
[i
]);
802 printf("%s: unknown type %d\n", name
, type
);
807 /****************************************************************************
808 ****************************************************************************/
810 static void display_printer_data(const char *v
,
811 enum winreg_Type type
,
816 union spoolss_PrinterData r
;
817 DATA_BLOB blob
= data_blob_const(data
, length
);
819 enum ndr_err_code ndr_err
;
821 result
= pull_spoolss_PrinterData(talloc_tos(), &blob
, &r
, type
);
822 if (!W_ERROR_IS_OK(result
)) {
828 printf("%s: REG_DWORD: 0x%08x\n", v
, r
.value
);
831 printf("%s: REG_SZ: %s\n", v
, r
.string
);
834 char *hex
= hex_encode_talloc(NULL
,
835 r
.binary
.data
, r
.binary
.length
);
837 printf("%s: REG_BINARY:", v
);
839 for (i
=0; i
<len
; i
++) {
840 if (hex
[i
] == '\0') {
852 if (strequal(v
, "OsVersion")) {
853 struct spoolss_OSVersion os
;
854 ndr_err
= ndr_pull_struct_blob(&blob
, talloc_tos(), &os
,
855 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_OSVersion
);
856 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
858 printf("OsMajor: %u\n", os
.major
);
859 printf("OsMinor: %u\n", os
.minor
);
860 printf("OsBuild: %u\n", os
.build
);
861 NDR_PRINT_DEBUG(spoolss_OSVersion
, &os
);
864 if (strequal(v
, "OsVersionEx")) {
865 struct spoolss_OSVersionEx os
;
866 ndr_err
= ndr_pull_struct_blob(&blob
, talloc_tos(), &os
,
867 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_OSVersionEx
);
868 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
869 printf("OsMajor: %u\n", os
.major
);
870 printf("OsMinor: %u\n", os
.minor
);
871 printf("OsBuild: %u\n", os
.build
);
872 printf("ServicePackMajor: %u\n", os
.service_pack_major
);
873 printf("ServicePackMinor: %u\n", os
.service_pack_minor
);
874 NDR_PRINT_DEBUG(spoolss_OSVersionEx
, &os
);
880 printf("%s: REG_MULTI_SZ: ", v
);
881 for (i
=0; r
.string_array
[i
] != NULL
; i
++) {
882 printf("%s ", r
.string_array
[i
]);
887 printf("%s: unknown type 0x%02x:\n", v
, type
);
892 /****************************************************************************
893 ****************************************************************************/
895 static WERROR
cmd_spoolss_getprinterdata(struct rpc_pipe_client
*cli
,
897 int argc
, const char **argv
)
899 struct policy_handle pol
;
902 const char *valuename
;
903 enum winreg_Type type
;
906 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
909 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
910 printf("<printername> of . queries print server\n");
915 /* Open a printer handle */
917 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
918 fstrcpy(printername
, cli
->srv_name_slash
);
920 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
921 cli
->srv_name_slash
, argv
[1]);
923 /* get a printer handle */
925 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
927 SEC_FLAG_MAXIMUM_ALLOWED
,
929 if (!W_ERROR_IS_OK(result
))
932 /* Get printer info */
934 result
= rpccli_spoolss_getprinterdata(cli
, mem_ctx
,
941 if (!W_ERROR_IS_OK(result
))
944 /* Display printer data */
946 display_printer_data(valuename
, type
, data
, needed
);
949 if (is_valid_policy_hnd(&pol
)) {
951 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
957 /****************************************************************************
958 ****************************************************************************/
960 static WERROR
cmd_spoolss_getprinterdataex(struct rpc_pipe_client
*cli
,
962 int argc
, const char **argv
)
964 struct policy_handle pol
;
968 const char *valuename
, *keyname
;
970 enum winreg_Type type
;
971 uint8_t *data
= NULL
;
972 uint32_t offered
= 0;
974 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
977 printf("Usage: %s <printername> <keyname> <valuename>\n",
979 printf("<printername> of . queries print server\n");
985 /* Open a printer handle */
987 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
988 fstrcpy(printername
, cli
->srv_name_slash
);
990 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
991 cli
->srv_name_slash
, argv
[1]);
993 /* get a printer handle */
995 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
997 SEC_FLAG_MAXIMUM_ALLOWED
,
999 if (!W_ERROR_IS_OK(result
))
1002 /* Get printer info */
1004 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
1009 status
= dcerpc_spoolss_GetPrinterDataEx(b
, mem_ctx
,
1018 if (!NT_STATUS_IS_OK(status
)) {
1019 result
= ntstatus_to_werror(status
);
1022 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
1024 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
1028 status
= dcerpc_spoolss_GetPrinterDataEx(b
, mem_ctx
,
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 result
= ntstatus_to_werror(status
);
1044 if (!W_ERROR_IS_OK(result
))
1047 /* Display printer data */
1049 display_printer_data(valuename
, type
, data
, needed
);
1053 if (is_valid_policy_hnd(&pol
)) {
1055 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
1070 printf("Printer Driver Info 1:\n");
1071 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1075 /****************************************************************************
1076 ****************************************************************************/
1078 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
1084 printf("Printer Driver Info 2:\n");
1085 printf("\tVersion: [%x]\n", r
->version
);
1086 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1087 printf("\tArchitecture: [%s]\n", r
->architecture
);
1088 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1089 printf("\tDatafile: [%s]\n", r
->data_file
);
1090 printf("\tConfigfile: [%s]\n", r
->config_file
);
1094 /****************************************************************************
1095 ****************************************************************************/
1097 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
1105 printf("Printer Driver Info 3:\n");
1106 printf("\tVersion: [%x]\n", r
->version
);
1107 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1108 printf("\tArchitecture: [%s]\n", r
->architecture
);
1109 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1110 printf("\tDatafile: [%s]\n", r
->data_file
);
1111 printf("\tConfigfile: [%s]\n", r
->config_file
);
1112 printf("\tHelpfile: [%s]\n", r
->help_file
);
1114 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1115 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1118 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1119 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1123 /****************************************************************************
1124 ****************************************************************************/
1126 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1134 printf("Printer Driver Info 4:\n");
1135 printf("\tVersion: [%x]\n", r
->version
);
1136 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1137 printf("\tArchitecture: [%s]\n", r
->architecture
);
1138 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1139 printf("\tDatafile: [%s]\n", r
->data_file
);
1140 printf("\tConfigfile: [%s]\n", r
->config_file
);
1141 printf("\tHelpfile: [%s]\n", r
->help_file
);
1143 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1144 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1147 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1148 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1150 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1151 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1156 /****************************************************************************
1157 ****************************************************************************/
1159 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1165 printf("Printer Driver Info 5:\n");
1166 printf("\tVersion: [%x]\n", r
->version
);
1167 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1168 printf("\tArchitecture: [%s]\n", r
->architecture
);
1169 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1170 printf("\tDatafile: [%s]\n", r
->data_file
);
1171 printf("\tConfigfile: [%s]\n", r
->config_file
);
1172 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1173 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1174 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1178 /****************************************************************************
1179 ****************************************************************************/
1181 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1189 printf("Printer Driver Info 6:\n");
1190 printf("\tVersion: [%x]\n", r
->version
);
1191 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1192 printf("\tArchitecture: [%s]\n", r
->architecture
);
1193 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1194 printf("\tDatafile: [%s]\n", r
->data_file
);
1195 printf("\tConfigfile: [%s]\n", r
->config_file
);
1196 printf("\tHelpfile: [%s]\n", r
->help_file
);
1198 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1199 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1202 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1203 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1205 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1206 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1209 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1210 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1211 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1212 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1213 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1214 printf("\tProvider: [%s]\n", r
->provider
);
1219 /****************************************************************************
1220 ****************************************************************************/
1222 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1230 printf("Printer Driver Info 8:\n");
1231 printf("\tVersion: [%x]\n", r
->version
);
1232 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1233 printf("\tArchitecture: [%s]\n", r
->architecture
);
1234 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1235 printf("\tDatafile: [%s]\n", r
->data_file
);
1236 printf("\tConfigfile: [%s]\n", r
->config_file
);
1237 printf("\tHelpfile: [%s]\n", r
->help_file
);
1238 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1239 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1241 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1242 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1245 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1246 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1249 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1250 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1251 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1252 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1253 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1254 printf("\tProvider: [%s]\n", r
->provider
);
1255 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1256 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1257 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1258 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1260 printf("\tInf Path: [%s]\n", r
->inf_path
);
1261 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1262 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1263 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1265 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1266 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1267 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1272 /****************************************************************************
1273 ****************************************************************************/
1275 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1276 TALLOC_CTX
*mem_ctx
,
1277 int argc
, const char **argv
)
1279 struct policy_handle pol
;
1282 const char *printername
;
1284 bool success
= false;
1285 union spoolss_DriverInfo info
;
1286 uint32_t server_major_version
;
1287 uint32_t server_minor_version
;
1288 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1290 if ((argc
== 1) || (argc
> 3)) {
1291 printf("Usage: %s <printername> [level]\n", argv
[0]);
1295 /* get the arguments need to open the printer handle */
1297 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1300 level
= atoi(argv
[2]);
1303 /* Open a printer handle */
1305 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1309 if (!W_ERROR_IS_OK(werror
)) {
1310 printf("Error opening printer handle for %s!\n", printername
);
1314 /* loop through and print driver info level for each architecture */
1316 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1318 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1320 archi_table
[i
].long_archi
,
1323 archi_table
[i
].version
,
1326 &server_major_version
,
1327 &server_minor_version
);
1328 if (!W_ERROR_IS_OK(werror
)) {
1332 /* need at least one success */
1336 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1340 display_print_driver1(&info
.info1
);
1343 display_print_driver2(&info
.info2
);
1346 display_print_driver3(&info
.info3
);
1349 display_print_driver4(&info
.info4
);
1352 display_print_driver5(&info
.info5
);
1355 display_print_driver6(&info
.info6
);
1358 display_print_driver8(&info
.info8
);
1361 printf("unknown info level %d\n", level
);
1368 if (is_valid_policy_hnd(&pol
)) {
1370 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
1380 /****************************************************************************
1381 ****************************************************************************/
1383 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1384 TALLOC_CTX
*mem_ctx
,
1385 const char *architecture
,
1390 union spoolss_DriverInfo
*info
= NULL
;
1393 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1394 cli
->srv_name_slash
,
1401 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1402 printf("Server does not support environment [%s]\n",
1411 if (!W_ERROR_IS_OK(werror
)) {
1412 printf("Error getting driver for environment [%s] - %s\n",
1413 architecture
, win_errstr(werror
));
1417 printf("\n[%s]\n", architecture
);
1421 for (j
=0; j
< count
; j
++) {
1422 display_print_driver1(&info
[j
].info1
);
1426 for (j
=0; j
< count
; j
++) {
1427 display_print_driver2(&info
[j
].info2
);
1431 for (j
=0; j
< count
; j
++) {
1432 display_print_driver3(&info
[j
].info3
);
1436 for (j
=0; j
< count
; j
++) {
1437 display_print_driver4(&info
[j
].info4
);
1441 for (j
=0; j
< count
; j
++) {
1442 display_print_driver5(&info
[j
].info5
);
1446 for (j
=0; j
< count
; j
++) {
1447 display_print_driver6(&info
[j
].info6
);
1451 for (j
=0; j
< count
; j
++) {
1452 display_print_driver8(&info
[j
].info8
);
1456 printf("unknown info level %d\n", level
);
1457 return WERR_INVALID_LEVEL
;
1463 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1464 TALLOC_CTX
*mem_ctx
,
1465 int argc
, const char **argv
)
1467 WERROR werror
= WERR_OK
;
1470 const char *architecture
= NULL
;
1473 printf("Usage: enumdrivers [level] [architecture]\n");
1478 level
= atoi(argv
[1]);
1482 architecture
= argv
[2];
1486 return enum_driver_by_architecture(cli
, mem_ctx
,
1491 /* loop through and print driver info level for each architecture */
1492 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1493 /* check to see if we already asked for this architecture string */
1495 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1499 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1500 archi_table
[i
].long_archi
,
1502 if (!W_ERROR_IS_OK(werror
)) {
1510 /****************************************************************************
1511 ****************************************************************************/
1513 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1515 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1518 /****************************************************************************
1519 ****************************************************************************/
1521 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1522 TALLOC_CTX
*mem_ctx
,
1523 int argc
, const char **argv
)
1527 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1530 union spoolss_DriverDirectoryInfo info
;
1532 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1535 printf("Usage: %s [environment]\n", argv
[0]);
1539 /* Get the arguments need to open the printer handle */
1545 /* Get the directory. Only use Info level 1 */
1547 status
= dcerpc_spoolss_GetPrinterDriverDirectory(b
, mem_ctx
,
1548 cli
->srv_name_slash
,
1556 if (!NT_STATUS_IS_OK(status
)) {
1557 return ntstatus_to_werror(status
);
1559 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1561 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1563 status
= dcerpc_spoolss_GetPrinterDriverDirectory(b
, mem_ctx
,
1564 cli
->srv_name_slash
,
1572 if (!NT_STATUS_IS_OK(status
)) {
1573 return ntstatus_to_werror(status
);
1577 if (W_ERROR_IS_OK(result
)) {
1578 display_printdriverdir_1(&info
.info1
);
1584 /****************************************************************************
1585 ****************************************************************************/
1587 static WERROR
cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client
*cli
,
1588 TALLOC_CTX
*mem_ctx
,
1589 int argc
, const char **argv
)
1593 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1596 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1597 const char *package_id
= "";
1598 const char *cab
= NULL
;
1601 printf("Usage: %s [environment] [package_id]\n", argv
[0]);
1605 /* Get the arguments need to open the printer handle */
1612 package_id
= argv
[2];
1616 cab
= talloc_zero_array(mem_ctx
, char, offered
);
1618 return WERR_NOT_ENOUGH_MEMORY
;
1620 status
= dcerpc_spoolss_GetPrinterDriverPackagePath(b
, mem_ctx
,
1621 cli
->srv_name_slash
,
1629 if (!NT_STATUS_IS_OK(status
)) {
1630 return ntstatus_to_werror(status
);
1633 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult
)), WERR_INSUFFICIENT_BUFFER
)) {
1635 cab
= talloc_zero_array(mem_ctx
, char, offered
);
1637 return WERR_NOT_ENOUGH_MEMORY
;
1639 status
= dcerpc_spoolss_GetPrinterDriverPackagePath(b
, mem_ctx
,
1640 cli
->srv_name_slash
,
1648 if (!NT_STATUS_IS_OK(status
)) {
1649 return ntstatus_to_werror(status
);
1653 return W_ERROR(WIN32_FROM_HRESULT(hresult
));
1657 /****************************************************************************
1658 ****************************************************************************/
1660 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1661 struct spoolss_AddDriverInfo3
*info
,
1667 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1669 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1671 info
->version
= archi_table
[i
].version
;
1672 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1677 if (archi_table
[i
].long_archi
== NULL
)
1679 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1686 /**************************************************************************
1687 wrapper for strtok to get the next parameter from a delimited list.
1688 Needed to handle the empty parameter string denoted by "NULL"
1689 *************************************************************************/
1691 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1692 const char *delim
, const char **dest
,
1697 /* get the next token */
1698 ptr
= strtok_r(str
, delim
, saveptr
);
1700 /* a string of 'NULL' is used to represent an empty
1701 parameter because two consecutive delimiters
1702 will not return an empty string. See man strtok(3)
1704 if (ptr
&& (strcasecmp_m(ptr
, "NULL") == 0)) {
1709 *dest
= talloc_strdup(mem_ctx
, ptr
);
1715 /********************************************************************************
1716 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1717 string in the form of
1718 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1719 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1720 <Default Data Type>:<Comma Separated list of Files>
1721 *******************************************************************************/
1723 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1728 char *saveptr
= NULL
;
1729 struct spoolss_StringArray
*deps
;
1730 const char **file_array
= NULL
;
1733 /* fill in the UNISTR fields */
1734 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1735 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1736 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1737 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1738 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1739 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1740 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1742 /* <Comma Separated List of Dependent Files> */
1743 /* save the beginning of the string */
1744 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1747 /* begin to strip out each filename */
1748 str
= strtok_r(str
, ",", &saveptr
);
1750 /* no dependent files, we are done */
1755 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1760 while (str
!= NULL
) {
1762 ok
= add_string_to_array(deps
, str
, &file_array
, &count
);
1766 str
= strtok_r(NULL
, ",", &saveptr
);
1769 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1770 if (!deps
->string
) {
1774 for (i
=0; i
< count
; i
++) {
1775 deps
->string
[i
] = file_array
[i
];
1778 r
->dependent_files
= deps
;
1783 /****************************************************************************
1784 ****************************************************************************/
1786 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1787 TALLOC_CTX
*mem_ctx
,
1788 int argc
, const char **argv
)
1793 struct spoolss_AddDriverInfoCtr info_ctr
;
1794 struct spoolss_AddDriverInfo3 info3
;
1797 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1799 /* parse the command arguments */
1800 if (argc
!= 3 && argc
!= 4)
1802 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1803 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1804 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1805 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1806 printf ("\t[version]\n");
1811 /* Fill in the spoolss_AddDriverInfo3 struct */
1814 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1816 printf ("Error Unknown architecture [%s]\n", argv
[1]);
1817 return WERR_INVALID_PARAMETER
;
1820 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1822 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1823 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1825 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1826 return WERR_INVALID_PARAMETER
;
1829 /* if printer driver version specified, override the default version
1830 * used by the architecture. This allows installation of Windows
1831 * 2000 (version 3) printer drivers. */
1834 info3
.version
= atoi(argv
[3]);
1838 info_ctr
.level
= level
;
1839 info_ctr
.info
.info3
= &info3
;
1841 status
= dcerpc_spoolss_AddPrinterDriver(b
, mem_ctx
,
1842 cli
->srv_name_slash
,
1845 if (!NT_STATUS_IS_OK(status
)) {
1846 return ntstatus_to_werror(status
);
1848 if (W_ERROR_IS_OK(result
)) {
1849 printf ("Printer Driver %s successfully installed.\n",
1857 /****************************************************************************
1858 ****************************************************************************/
1860 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1861 TALLOC_CTX
*mem_ctx
,
1862 int argc
, const char **argv
)
1865 struct spoolss_SetPrinterInfoCtr info_ctr
;
1866 struct spoolss_SetPrinterInfo2 info2
;
1868 /* parse the command arguments */
1871 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1875 /* Fill in the DRIVER_INFO_2 struct */
1878 info2
.printername
= argv
[1];
1879 info2
.drivername
= argv
[3];
1880 info2
.sharename
= argv
[2];
1881 info2
.portname
= argv
[4];
1882 info2
.comment
= "Created by rpcclient";
1883 info2
.printprocessor
= "winprint";
1884 info2
.datatype
= "RAW";
1885 info2
.devmode_ptr
= 0;
1886 info2
.secdesc_ptr
= 0;
1887 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1889 info2
.defaultpriority
= 0;
1890 info2
.starttime
= 0;
1891 info2
.untiltime
= 0;
1893 /* These three fields must not be used by AddPrinter()
1894 as defined in the MS Platform SDK documentation..
1898 info2.averageppm = 0;
1902 info_ctr
.info
.info2
= &info2
;
1904 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1906 if (W_ERROR_IS_OK(result
))
1907 printf ("Printer %s successfully installed.\n", argv
[1]);
1912 /****************************************************************************
1913 ****************************************************************************/
1915 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1916 TALLOC_CTX
*mem_ctx
,
1917 int argc
, const char **argv
)
1919 struct policy_handle pol
;
1923 const char *printername
;
1924 union spoolss_PrinterInfo info
;
1925 struct spoolss_SetPrinterInfoCtr info_ctr
;
1926 struct spoolss_SetPrinterInfo2 info2
;
1927 struct spoolss_DevmodeContainer devmode_ctr
;
1928 struct sec_desc_buf secdesc_ctr
;
1929 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
1931 ZERO_STRUCT(devmode_ctr
);
1932 ZERO_STRUCT(secdesc_ctr
);
1934 /* parse the command arguments */
1937 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1941 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1943 /* Get a printer handle */
1945 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1949 if (!W_ERROR_IS_OK(result
))
1952 /* Get printer info */
1954 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1959 if (!W_ERROR_IS_OK(result
)) {
1960 printf ("Unable to retrieve printer information!\n");
1964 /* Set the printer driver */
1966 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
1967 info2
.drivername
= argv
[2];
1970 info_ctr
.info
.info2
= &info2
;
1972 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
1979 if (!NT_STATUS_IS_OK(status
)) {
1980 result
= ntstatus_to_werror(status
);
1983 if (!W_ERROR_IS_OK(result
)) {
1984 printf("SetPrinter call failed!\n");
1988 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1993 if (is_valid_policy_hnd(&pol
)) {
1995 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
2002 /****************************************************************************
2003 ****************************************************************************/
2005 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
2006 TALLOC_CTX
*mem_ctx
,
2007 int argc
, const char **argv
)
2009 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
2011 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2016 const char *arch
= NULL
;
2017 uint32_t delete_flags
= 0;
2019 /* parse the command arguments */
2020 if (argc
< 2 || argc
> 5) {
2021 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv
[0]);
2028 vers
= atoi(argv
[3]);
2029 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
2032 delete_flags
= atoi(argv
[4]);
2034 /* delete the driver for all architectures */
2035 for (i
=0; archi_table
[i
].long_archi
; i
++) {
2037 if (arch
&& !strequal(archi_table
[i
].long_archi
, arch
))
2040 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
2043 /* make the call to remove the driver */
2044 status
= dcerpc_spoolss_DeletePrinterDriverEx(b
, mem_ctx
,
2045 cli
->srv_name_slash
,
2046 archi_table
[i
].long_archi
,
2049 archi_table
[i
].version
,
2051 if (!NT_STATUS_IS_OK(status
)) {
2052 return ntstatus_to_werror(status
);
2054 if ( !W_ERROR_IS_OK(result
) )
2056 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
2057 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2058 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
2063 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
2064 archi_table
[i
].long_archi
, archi_table
[i
].version
);
2073 /****************************************************************************
2074 ****************************************************************************/
2076 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
2077 TALLOC_CTX
*mem_ctx
,
2078 int argc
, const char **argv
)
2080 WERROR result
= WERR_OK
;
2083 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2085 /* parse the command arguments */
2087 printf ("Usage: %s <driver>\n", argv
[0]);
2091 /* delete the driver for all architectures */
2092 for (i
=0; archi_table
[i
].long_archi
; i
++) {
2095 /* make the call to remove the driver */
2096 status
= dcerpc_spoolss_DeletePrinterDriver(b
, mem_ctx
,
2097 cli
->srv_name_slash
,
2098 archi_table
[i
].long_archi
,
2101 if (!NT_STATUS_IS_OK(status
)) {
2102 result
= ntstatus_to_werror(status
);
2105 if ( !W_ERROR_IS_OK(result
) ) {
2106 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
2107 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2108 argv
[1], archi_table
[i
].long_archi
,
2109 win_errstr(result
));
2112 printf ("Driver %s removed for arch [%s].\n", argv
[1],
2113 archi_table
[i
].long_archi
);
2120 /****************************************************************************
2121 ****************************************************************************/
2123 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
2124 TALLOC_CTX
*mem_ctx
,
2125 int argc
, const char **argv
)
2129 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
2132 union spoolss_PrintProcessorDirectoryInfo info
;
2134 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2136 /* parse the command arguments */
2138 printf ("Usage: %s [environment]\n", argv
[0]);
2143 environment
= argv
[1];
2146 status
= dcerpc_spoolss_GetPrintProcessorDirectory(b
, mem_ctx
,
2147 cli
->srv_name_slash
,
2155 if (!NT_STATUS_IS_OK(status
)) {
2156 return ntstatus_to_werror(status
);
2158 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
2160 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2162 status
= dcerpc_spoolss_GetPrintProcessorDirectory(b
, mem_ctx
,
2163 cli
->srv_name_slash
,
2171 if (!NT_STATUS_IS_OK(status
)) {
2172 return ntstatus_to_werror(status
);
2176 if (W_ERROR_IS_OK(result
)) {
2177 printf("%s\n", info
.info1
.directory_name
);
2183 /****************************************************************************
2184 ****************************************************************************/
2186 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2187 int argc
, const char **argv
)
2189 struct policy_handle handle
;
2192 const char *printername
;
2193 struct spoolss_AddFormInfoCtr info_ctr
;
2194 struct spoolss_AddFormInfo1 info1
;
2195 struct spoolss_AddFormInfo2 info2
;
2197 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2199 /* Parse the command arguments */
2201 if (argc
< 3 || argc
> 5) {
2202 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2206 /* Get a printer handle */
2208 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2210 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2214 if (!W_ERROR_IS_OK(werror
))
2217 /* Dummy up some values for the form data */
2220 level
= atoi(argv
[3]);
2225 info1
.flags
= SPOOLSS_FORM_USER
;
2226 info1
.form_name
= argv
[2];
2227 info1
.size
.width
= 100;
2228 info1
.size
.height
= 100;
2229 info1
.area
.left
= 0;
2230 info1
.area
.top
= 10;
2231 info1
.area
.right
= 20;
2232 info1
.area
.bottom
= 30;
2235 info_ctr
.info
.info1
= &info1
;
2239 info2
.flags
= SPOOLSS_FORM_USER
;
2240 info2
.form_name
= argv
[2];
2241 info2
.size
.width
= 100;
2242 info2
.size
.height
= 100;
2243 info2
.area
.left
= 0;
2244 info2
.area
.top
= 10;
2245 info2
.area
.right
= 20;
2246 info2
.area
.bottom
= 30;
2247 info2
.keyword
= argv
[2];
2248 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2249 info2
.mui_dll
= NULL
;
2250 info2
.ressource_id
= 0;
2251 info2
.display_name
= argv
[2];
2255 info_ctr
.info
.info2
= &info2
;
2259 werror
= WERR_INVALID_PARAMETER
;
2265 status
= dcerpc_spoolss_AddForm(b
, mem_ctx
,
2269 if (!NT_STATUS_IS_OK(status
)) {
2270 werror
= ntstatus_to_werror(status
);
2274 if (is_valid_policy_hnd(&handle
)) {
2276 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2282 /****************************************************************************
2283 ****************************************************************************/
2285 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2286 int argc
, const char **argv
)
2288 struct policy_handle handle
;
2291 const char *printername
;
2292 struct spoolss_AddFormInfoCtr info_ctr
;
2293 struct spoolss_AddFormInfo1 info1
;
2294 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2296 /* Parse the command arguments */
2299 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2303 /* Get a printer handle */
2305 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2307 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2309 SEC_FLAG_MAXIMUM_ALLOWED
,
2311 if (!W_ERROR_IS_OK(werror
))
2314 /* Dummy up some values for the form data */
2316 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2317 info1
.size
.width
= 100;
2318 info1
.size
.height
= 100;
2319 info1
.area
.left
= 0;
2320 info1
.area
.top
= 1000;
2321 info1
.area
.right
= 2000;
2322 info1
.area
.bottom
= 3000;
2323 info1
.form_name
= argv
[2];
2325 info_ctr
.info
.info1
= &info1
;
2330 status
= dcerpc_spoolss_SetForm(b
, mem_ctx
,
2335 if (!NT_STATUS_IS_OK(status
)) {
2336 werror
= ntstatus_to_werror(status
);
2340 if (is_valid_policy_hnd(&handle
)) {
2342 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2348 /****************************************************************************
2349 ****************************************************************************/
2351 static const char *get_form_flag(int form_flag
)
2353 switch (form_flag
) {
2354 case SPOOLSS_FORM_USER
:
2356 case SPOOLSS_FORM_BUILTIN
:
2357 return "FORM_BUILTIN";
2358 case SPOOLSS_FORM_PRINTER
:
2359 return "FORM_PRINTER";
2365 /****************************************************************************
2366 ****************************************************************************/
2368 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2371 "\tflag: %s (%d)\n" \
2372 "\twidth: %d, length: %d\n" \
2373 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2374 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2375 r
->size
.width
, r
->size
.height
,
2376 r
->area
.left
, r
->area
.right
,
2377 r
->area
.top
, r
->area
.bottom
);
2380 /****************************************************************************
2381 ****************************************************************************/
2383 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2386 "\tflag: %s (%d)\n" \
2387 "\twidth: %d, length: %d\n" \
2388 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2389 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2390 r
->size
.width
, r
->size
.height
,
2391 r
->area
.left
, r
->area
.right
,
2392 r
->area
.top
, r
->area
.bottom
);
2393 printf("\tkeyword: %s\n", r
->keyword
);
2394 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2395 printf("\tmui_dll: %s\n", r
->mui_dll
);
2396 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2397 printf("\tdisplay_name: %s\n", r
->display_name
);
2398 printf("\tlang_id: %d\n", r
->lang_id
);
2402 /****************************************************************************
2403 ****************************************************************************/
2405 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2406 int argc
, const char **argv
)
2408 struct policy_handle handle
;
2411 const char *printername
;
2413 uint32_t offered
= 0;
2414 union spoolss_FormInfo info
;
2417 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2419 /* Parse the command arguments */
2421 if (argc
< 3 || argc
> 5) {
2422 printf ("Usage: %s <printer> <formname> [level]\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
))
2438 level
= atoi(argv
[3]);
2443 status
= dcerpc_spoolss_GetForm(b
, mem_ctx
,
2452 if (!NT_STATUS_IS_OK(status
)) {
2453 werror
= ntstatus_to_werror(status
);
2456 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2457 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2459 status
= dcerpc_spoolss_GetForm(b
, mem_ctx
,
2468 if (!NT_STATUS_IS_OK(status
)) {
2469 werror
= ntstatus_to_werror(status
);
2474 if (!W_ERROR_IS_OK(werror
)) {
2480 display_form_info1(&info
.info1
);
2483 display_form_info2(&info
.info2
);
2488 if (is_valid_policy_hnd(&handle
)) {
2490 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2496 /****************************************************************************
2497 ****************************************************************************/
2499 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2500 TALLOC_CTX
*mem_ctx
, int argc
,
2503 struct policy_handle handle
;
2506 const char *printername
;
2507 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2509 /* Parse the command arguments */
2512 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2516 /* Get a printer handle */
2518 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2520 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2522 SEC_FLAG_MAXIMUM_ALLOWED
,
2524 if (!W_ERROR_IS_OK(werror
))
2527 /* Delete the form */
2529 status
= dcerpc_spoolss_DeleteForm(b
, mem_ctx
,
2533 if (!NT_STATUS_IS_OK(status
)) {
2534 werror
= ntstatus_to_werror(status
);
2539 if (is_valid_policy_hnd(&handle
)) {
2541 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2547 /****************************************************************************
2548 ****************************************************************************/
2550 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2551 TALLOC_CTX
*mem_ctx
, int argc
,
2554 struct policy_handle handle
;
2556 const char *printername
;
2557 uint32_t num_forms
, level
= 1, i
;
2558 union spoolss_FormInfo
*forms
;
2559 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2561 /* Parse the command arguments */
2563 if (argc
< 2 || argc
> 4) {
2564 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2568 /* Get a printer handle */
2570 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2572 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2574 SEC_FLAG_MAXIMUM_ALLOWED
,
2576 if (!W_ERROR_IS_OK(werror
))
2580 level
= atoi(argv
[2]);
2583 /* Enumerate forms */
2585 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2592 if (!W_ERROR_IS_OK(werror
))
2595 /* Display output */
2597 for (i
= 0; i
< num_forms
; i
++) {
2600 display_form_info1(&forms
[i
].info1
);
2603 display_form_info2(&forms
[i
].info2
);
2609 if (is_valid_policy_hnd(&handle
)) {
2611 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
2617 /****************************************************************************
2618 ****************************************************************************/
2620 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2621 TALLOC_CTX
*mem_ctx
,
2622 int argc
, const char **argv
)
2626 const char *printername
;
2627 struct policy_handle pol
= { 0, };
2628 union spoolss_PrinterInfo info
;
2629 enum winreg_Type type
;
2630 union spoolss_PrinterData data
;
2632 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2635 /* parse the command arguments */
2637 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2638 " <value> <data>\n",
2643 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2647 if (strequal(argv
[2], "string")) {
2651 if (strequal(argv
[2], "binary")) {
2655 if (strequal(argv
[2], "dword")) {
2659 if (strequal(argv
[2], "multistring")) {
2660 type
= REG_MULTI_SZ
;
2663 if (type
== REG_NONE
) {
2664 printf("Unknown data type: %s\n", argv
[2]);
2665 result
= WERR_INVALID_PARAMETER
;
2669 /* get a printer handle */
2671 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2673 SEC_FLAG_MAXIMUM_ALLOWED
,
2675 if (!W_ERROR_IS_OK(result
)) {
2679 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2684 if (!W_ERROR_IS_OK(result
)) {
2688 printf("%s\n", current_timestring(mem_ctx
, true));
2689 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2691 /* Set the printer data */
2695 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2696 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2699 data
.value
= smb_strtoul(argv
[4],
2705 result
= WERR_INVALID_PARAMETER
;
2711 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2713 case REG_MULTI_SZ
: {
2716 const char **strings
= NULL
;
2720 for (i
=4; i
<argc
; i
++) {
2721 if (strcmp(argv
[i
], "NULL") == 0) {
2724 if (!add_string_to_array(mem_ctx
, argv
[i
],
2727 result
= WERR_NOT_ENOUGH_MEMORY
;
2731 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2732 if (!data
.string_array
) {
2733 result
= WERR_NOT_ENOUGH_MEMORY
;
2736 for (i
=0; i
< num_strings
; i
++) {
2737 data
.string_array
[i
] = strings
[i
];
2742 printf("Unknown data type: %s\n", argv
[2]);
2743 result
= WERR_INVALID_PARAMETER
;
2747 result
= push_spoolss_PrinterData(mem_ctx
, &blob
, type
, &data
);
2748 if (!W_ERROR_IS_OK(result
)) {
2752 status
= dcerpc_spoolss_SetPrinterData(b
, mem_ctx
,
2754 argv
[3], /* value_name */
2759 if (!NT_STATUS_IS_OK(status
)) {
2760 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2761 result
= ntstatus_to_werror(status
);
2764 if (!W_ERROR_IS_OK(result
)) {
2765 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2768 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2770 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2775 if (!W_ERROR_IS_OK(result
)) {
2779 printf("%s\n", current_timestring(mem_ctx
, true));
2780 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2784 if (is_valid_policy_hnd(&pol
)) {
2786 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &_result
);
2792 /****************************************************************************
2793 ****************************************************************************/
2795 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2797 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2798 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2802 /****************************************************************************
2803 ****************************************************************************/
2805 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2807 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2808 r
->position
, r
->job_id
,
2809 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2810 r
->total_pages
, r
->size
);
2813 /****************************************************************************
2814 ****************************************************************************/
2816 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2818 printf("jobid[%d], next_jobid[%d]\n",
2819 r
->job_id
, r
->next_job_id
);
2822 /****************************************************************************
2823 ****************************************************************************/
2825 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2827 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2828 r
->position
, r
->job_id
,
2829 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2830 r
->total_pages
, r
->size
, r
->size_high
);
2833 /****************************************************************************
2834 ****************************************************************************/
2836 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2837 TALLOC_CTX
*mem_ctx
, int argc
,
2841 uint32_t level
= 1, count
, i
;
2842 const char *printername
;
2843 struct policy_handle hnd
;
2844 union spoolss_JobInfo
*info
;
2845 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2847 if (argc
< 2 || argc
> 3) {
2848 printf("Usage: %s printername [level]\n", argv
[0]);
2853 level
= atoi(argv
[2]);
2856 /* Open printer handle */
2858 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2860 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2862 SEC_FLAG_MAXIMUM_ALLOWED
,
2864 if (!W_ERROR_IS_OK(result
))
2867 /* Enumerate ports */
2869 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2877 if (!W_ERROR_IS_OK(result
)) {
2881 for (i
= 0; i
< count
; i
++) {
2884 display_job_info1(&info
[i
].info1
);
2887 display_job_info2(&info
[i
].info2
);
2890 d_printf("unknown info level %d\n", level
);
2896 if (is_valid_policy_hnd(&hnd
)) {
2898 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
2904 /****************************************************************************
2905 ****************************************************************************/
2907 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2908 TALLOC_CTX
*mem_ctx
, int argc
,
2912 const char *printername
;
2913 struct policy_handle hnd
;
2916 union spoolss_JobInfo info
;
2917 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
2919 if (argc
< 3 || argc
> 4) {
2920 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2924 job_id
= atoi(argv
[2]);
2927 level
= atoi(argv
[3]);
2930 /* Open printer handle */
2932 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2934 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2936 SEC_FLAG_MAXIMUM_ALLOWED
,
2938 if (!W_ERROR_IS_OK(result
)) {
2942 /* Enumerate ports */
2944 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2951 if (!W_ERROR_IS_OK(result
)) {
2957 display_job_info1(&info
.info1
);
2960 display_job_info2(&info
.info2
);
2963 display_job_info3(&info
.info3
);
2966 display_job_info4(&info
.info4
);
2969 d_printf("unknown info level %d\n", level
);
2974 if (is_valid_policy_hnd(&hnd
)) {
2976 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
2982 /****************************************************************************
2983 ****************************************************************************/
2987 enum spoolss_JobControl val
;
2989 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE
},
2990 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME
},
2991 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL
},
2992 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART
},
2993 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE
},
2994 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
},
2995 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
},
2996 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN
},
2997 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE
}
3000 static enum spoolss_JobControl
parse_setjob_command(const char *cmd
)
3004 for (i
= 0; i
< sizeof(cmdvals
)/sizeof(cmdvals
[0]); i
++) {
3005 if (strequal(cmdvals
[i
].name
, cmd
)) {
3006 return cmdvals
[i
].val
;
3009 return (enum spoolss_JobControl
)atoi(cmd
);
3012 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
3013 TALLOC_CTX
*mem_ctx
, int argc
,
3018 const char *printername
;
3019 struct policy_handle hnd
;
3021 enum spoolss_JobControl command
;
3022 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3025 printf("Usage: %s printername job_id command\n", argv
[0]);
3026 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3027 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3031 job_id
= atoi(argv
[2]);
3032 command
= parse_setjob_command(argv
[3]);
3034 /* Open printer handle */
3036 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3038 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3040 SEC_FLAG_MAXIMUM_ALLOWED
,
3042 if (!W_ERROR_IS_OK(result
)) {
3048 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3054 if (!NT_STATUS_IS_OK(status
)) {
3055 result
= ntstatus_to_werror(status
);
3058 if (!W_ERROR_IS_OK(result
)) {
3063 if (is_valid_policy_hnd(&hnd
)) {
3065 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3071 /****************************************************************************
3072 ****************************************************************************/
3074 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
3075 TALLOC_CTX
*mem_ctx
, int argc
,
3080 const char *printername
;
3081 struct policy_handle hnd
;
3082 uint32_t value_needed
;
3083 enum winreg_Type type
;
3084 uint32_t data_needed
;
3085 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3086 struct spoolss_EnumPrinterData r
;
3089 printf("Usage: %s printername\n", argv
[0]);
3093 /* Open printer handle */
3095 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3097 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3099 SEC_FLAG_MAXIMUM_ALLOWED
,
3101 if (!W_ERROR_IS_OK(result
)) {
3105 /* Enumerate data */
3108 r
.in
.enum_index
= 0;
3109 r
.in
.value_offered
= 0;
3110 r
.in
.data_offered
= 0;
3111 r
.out
.value_name
= NULL
;
3112 r
.out
.value_needed
= &value_needed
;
3115 r
.out
.data_needed
= &data_needed
;
3117 status
= dcerpc_spoolss_EnumPrinterData_r(b
, mem_ctx
, &r
);
3118 if (!NT_STATUS_IS_OK(status
)) {
3119 result
= ntstatus_to_werror(status
);
3123 if (!W_ERROR_IS_OK(r
.out
.result
)) {
3124 result
= r
.out
.result
;
3128 r
.in
.data_offered
= *r
.out
.data_needed
;
3129 r
.in
.value_offered
= *r
.out
.value_needed
;
3130 r
.out
.data
= talloc_zero_array(mem_ctx
, uint8_t, r
.in
.data_offered
);
3131 r
.out
.value_name
= talloc_zero_array(mem_ctx
, char, r
.in
.value_offered
);
3135 status
= dcerpc_spoolss_EnumPrinterData_r(b
, mem_ctx
, &r
);
3136 if (!NT_STATUS_IS_OK(status
)) {
3137 result
= ntstatus_to_werror(status
);
3141 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
3148 display_reg_value(r
.out
.value_name
, *r
.out
.type
,
3149 data_blob_const(r
.out
.data
, r
.in
.data_offered
));
3151 } while (W_ERROR_IS_OK(r
.out
.result
));
3154 if (is_valid_policy_hnd(&hnd
)) {
3156 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3162 /****************************************************************************
3163 ****************************************************************************/
3165 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
3166 TALLOC_CTX
*mem_ctx
, int argc
,
3171 const char *printername
;
3172 struct policy_handle hnd
;
3174 struct spoolss_PrinterEnumValues
*info
;
3175 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3178 printf("Usage: %s printername <keyname>\n", argv
[0]);
3182 /* Open printer handle */
3184 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3186 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3188 SEC_FLAG_MAXIMUM_ALLOWED
,
3190 if (!W_ERROR_IS_OK(result
)) {
3194 /* Enumerate subkeys */
3196 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
3202 if (!W_ERROR_IS_OK(result
)) {
3206 for (i
=0; i
< count
; i
++) {
3207 display_printer_data(info
[i
].value_name
,
3210 info
[i
].data
->length
);
3214 if (is_valid_policy_hnd(&hnd
)) {
3216 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3222 /****************************************************************************
3223 ****************************************************************************/
3225 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
3226 TALLOC_CTX
*mem_ctx
, int argc
,
3230 const char *printername
;
3231 const char *keyname
= NULL
;
3232 struct policy_handle hnd
;
3233 const char **key_buffer
= NULL
;
3235 uint32_t offered
= 0;
3236 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3238 if (argc
< 2 || argc
> 4) {
3239 printf("Usage: %s printername [keyname] [offered]\n", argv
[0]);
3250 offered
= atoi(argv
[3]);
3253 /* Open printer handle */
3255 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3257 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3259 SEC_FLAG_MAXIMUM_ALLOWED
,
3261 if (!W_ERROR_IS_OK(result
)) {
3265 /* Enumerate subkeys */
3267 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
3273 if (!W_ERROR_IS_OK(result
)) {
3277 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
3278 printf("%s\n", key_buffer
[i
]);
3283 if (is_valid_policy_hnd(&hnd
)) {
3285 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3291 /****************************************************************************
3292 ****************************************************************************/
3294 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
3295 TALLOC_CTX
*mem_ctx
, int argc
,
3298 const char *printername
;
3299 const char *clientname
;
3300 struct policy_handle hnd
= { 0, };
3303 struct spoolss_NotifyOption option
;
3304 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3307 printf("Usage: %s printername\n", argv
[0]);
3314 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3316 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3318 SEC_FLAG_MAXIMUM_ALLOWED
,
3320 if (!W_ERROR_IS_OK(result
)) {
3321 printf("Error opening %s\n", argv
[1]);
3325 /* Create spool options */
3330 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3331 if (option
.types
== NULL
) {
3332 result
= WERR_NOT_ENOUGH_MEMORY
;
3336 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3337 option
.types
[0].count
= 1;
3338 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3339 if (option
.types
[0].fields
== NULL
) {
3340 result
= WERR_NOT_ENOUGH_MEMORY
;
3343 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3345 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3346 option
.types
[1].count
= 1;
3347 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3348 if (option
.types
[1].fields
== NULL
) {
3349 result
= WERR_NOT_ENOUGH_MEMORY
;
3352 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3354 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", lp_netbios_name());
3356 result
= WERR_NOT_ENOUGH_MEMORY
;
3362 status
= dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b
, mem_ctx
,
3370 if (!NT_STATUS_IS_OK(status
)) {
3371 result
= ntstatus_to_werror(status
);
3374 if (!W_ERROR_IS_OK(result
)) {
3375 printf("Error rffpcnex %s\n", argv
[1]);
3380 if (is_valid_policy_hnd(&hnd
)) {
3382 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &hnd
, &_result
);
3388 /****************************************************************************
3389 ****************************************************************************/
3391 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3392 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3394 union spoolss_PrinterInfo info1
, info2
;
3396 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3398 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3399 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3404 if ( !W_ERROR_IS_OK(werror
) ) {
3405 printf("failed (%s)\n", win_errstr(werror
));
3406 talloc_destroy(mem_ctx
);
3411 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3412 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3417 if ( !W_ERROR_IS_OK(werror
) ) {
3418 printf("failed (%s)\n", win_errstr(werror
));
3419 talloc_destroy(mem_ctx
);
3424 talloc_destroy(mem_ctx
);
3429 /****************************************************************************
3430 ****************************************************************************/
3432 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3433 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3435 union spoolss_PrinterInfo info1
, info2
;
3437 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3438 struct security_descriptor
*sd1
, *sd2
;
3442 printf("Retrieving printer security for %s...", cli1
->desthost
);
3443 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3448 if ( !W_ERROR_IS_OK(werror
) ) {
3449 printf("failed (%s)\n", win_errstr(werror
));
3455 printf("Retrieving printer security for %s...", cli2
->desthost
);
3456 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3461 if ( !W_ERROR_IS_OK(werror
) ) {
3462 printf("failed (%s)\n", win_errstr(werror
));
3471 sd1
= info1
.info3
.secdesc
;
3472 sd2
= info2
.info3
.secdesc
;
3474 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3475 printf("NULL secdesc!\n");
3480 if (!security_descriptor_equal( sd1
, sd2
) ) {
3481 printf("Security Descriptors *not* equal!\n");
3486 printf("Security descriptors match\n");
3489 talloc_destroy(mem_ctx
);
3494 /****************************************************************************
3495 ****************************************************************************/
3497 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3498 TALLOC_CTX
*mem_ctx
, int argc
,
3501 const char *printername
;
3502 char *printername_path
= NULL
;
3503 struct cli_state
*cli_server2
= NULL
;
3504 struct rpc_pipe_client
*cli2
= NULL
;
3505 struct policy_handle hPrinter1
, hPrinter2
;
3508 struct cli_credentials
*creds
= samba_cmdline_get_creds();
3511 printf("Usage: %s <printer> <server>\n", argv
[0]);
3515 printername
= argv
[1];
3517 /* first get the connection to the remote server */
3519 nt_status
= cli_full_connection_creds(&cli_server2
, lp_netbios_name(), argv
[2],
3523 CLI_FULL_CONNECTION_IPC
);
3524 if ( !NT_STATUS_IS_OK(nt_status
) )
3525 return WERR_GEN_FAILURE
;
3527 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
,
3529 if (!NT_STATUS_IS_OK(nt_status
)) {
3530 printf("failed to open spoolss pipe on server %s (%s)\n",
3531 argv
[2], nt_errstr(nt_status
));
3532 return WERR_GEN_FAILURE
;
3535 /* now open up both printers */
3537 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3539 printf("Opening %s...", printername_path
);
3541 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3545 if ( !W_ERROR_IS_OK(werror
) ) {
3546 printf("failed (%s)\n", win_errstr(werror
));
3551 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3553 printf("Opening %s...", printername_path
);
3554 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3558 if ( !W_ERROR_IS_OK(werror
) ) {
3559 printf("failed (%s)\n", win_errstr(werror
));
3564 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3565 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3567 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3574 printf("Closing printers...");
3577 dcerpc_spoolss_ClosePrinter(cli
->binding_handle
, mem_ctx
, &hPrinter1
, &_result
);
3578 dcerpc_spoolss_ClosePrinter(cli2
->binding_handle
, mem_ctx
, &hPrinter2
, &_result
);
3582 /* close the second remote connection */
3584 cli_shutdown( cli_server2
);
3588 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3590 printf("print_processor_name: %s\n", r
->print_processor_name
);
3593 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3594 TALLOC_CTX
*mem_ctx
, int argc
,
3598 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3599 uint32_t num_procs
, level
= 1, i
;
3600 union spoolss_PrintProcessorInfo
*procs
;
3602 /* Parse the command arguments */
3604 if (argc
< 1 || argc
> 4) {
3605 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3610 environment
= argv
[1];
3614 level
= atoi(argv
[2]);
3617 /* Enumerate Print Processors */
3619 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3620 cli
->srv_name_slash
,
3626 if (!W_ERROR_IS_OK(werror
))
3629 /* Display output */
3631 for (i
= 0; i
< num_procs
; i
++) {
3634 display_proc_info1(&procs
[i
].info1
);
3643 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3645 printf("name_array: %s\n", r
->name_array
);
3648 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3649 TALLOC_CTX
*mem_ctx
, int argc
,
3653 const char *print_processor_name
= "winprint";
3654 uint32_t num_procs
, level
= 1, i
;
3655 union spoolss_PrintProcDataTypesInfo
*procs
;
3657 /* Parse the command arguments */
3659 if (argc
< 1 || argc
> 4) {
3660 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3665 print_processor_name
= argv
[1];
3669 level
= atoi(argv
[2]);
3672 /* Enumerate Print Processor Data Types */
3674 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3675 cli
->srv_name_slash
,
3676 print_processor_name
,
3681 if (!W_ERROR_IS_OK(werror
))
3684 /* Display output */
3686 for (i
= 0; i
< num_procs
; i
++) {
3689 display_proc_data_types_info1(&procs
[i
].info1
);
3698 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3700 printf("monitor_name: %s\n", r
->monitor_name
);
3703 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3705 printf("monitor_name: %s\n", r
->monitor_name
);
3706 printf("environment: %s\n", r
->environment
);
3707 printf("dll_name: %s\n", r
->dll_name
);
3710 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3711 TALLOC_CTX
*mem_ctx
, int argc
,
3715 uint32_t count
, level
= 1, i
;
3716 union spoolss_MonitorInfo
*info
;
3718 /* Parse the command arguments */
3721 printf("Usage: %s [level]\n", argv
[0]);
3726 level
= atoi(argv
[1]);
3729 /* Enumerate Print Monitors */
3731 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3732 cli
->srv_name_slash
,
3737 if (!W_ERROR_IS_OK(werror
)) {
3741 /* Display output */
3743 for (i
= 0; i
< count
; i
++) {
3746 display_monitor1(&info
[i
].info1
);
3749 display_monitor2(&info
[i
].info2
);
3758 static WERROR
cmd_spoolss_create_printer_ic(struct rpc_pipe_client
*cli
,
3759 TALLOC_CTX
*mem_ctx
, int argc
,
3764 struct policy_handle handle
, gdi_handle
;
3765 const char *printername
;
3766 struct spoolss_DevmodeContainer devmode_ctr
;
3767 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3769 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3771 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3773 SEC_FLAG_MAXIMUM_ALLOWED
,
3775 if (!W_ERROR_IS_OK(result
)) {
3779 ZERO_STRUCT(devmode_ctr
);
3781 status
= dcerpc_spoolss_CreatePrinterIC(b
, mem_ctx
,
3786 if (!NT_STATUS_IS_OK(status
)) {
3787 result
= ntstatus_to_werror(status
);
3790 if (!W_ERROR_IS_OK(result
)) {
3795 if (is_valid_policy_hnd(&gdi_handle
)) {
3797 dcerpc_spoolss_DeletePrinterIC(b
, mem_ctx
, &gdi_handle
, &_result
);
3799 if (is_valid_policy_hnd(&handle
)) {
3801 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
3807 static WERROR
cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client
*cli
,
3808 TALLOC_CTX
*mem_ctx
, int argc
,
3813 struct policy_handle handle
, gdi_handle
;
3814 const char *printername
;
3815 struct spoolss_DevmodeContainer devmode_ctr
;
3816 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3820 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3822 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3824 SEC_FLAG_MAXIMUM_ALLOWED
,
3826 if (!W_ERROR_IS_OK(result
)) {
3830 ZERO_STRUCT(devmode_ctr
);
3832 status
= dcerpc_spoolss_CreatePrinterIC(b
, mem_ctx
,
3837 if (!NT_STATUS_IS_OK(status
)) {
3838 result
= ntstatus_to_werror(status
);
3841 if (!W_ERROR_IS_OK(result
)) {
3845 in
= data_blob_string_const("");
3846 out
= data_blob_talloc_zero(mem_ctx
, 4);
3848 status
= dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b
, mem_ctx
,
3856 if (!NT_STATUS_IS_OK(status
)) {
3857 result
= ntstatus_to_werror(status
);
3860 if (!W_ERROR_IS_OK(result
)) {
3864 count
= IVAL(out
.data
, 0);
3866 out
= data_blob_talloc_zero(mem_ctx
,
3867 count
* sizeof(struct UNIVERSAL_FONT_ID
) + 4);
3869 status
= dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b
, mem_ctx
,
3877 if (!NT_STATUS_IS_OK(status
)) {
3878 result
= ntstatus_to_werror(status
);
3881 if (!W_ERROR_IS_OK(result
)) {
3886 enum ndr_err_code ndr_err
;
3887 struct UNIVERSAL_FONT_ID_ctr r
;
3889 ndr_err
= ndr_pull_struct_blob(&out
, mem_ctx
, &r
,
3890 (ndr_pull_flags_fn_t
)ndr_pull_UNIVERSAL_FONT_ID_ctr
);
3891 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3892 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr
, &r
);
3897 if (is_valid_policy_hnd(&gdi_handle
)) {
3899 dcerpc_spoolss_DeletePrinterIC(b
, mem_ctx
, &gdi_handle
, &_result
);
3901 if (is_valid_policy_hnd(&handle
)) {
3903 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &_result
);
3909 static WERROR
cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client
*cli
,
3910 TALLOC_CTX
*mem_ctx
, int argc
,
3915 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3916 const char *architecture
= SPOOLSS_ARCHITECTURE_x64
;
3917 struct spoolss_CorePrinterDriver core_printer_drivers
;
3926 array
= talloc_zero_array(mem_ctx
, const char *, count
+ 1);
3927 if (array
== NULL
) {
3928 return WERR_NOT_ENOUGH_MEMORY
;
3930 array
[0] = talloc_strdup(array
, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
);
3931 if (array
[0] == NULL
) {
3932 return WERR_NOT_ENOUGH_MEMORY
;
3936 array
= talloc_zero_array(mem_ctx
, const char *, count
+ 1);
3937 if (array
== NULL
) {
3938 return WERR_NOT_ENOUGH_MEMORY
;
3940 for (i
= 0; i
< argc
- 1; i
++) {
3941 array
[i
] = talloc_strdup(array
, argv
[i
+ 1]);
3942 if (array
[i
] == NULL
) {
3943 return WERR_NOT_ENOUGH_MEMORY
;
3948 ok
= push_reg_multi_sz(mem_ctx
, &blob
, array
);
3950 return WERR_NOT_ENOUGH_MEMORY
;
3953 status
= dcerpc_spoolss_GetCorePrinterDrivers(b
, mem_ctx
,
3954 cli
->srv_name_slash
,
3957 (uint16_t *)blob
.data
,
3959 &core_printer_drivers
,
3961 if (!NT_STATUS_IS_OK(status
)) {
3962 return ntstatus_to_werror(status
);
3965 if (!HRES_IS_OK(result
)) {
3966 return W_ERROR(WIN32_FROM_HRESULT(result
));
3972 static WERROR
cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client
*cli
,
3973 TALLOC_CTX
*mem_ctx
, int argc
,
3978 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
3979 const char *servername
= cli
->srv_name_slash
;
3980 DATA_BLOB in
= data_blob_null
;
3981 struct spoolss_PrinterInfo4
*info
;
3982 uint32_t needed
, count
;
3985 printf("usage: %s [servername]\n", argv
[0]);
3990 servername
= argv
[1];
3993 status
= dcerpc_spoolss_EnumPerMachineConnections(b
, mem_ctx
,
4001 if (!NT_STATUS_IS_OK(status
)) {
4002 return ntstatus_to_werror(status
);
4005 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
4006 in
= data_blob_talloc_zero(mem_ctx
, needed
);
4007 status
= dcerpc_spoolss_EnumPerMachineConnections(b
, mem_ctx
,
4015 if (!NT_STATUS_IS_OK(status
)) {
4016 return ntstatus_to_werror(status
);
4023 static WERROR
cmd_spoolss_add_permachineconnection(struct rpc_pipe_client
*cli
,
4024 TALLOC_CTX
*mem_ctx
, int argc
,
4029 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
4030 const char *servername
= cli
->srv_name_slash
;
4031 const char *printername
= "Microsoft Print to PDF";
4032 const char *printserver
= "samba.org";
4033 const char *provider
= ""; /* refers to Win32spl.dll then */
4034 const char *composed_printername
;
4037 printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv
[0]);
4042 servername
= argv
[1];
4045 printername
= argv
[2];
4048 printserver
= argv
[3];
4054 composed_printername
= talloc_asprintf(mem_ctx
, "%s\\%s", servername
,
4056 if (composed_printername
== NULL
) {
4057 return WERR_NOT_ENOUGH_MEMORY
;
4059 status
= dcerpc_spoolss_AddPerMachineConnection(b
, mem_ctx
,
4061 composed_printername
,
4065 if (!NT_STATUS_IS_OK(status
)) {
4066 return ntstatus_to_werror(status
);
4072 static WERROR
cmd_spoolss_del_permachineconnection(struct rpc_pipe_client
*cli
,
4073 TALLOC_CTX
*mem_ctx
, int argc
,
4078 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
4079 const char *servername
= cli
->srv_name_slash
;
4080 const char *printername
= "Microsoft Print to PDF";
4081 const char *composed_printername
;
4084 printf("usage: %s [servername] [printername]\n", argv
[0]);
4089 servername
= argv
[1];
4092 printername
= argv
[2];
4095 composed_printername
= talloc_asprintf(mem_ctx
, "%s\\%s", servername
,
4097 if (composed_printername
== NULL
) {
4098 return WERR_NOT_ENOUGH_MEMORY
;
4101 status
= dcerpc_spoolss_DeletePerMachineConnection(b
, mem_ctx
,
4103 composed_printername
,
4105 if (!NT_STATUS_IS_OK(status
)) {
4106 return ntstatus_to_werror(status
);
4112 /* List of commands exported by this module */
4113 struct cmd_set spoolss_commands
[] = {
4120 .name
= "adddriver",
4121 .returntype
= RPC_RTYPE_WERROR
,
4123 .wfn
= cmd_spoolss_addprinterdriver
,
4124 .table
= &ndr_table_spoolss
,
4126 .description
= "Add a print driver",
4128 .use_netlogon_creds
= false,
4131 .name
= "addprinter",
4132 .returntype
= RPC_RTYPE_WERROR
,
4134 .wfn
= cmd_spoolss_addprinterex
,
4135 .table
= &ndr_table_spoolss
,
4137 .description
= "Add a printer",
4141 .name
= "deldriver",
4142 .returntype
= RPC_RTYPE_WERROR
,
4144 .wfn
= cmd_spoolss_deletedriver
,
4145 .table
= &ndr_table_spoolss
,
4147 .description
= "Delete a printer driver",
4151 .name
= "deldriverex",
4152 .returntype
= RPC_RTYPE_WERROR
,
4154 .wfn
= cmd_spoolss_deletedriverex
,
4155 .table
= &ndr_table_spoolss
,
4157 .description
= "Delete a printer driver with files",
4162 .returntype
= RPC_RTYPE_WERROR
,
4164 .wfn
= cmd_spoolss_enum_data
,
4165 .table
= &ndr_table_spoolss
,
4167 .description
= "Enumerate printer data",
4171 .name
= "enumdataex",
4172 .returntype
= RPC_RTYPE_WERROR
,
4174 .wfn
= cmd_spoolss_enum_data_ex
,
4175 .table
= &ndr_table_spoolss
,
4177 .description
= "Enumerate printer data for a key",
4182 .returntype
= RPC_RTYPE_WERROR
,
4184 .wfn
= cmd_spoolss_enum_printerkey
,
4185 .table
= &ndr_table_spoolss
,
4187 .description
= "Enumerate printer keys",
4192 .returntype
= RPC_RTYPE_WERROR
,
4194 .wfn
= cmd_spoolss_enum_jobs
,
4195 .table
= &ndr_table_spoolss
,
4197 .description
= "Enumerate print jobs",
4202 .returntype
= RPC_RTYPE_WERROR
,
4204 .wfn
= cmd_spoolss_get_job
,
4205 .table
= &ndr_table_spoolss
,
4207 .description
= "Get print job",
4212 .returntype
= RPC_RTYPE_WERROR
,
4214 .wfn
= cmd_spoolss_set_job
,
4215 .table
= &ndr_table_spoolss
,
4217 .description
= "Set print job",
4221 .name
= "enumports",
4222 .returntype
= RPC_RTYPE_WERROR
,
4224 .wfn
= cmd_spoolss_enum_ports
,
4225 .table
= &ndr_table_spoolss
,
4227 .description
= "Enumerate printer ports",
4231 .name
= "enumdrivers",
4232 .returntype
= RPC_RTYPE_WERROR
,
4234 .wfn
= cmd_spoolss_enum_drivers
,
4235 .table
= &ndr_table_spoolss
,
4237 .description
= "Enumerate installed printer drivers",
4241 .name
= "enumprinters",
4242 .returntype
= RPC_RTYPE_WERROR
,
4244 .wfn
= cmd_spoolss_enum_printers
,
4245 .table
= &ndr_table_spoolss
,
4247 .description
= "Enumerate printers",
4252 .returntype
= RPC_RTYPE_WERROR
,
4254 .wfn
= cmd_spoolss_getprinterdata
,
4255 .table
= &ndr_table_spoolss
,
4257 .description
= "Get print driver data",
4261 .name
= "getdataex",
4262 .returntype
= RPC_RTYPE_WERROR
,
4264 .wfn
= cmd_spoolss_getprinterdataex
,
4265 .table
= &ndr_table_spoolss
,
4267 .description
= "Get printer driver data with keyname",
4271 .name
= "getdriver",
4272 .returntype
= RPC_RTYPE_WERROR
,
4274 .wfn
= cmd_spoolss_getdriver
,
4275 .table
= &ndr_table_spoolss
,
4277 .description
= "Get print driver information",
4281 .name
= "getdriverdir",
4282 .returntype
= RPC_RTYPE_WERROR
,
4284 .wfn
= cmd_spoolss_getdriverdir
,
4285 .table
= &ndr_table_spoolss
,
4287 .description
= "Get print driver upload directory",
4291 .name
= "getdriverpackagepath",
4292 .returntype
= RPC_RTYPE_WERROR
,
4294 .wfn
= cmd_spoolss_getdriverpackagepath
,
4295 .table
= &ndr_table_spoolss
,
4297 .description
= "Get print driver package download directory",
4301 .name
= "getprinter",
4302 .returntype
= RPC_RTYPE_WERROR
,
4304 .wfn
= cmd_spoolss_getprinter
,
4305 .table
= &ndr_table_spoolss
,
4307 .description
= "Get printer info",
4311 .name
= "openprinter",
4312 .returntype
= RPC_RTYPE_WERROR
,
4314 .wfn
= cmd_spoolss_open_printer
,
4315 .table
= &ndr_table_spoolss
,
4317 .description
= "Open printer handle",
4321 .name
= "openprinter_ex",
4322 .returntype
= RPC_RTYPE_WERROR
,
4324 .wfn
= cmd_spoolss_open_printer_ex
,
4325 .table
= &ndr_table_spoolss
,
4327 .description
= "Open printer handle",
4331 .name
= "setdriver",
4332 .returntype
= RPC_RTYPE_WERROR
,
4334 .wfn
= cmd_spoolss_setdriver
,
4335 .table
= &ndr_table_spoolss
,
4337 .description
= "Set printer driver",
4341 .name
= "getprintprocdir",
4342 .returntype
= RPC_RTYPE_WERROR
,
4344 .wfn
= cmd_spoolss_getprintprocdir
,
4345 .table
= &ndr_table_spoolss
,
4347 .description
= "Get print processor directory",
4352 .returntype
= RPC_RTYPE_WERROR
,
4354 .wfn
= cmd_spoolss_addform
,
4355 .table
= &ndr_table_spoolss
,
4357 .description
= "Add form",
4362 .returntype
= RPC_RTYPE_WERROR
,
4364 .wfn
= cmd_spoolss_setform
,
4365 .table
= &ndr_table_spoolss
,
4367 .description
= "Set form",
4372 .returntype
= RPC_RTYPE_WERROR
,
4374 .wfn
= cmd_spoolss_getform
,
4375 .table
= &ndr_table_spoolss
,
4377 .description
= "Get form",
4381 .name
= "deleteform",
4382 .returntype
= RPC_RTYPE_WERROR
,
4384 .wfn
= cmd_spoolss_deleteform
,
4385 .table
= &ndr_table_spoolss
,
4387 .description
= "Delete form",
4391 .name
= "enumforms",
4392 .returntype
= RPC_RTYPE_WERROR
,
4394 .wfn
= cmd_spoolss_enum_forms
,
4395 .table
= &ndr_table_spoolss
,
4397 .description
= "Enumerate forms",
4401 .name
= "setprinter",
4402 .returntype
= RPC_RTYPE_WERROR
,
4404 .wfn
= cmd_spoolss_setprinter
,
4405 .table
= &ndr_table_spoolss
,
4407 .description
= "Set printer comment",
4411 .name
= "setprintername",
4412 .returntype
= RPC_RTYPE_WERROR
,
4414 .wfn
= cmd_spoolss_setprintername
,
4415 .table
= &ndr_table_spoolss
,
4417 .description
= "Set printername",
4421 .name
= "setprinterdata",
4422 .returntype
= RPC_RTYPE_WERROR
,
4424 .wfn
= cmd_spoolss_setprinterdata
,
4425 .table
= &ndr_table_spoolss
,
4427 .description
= "Set REG_SZ printer data",
4432 .returntype
= RPC_RTYPE_WERROR
,
4434 .wfn
= cmd_spoolss_rffpcnex
,
4435 .table
= &ndr_table_spoolss
,
4437 .description
= "Rffpcnex test",
4441 .name
= "printercmp",
4442 .returntype
= RPC_RTYPE_WERROR
,
4444 .wfn
= cmd_spoolss_printercmp
,
4445 .table
= &ndr_table_spoolss
,
4447 .description
= "Printer comparison test",
4451 .name
= "enumprocs",
4452 .returntype
= RPC_RTYPE_WERROR
,
4454 .wfn
= cmd_spoolss_enum_procs
,
4455 .table
= &ndr_table_spoolss
,
4457 .description
= "Enumerate Print Processors",
4461 .name
= "enumprocdatatypes",
4462 .returntype
= RPC_RTYPE_WERROR
,
4464 .wfn
= cmd_spoolss_enum_proc_data_types
,
4465 .table
= &ndr_table_spoolss
,
4467 .description
= "Enumerate Print Processor Data Types",
4471 .name
= "enummonitors",
4472 .returntype
= RPC_RTYPE_WERROR
,
4474 .wfn
= cmd_spoolss_enum_monitors
,
4475 .table
= &ndr_table_spoolss
,
4477 .description
= "Enumerate Print Monitors",
4481 .name
= "createprinteric",
4482 .returntype
= RPC_RTYPE_WERROR
,
4484 .wfn
= cmd_spoolss_create_printer_ic
,
4485 .table
= &ndr_table_spoolss
,
4487 .description
= "Create Printer IC",
4491 .name
= "playgdiscriptonprinteric",
4492 .returntype
= RPC_RTYPE_WERROR
,
4494 .wfn
= cmd_spoolss_play_gdi_script_on_printer_ic
,
4495 .table
= &ndr_table_spoolss
,
4497 .description
= "Create Printer IC",
4501 .name
= "getcoreprinterdrivers",
4502 .returntype
= RPC_RTYPE_WERROR
,
4504 .wfn
= cmd_spoolss_get_core_printer_drivers
,
4505 .table
= &ndr_table_spoolss
,
4507 .description
= "Get CorePrinterDriver",
4511 .name
= "enumpermachineconnections",
4512 .returntype
= RPC_RTYPE_WERROR
,
4514 .wfn
= cmd_spoolss_enum_permachineconnections
,
4515 .table
= &ndr_table_spoolss
,
4517 .description
= "Enumerate Per Machine Connections",
4521 .name
= "addpermachineconnection",
4522 .returntype
= RPC_RTYPE_WERROR
,
4524 .wfn
= cmd_spoolss_add_permachineconnection
,
4525 .table
= &ndr_table_spoolss
,
4527 .description
= "Add Per Machine Connection",
4531 .name
= "delpermachineconnection",
4532 .returntype
= RPC_RTYPE_WERROR
,
4534 .wfn
= cmd_spoolss_del_permachineconnection
,
4535 .table
= &ndr_table_spoolss
,
4537 .description
= "Delete Per Machine Connection",