2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
31 #include "registry/reg_objects.h"
32 #include "nt_printing.h"
34 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
36 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
37 _cli->srv_name_slash, _arg); \
38 W_ERROR_HAVE_NO_MEMORY(_printername); \
41 /* The version int is used by getdrivers. Note that
42 all architecture strings that support mutliple
43 versions must be grouped together since enumdrivers
44 uses this property to prevent issuing multiple
45 enumdriver calls for the same arch */
48 static const struct print_architecture_table_node archi_table
[]= {
50 {"Windows 4.0", "WIN40", 0 },
51 {"Windows NT x86", "W32X86", 2 },
52 {"Windows NT x86", "W32X86", 3 },
53 {"Windows NT R4000", "W32MIPS", 2 },
54 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
55 {"Windows NT PowerPC", "W32PPC", 2 },
56 {"Windows IA64", "IA64", 3 },
57 {"Windows x64", "x64", 3 },
64 * rpcclient module for SPOOLSS rpc pipe.
66 * This generally just parses and checks command lines, and then calls
67 * a cli_spoolss function.
70 /****************************************************************************
71 function to do the mapping between the long architecture name and
73 ****************************************************************************/
75 static const char *cmd_spoolss_get_short_archi(const char *long_archi
)
79 DEBUG(107,("Getting architecture dependant directory\n"));
82 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
83 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
85 if (archi_table
[i
].long_archi
==NULL
) {
86 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
90 /* this might be client code - but shouldn't this be an fstrcpy etc? */
93 DEBUGADD(108,("index: [%d]\n", i
));
94 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
95 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
97 return archi_table
[i
].short_archi
;
100 /****************************************************************************
101 ****************************************************************************/
103 static WERROR
cmd_spoolss_open_printer_ex(struct rpc_pipe_client
*cli
,
105 int argc
, const char **argv
)
108 struct policy_handle hnd
;
109 uint32_t access_mask
= PRINTER_ALL_ACCESS
;
112 printf("Usage: %s <printername> [access_mask]\n", argv
[0]);
117 sscanf(argv
[2], "%x", &access_mask
);
120 /* Open the printer handle */
122 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
126 if (W_ERROR_IS_OK(werror
)) {
127 printf("Printer %s opened successfully\n", argv
[1]);
128 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, &werror
);
130 if (!W_ERROR_IS_OK(werror
)) {
131 printf("Error closing printer handle! (%s)\n",
132 get_dos_error_msg(werror
));
139 /****************************************************************************
140 ****************************************************************************/
142 static WERROR
cmd_spoolss_open_printer(struct rpc_pipe_client
*cli
,
144 int argc
, const char **argv
)
147 struct policy_handle hnd
;
148 uint32_t access_mask
= PRINTER_ALL_ACCESS
;
150 struct spoolss_DevmodeContainer devmode_ctr
;
152 ZERO_STRUCT(devmode_ctr
);
155 printf("Usage: %s <printername> [access_mask]\n", argv
[0]);
160 sscanf(argv
[2], "%x", &access_mask
);
163 /* Open the printer handle */
165 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
172 if (W_ERROR_IS_OK(werror
)) {
173 printf("Printer %s opened successfully\n", argv
[1]);
174 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, &werror
);
176 if (!W_ERROR_IS_OK(werror
)) {
177 printf("Error closing printer handle! (%s)\n",
178 get_dos_error_msg(werror
));
185 /****************************************************************************
186 ****************************************************************************/
188 static void display_print_info0(struct spoolss_PrinterInfo0
*r
)
193 printf("\tprintername:[%s]\n", r
->printername
);
194 printf("\tservername:[%s]\n", r
->servername
);
195 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
196 printf("\ttotal_jobs:[0x%x]\n", r
->total_jobs
);
197 printf("\ttotal_bytes:[0x%x]\n", r
->total_bytes
);
198 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r
->time
.year
, r
->time
.month
,
199 r
->time
.day
, r
->time
.day_of_week
);
200 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r
->time
.hour
, r
->time
.minute
,
201 r
->time
.second
, r
->time
.millisecond
);
203 printf("\tglobal_counter:[0x%x]\n", r
->global_counter
);
204 printf("\ttotal_pages:[0x%x]\n", r
->total_pages
);
206 printf("\tversion:[0x%x]\n", r
->version
);
207 printf("\tfree_build:[0x%x]\n", r
->free_build
);
208 printf("\tspooling:[0x%x]\n", r
->spooling
);
209 printf("\tmax_spooling:[0x%x]\n", r
->max_spooling
);
210 printf("\tsession_counter:[0x%x]\n", r
->session_counter
);
211 printf("\tnum_error_out_of_paper:[0x%x]\n", r
->num_error_out_of_paper
);
212 printf("\tnum_error_not_ready:[0x%x]\n", r
->num_error_not_ready
);
213 printf("\tjob_error:[0x%x]\n", r
->job_error
);
214 printf("\tnumber_of_processors:[0x%x]\n", r
->number_of_processors
);
215 printf("\tprocessor_type:[0x%x]\n", r
->processor_type
);
216 printf("\thigh_part_total_bytes:[0x%x]\n", r
->high_part_total_bytes
);
217 printf("\tchange_id:[0x%x]\n", r
->change_id
);
218 printf("\tlast_error: %s\n", win_errstr(r
->last_error
));
219 printf("\tstatus:[0x%x]\n", r
->status
);
220 printf("\tenumerate_network_printers:[0x%x]\n", r
->enumerate_network_printers
);
221 printf("\tc_setprinter:[0x%x]\n", r
->c_setprinter
);
222 printf("\tprocessor_architecture:[0x%x]\n", r
->processor_architecture
);
223 printf("\tprocessor_level:[0x%x]\n", r
->processor_level
);
224 printf("\tref_ic:[0x%x]\n", r
->ref_ic
);
225 printf("\treserved2:[0x%x]\n", r
->reserved2
);
226 printf("\treserved3:[0x%x]\n", r
->reserved3
);
231 /****************************************************************************
232 ****************************************************************************/
234 static void display_print_info1(struct spoolss_PrinterInfo1
*r
)
236 printf("\tflags:[0x%x]\n", r
->flags
);
237 printf("\tname:[%s]\n", r
->name
);
238 printf("\tdescription:[%s]\n", r
->description
);
239 printf("\tcomment:[%s]\n", r
->comment
);
244 /****************************************************************************
245 ****************************************************************************/
247 static void display_print_info2(struct spoolss_PrinterInfo2
*r
)
249 printf("\tservername:[%s]\n", r
->servername
);
250 printf("\tprintername:[%s]\n", r
->printername
);
251 printf("\tsharename:[%s]\n", r
->sharename
);
252 printf("\tportname:[%s]\n", r
->portname
);
253 printf("\tdrivername:[%s]\n", r
->drivername
);
254 printf("\tcomment:[%s]\n", r
->comment
);
255 printf("\tlocation:[%s]\n", r
->location
);
256 printf("\tsepfile:[%s]\n", r
->sepfile
);
257 printf("\tprintprocessor:[%s]\n", r
->printprocessor
);
258 printf("\tdatatype:[%s]\n", r
->datatype
);
259 printf("\tparameters:[%s]\n", r
->parameters
);
260 printf("\tattributes:[0x%x]\n", r
->attributes
);
261 printf("\tpriority:[0x%x]\n", r
->priority
);
262 printf("\tdefaultpriority:[0x%x]\n", r
->defaultpriority
);
263 printf("\tstarttime:[0x%x]\n", r
->starttime
);
264 printf("\tuntiltime:[0x%x]\n", r
->untiltime
);
265 printf("\tstatus:[0x%x]\n", r
->status
);
266 printf("\tcjobs:[0x%x]\n", r
->cjobs
);
267 printf("\taverageppm:[0x%x]\n", r
->averageppm
);
270 display_sec_desc(r
->secdesc
);
275 /****************************************************************************
276 ****************************************************************************/
278 static void display_print_info3(struct spoolss_PrinterInfo3
*r
)
280 display_sec_desc(r
->secdesc
);
285 /****************************************************************************
286 ****************************************************************************/
288 static void display_print_info4(struct spoolss_PrinterInfo4
*r
)
290 printf("\tservername:[%s]\n", r
->servername
);
291 printf("\tprintername:[%s]\n", r
->printername
);
292 printf("\tattributes:[0x%x]\n", r
->attributes
);
296 /****************************************************************************
297 ****************************************************************************/
299 static void display_print_info5(struct spoolss_PrinterInfo5
*r
)
301 printf("\tprintername:[%s]\n", r
->printername
);
302 printf("\tportname:[%s]\n", r
->portname
);
303 printf("\tattributes:[0x%x]\n", r
->attributes
);
304 printf("\tdevice_not_selected_timeout:[0x%x]\n", r
->device_not_selected_timeout
);
305 printf("\ttransmission_retry_timeout:[0x%x]\n", r
->transmission_retry_timeout
);
309 /****************************************************************************
310 ****************************************************************************/
312 static void display_print_info6(struct spoolss_PrinterInfo6
*r
)
314 printf("\tstatus:[0x%x]\n", r
->status
);
318 /****************************************************************************
319 ****************************************************************************/
321 static void display_print_info7(struct spoolss_PrinterInfo7
*r
)
323 printf("\tguid:[%s]\n", r
->guid
);
324 printf("\taction:[0x%x]\n", r
->action
);
328 /****************************************************************************
329 ****************************************************************************/
331 static WERROR
cmd_spoolss_enum_printers(struct rpc_pipe_client
*cli
,
333 int argc
, const char **argv
)
337 union spoolss_PrinterInfo
*info
;
340 uint32_t flags
= PRINTER_ENUM_LOCAL
;
343 printf("Usage: %s [level] [name] [flags]\n", argv
[0]);
348 level
= atoi(argv
[1]);
354 name
= cli
->srv_name_slash
;
358 flags
= atoi(argv
[3]);
361 result
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
368 if (W_ERROR_IS_OK(result
)) {
371 printf ("No printers returned.\n");
375 for (i
= 0; i
< count
; i
++) {
378 display_print_info0(&info
[i
].info0
);
381 display_print_info1(&info
[i
].info1
);
384 display_print_info2(&info
[i
].info2
);
387 display_print_info3(&info
[i
].info3
);
390 display_print_info4(&info
[i
].info4
);
393 display_print_info5(&info
[i
].info5
);
396 display_print_info6(&info
[i
].info6
);
399 printf("unknown info level %d\n", level
);
409 /****************************************************************************
410 ****************************************************************************/
412 static void display_port_info_1(struct spoolss_PortInfo1
*r
)
414 printf("\tPort Name:\t[%s]\n", r
->port_name
);
417 /****************************************************************************
418 ****************************************************************************/
420 static void display_port_info_2(struct spoolss_PortInfo2
*r
)
422 printf("\tPort Name:\t[%s]\n", r
->port_name
);
423 printf("\tMonitor Name:\t[%s]\n", r
->monitor_name
);
424 printf("\tDescription:\t[%s]\n", r
->description
);
425 printf("\tPort Type:\t" );
427 int comma
= 0; /* hack */
429 if (r
->port_type
& SPOOLSS_PORT_TYPE_READ
) {
433 if (r
->port_type
& SPOOLSS_PORT_TYPE_WRITE
) {
434 printf( "%sWrite", comma
? ", " : "" );
437 /* These two have slightly different interpretations
438 on 95/98/ME but I'm disregarding that for now */
439 if (r
->port_type
& SPOOLSS_PORT_TYPE_REDIRECTED
) {
440 printf( "%sRedirected", comma
? ", " : "" );
443 if (r
->port_type
& SPOOLSS_PORT_TYPE_NET_ATTACHED
) {
444 printf( "%sNet-Attached", comma
? ", " : "" );
448 printf( "[Unset]\n" );
450 printf("\tReserved:\t[%d]\n", r
->reserved
);
454 /****************************************************************************
455 ****************************************************************************/
457 static WERROR
cmd_spoolss_enum_ports(struct rpc_pipe_client
*cli
,
458 TALLOC_CTX
*mem_ctx
, int argc
,
464 union spoolss_PortInfo
*info
;
467 printf("Usage: %s [level]\n", argv
[0]);
472 level
= atoi(argv
[1]);
475 /* Enumerate ports */
477 result
= rpccli_spoolss_enumports(cli
, mem_ctx
,
483 if (W_ERROR_IS_OK(result
)) {
486 for (i
= 0; i
< count
; i
++) {
489 display_port_info_1(&info
[i
].info1
);
492 display_port_info_2(&info
[i
].info2
);
495 printf("unknown info level %d\n", level
);
504 /****************************************************************************
505 ****************************************************************************/
507 static WERROR
cmd_spoolss_setprinter(struct rpc_pipe_client
*cli
,
509 int argc
, const char **argv
)
511 struct policy_handle pol
;
514 uint32_t info_level
= 2;
515 union spoolss_PrinterInfo info
;
516 struct spoolss_SetPrinterInfoCtr info_ctr
;
517 struct spoolss_SetPrinterInfo2 info2
;
518 const char *printername
, *comment
= NULL
;
519 struct spoolss_DevmodeContainer devmode_ctr
;
520 struct sec_desc_buf secdesc_ctr
;
522 if (argc
== 1 || argc
> 3) {
523 printf("Usage: %s printername comment\n", argv
[0]);
528 /* Open a printer handle */
533 ZERO_STRUCT(devmode_ctr
);
534 ZERO_STRUCT(secdesc_ctr
);
536 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
538 /* get a printer handle */
539 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
543 if (!W_ERROR_IS_OK(result
))
546 /* Get printer info */
547 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
552 if (!W_ERROR_IS_OK(result
))
556 /* Modify the comment. */
557 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
558 info2
.comment
= comment
;
561 info_ctr
.info
.info2
= &info2
;
563 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
570 if (W_ERROR_IS_OK(result
))
571 printf("Success in setting comment.\n");
574 if (is_valid_policy_hnd(&pol
))
575 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
580 /****************************************************************************
581 ****************************************************************************/
583 static WERROR
cmd_spoolss_setprintername(struct rpc_pipe_client
*cli
,
585 int argc
, const char **argv
)
587 struct policy_handle pol
;
590 uint32_t info_level
= 2;
591 union spoolss_PrinterInfo info
;
592 const char *printername
,
593 *new_printername
= NULL
;
594 struct spoolss_SetPrinterInfoCtr info_ctr
;
595 struct spoolss_SetPrinterInfo2 info2
;
596 struct spoolss_DevmodeContainer devmode_ctr
;
597 struct sec_desc_buf secdesc_ctr
;
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
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
646 if (W_ERROR_IS_OK(result
))
647 printf("Success in setting printername.\n");
650 if (is_valid_policy_hnd(&pol
))
651 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
656 /****************************************************************************
657 ****************************************************************************/
659 static WERROR
cmd_spoolss_getprinter(struct rpc_pipe_client
*cli
,
661 int argc
, const char **argv
)
663 struct policy_handle pol
;
666 const char *printername
;
667 union spoolss_PrinterInfo info
;
669 if (argc
== 1 || argc
> 3) {
670 printf("Usage: %s <printername> [level]\n", argv
[0]);
674 /* Open a printer handle */
676 level
= atoi(argv
[2]);
679 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
681 /* get a printer handle */
683 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
685 SEC_FLAG_MAXIMUM_ALLOWED
,
687 if (!W_ERROR_IS_OK(result
)) {
691 /* Get printer info */
693 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
698 if (!W_ERROR_IS_OK(result
)) {
702 /* Display printer info */
705 display_print_info0(&info
.info0
);
708 display_print_info1(&info
.info1
);
711 display_print_info2(&info
.info2
);
714 display_print_info3(&info
.info3
);
717 display_print_info4(&info
.info4
);
720 display_print_info5(&info
.info5
);
723 display_print_info6(&info
.info6
);
726 display_print_info7(&info
.info7
);
729 printf("unknown info level %d\n", level
);
733 if (is_valid_policy_hnd(&pol
)) {
734 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
740 /****************************************************************************
741 ****************************************************************************/
743 static void display_reg_value(struct regval_blob
*value
)
745 const char *text
= NULL
;
748 switch(regval_type(value
)) {
750 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value
),
751 *((uint32_t *) regval_data_p(value
)));
754 blob
= data_blob_const(regval_data_p(value
), regval_size(value
));
755 pull_reg_sz(talloc_tos(), &blob
, &text
);
756 printf("%s: REG_SZ: %s\n", regval_name(value
), text
? text
: "");
759 char *hex
= hex_encode_talloc(NULL
, regval_data_p(value
), regval_size(value
));
761 printf("%s: REG_BINARY:", regval_name(value
));
763 for (i
=0; i
<len
; i
++) {
764 if (hex
[i
] == '\0') {
779 blob
= data_blob_const(regval_data_p(value
), regval_size(value
));
781 if (!pull_reg_multi_sz(NULL
, &blob
, &values
)) {
782 d_printf("pull_reg_multi_sz failed\n");
786 printf("%s: REG_MULTI_SZ: \n", regval_name(value
));
787 for (i
=0; values
[i
] != NULL
; i
++) {
788 d_printf("%s\n", values
[i
]);
794 printf("%s: unknown type %d\n", regval_name(value
), regval_type(value
));
799 /****************************************************************************
800 ****************************************************************************/
802 static void display_printer_data(const char *v
,
803 enum winreg_Type type
,
808 union spoolss_PrinterData r
;
809 DATA_BLOB blob
= data_blob_const(data
, length
);
812 result
= pull_spoolss_PrinterData(talloc_tos(), &blob
, &r
, type
);
813 if (!W_ERROR_IS_OK(result
)) {
819 printf("%s: REG_DWORD: 0x%08x\n", v
, r
.value
);
822 printf("%s: REG_SZ: %s\n", v
, r
.string
);
825 char *hex
= hex_encode_talloc(NULL
,
826 r
.binary
.data
, r
.binary
.length
);
828 printf("%s: REG_BINARY:", v
);
830 for (i
=0; i
<len
; i
++) {
831 if (hex
[i
] == '\0') {
844 printf("%s: REG_MULTI_SZ: ", v
);
845 for (i
=0; r
.string_array
[i
] != NULL
; i
++) {
846 printf("%s ", r
.string_array
[i
]);
851 printf("%s: unknown type 0x%02x:\n", v
, type
);
856 /****************************************************************************
857 ****************************************************************************/
859 static WERROR
cmd_spoolss_getprinterdata(struct rpc_pipe_client
*cli
,
861 int argc
, const char **argv
)
863 struct policy_handle pol
;
866 const char *valuename
;
867 enum winreg_Type type
;
872 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
873 printf("<printername> of . queries print server\n");
878 /* Open a printer handle */
880 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
881 fstrcpy(printername
, cli
->srv_name_slash
);
883 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
884 cli
->srv_name_slash
, argv
[1]);
886 /* get a printer handle */
888 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
890 SEC_FLAG_MAXIMUM_ALLOWED
,
892 if (!W_ERROR_IS_OK(result
))
895 /* Get printer info */
897 result
= rpccli_spoolss_getprinterdata(cli
, mem_ctx
,
904 if (!W_ERROR_IS_OK(result
))
907 /* Display printer data */
909 display_printer_data(valuename
, type
, data
, needed
);
912 if (is_valid_policy_hnd(&pol
))
913 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
918 /****************************************************************************
919 ****************************************************************************/
921 static WERROR
cmd_spoolss_getprinterdataex(struct rpc_pipe_client
*cli
,
923 int argc
, const char **argv
)
925 struct policy_handle pol
;
929 const char *valuename
, *keyname
;
931 enum winreg_Type type
;
932 uint8_t *data
= NULL
;
933 uint32_t offered
= 0;
937 printf("Usage: %s <printername> <keyname> <valuename>\n",
939 printf("<printername> of . queries print server\n");
945 /* Open a printer handle */
947 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
948 fstrcpy(printername
, cli
->srv_name_slash
);
950 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
951 cli
->srv_name_slash
, argv
[1]);
953 /* get a printer handle */
955 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
957 SEC_FLAG_MAXIMUM_ALLOWED
,
959 if (!W_ERROR_IS_OK(result
))
962 /* Get printer info */
964 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
969 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
978 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
980 data
= talloc_zero_array(mem_ctx
, uint8_t, offered
);
984 status
= rpccli_spoolss_GetPrinterDataEx(cli
, mem_ctx
,
995 if (!NT_STATUS_IS_OK(status
)) {
999 if (!W_ERROR_IS_OK(result
))
1002 /* Display printer data */
1004 display_printer_data(valuename
, type
, data
, needed
);
1008 if (is_valid_policy_hnd(&pol
))
1009 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1014 /****************************************************************************
1015 ****************************************************************************/
1017 static void display_print_driver1(struct spoolss_DriverInfo1
*r
)
1023 printf("Printer Driver Info 1:\n");
1024 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1028 /****************************************************************************
1029 ****************************************************************************/
1031 static void display_print_driver2(struct spoolss_DriverInfo2
*r
)
1037 printf("Printer Driver Info 2:\n");
1038 printf("\tVersion: [%x]\n", r
->version
);
1039 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1040 printf("\tArchitecture: [%s]\n", r
->architecture
);
1041 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1042 printf("\tDatafile: [%s]\n", r
->data_file
);
1043 printf("\tConfigfile: [%s]\n", r
->config_file
);
1047 /****************************************************************************
1048 ****************************************************************************/
1050 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
1058 printf("Printer Driver Info 3:\n");
1059 printf("\tVersion: [%x]\n", r
->version
);
1060 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1061 printf("\tArchitecture: [%s]\n", r
->architecture
);
1062 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1063 printf("\tDatafile: [%s]\n", r
->data_file
);
1064 printf("\tConfigfile: [%s]\n", r
->config_file
);
1065 printf("\tHelpfile: [%s]\n", r
->help_file
);
1067 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1068 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1071 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1072 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1076 /****************************************************************************
1077 ****************************************************************************/
1079 static void display_print_driver4(struct spoolss_DriverInfo4
*r
)
1087 printf("Printer Driver Info 4:\n");
1088 printf("\tVersion: [%x]\n", r
->version
);
1089 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1090 printf("\tArchitecture: [%s]\n", r
->architecture
);
1091 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1092 printf("\tDatafile: [%s]\n", r
->data_file
);
1093 printf("\tConfigfile: [%s]\n", r
->config_file
);
1094 printf("\tHelpfile: [%s]\n", r
->help_file
);
1096 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1097 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1100 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1101 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1103 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1104 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1109 /****************************************************************************
1110 ****************************************************************************/
1112 static void display_print_driver5(struct spoolss_DriverInfo5
*r
)
1118 printf("Printer Driver Info 5:\n");
1119 printf("\tVersion: [%x]\n", r
->version
);
1120 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1121 printf("\tArchitecture: [%s]\n", r
->architecture
);
1122 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1123 printf("\tDatafile: [%s]\n", r
->data_file
);
1124 printf("\tConfigfile: [%s]\n", r
->config_file
);
1125 printf("\tDriver Attributes: [0x%x]\n", r
->driver_attributes
);
1126 printf("\tConfig Version: [0x%x]\n", r
->config_version
);
1127 printf("\tDriver Version: [0x%x]\n", r
->driver_version
);
1131 /****************************************************************************
1132 ****************************************************************************/
1134 static void display_print_driver6(struct spoolss_DriverInfo6
*r
)
1142 printf("Printer Driver Info 6:\n");
1143 printf("\tVersion: [%x]\n", r
->version
);
1144 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1145 printf("\tArchitecture: [%s]\n", r
->architecture
);
1146 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1147 printf("\tDatafile: [%s]\n", r
->data_file
);
1148 printf("\tConfigfile: [%s]\n", r
->config_file
);
1149 printf("\tHelpfile: [%s]\n", r
->help_file
);
1151 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1152 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1155 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1156 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1158 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1159 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1162 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1163 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1164 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1165 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1166 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1167 printf("\tProvider: [%s]\n", r
->provider
);
1172 /****************************************************************************
1173 ****************************************************************************/
1175 static void display_print_driver8(struct spoolss_DriverInfo8
*r
)
1183 printf("Printer Driver Info 8:\n");
1184 printf("\tVersion: [%x]\n", r
->version
);
1185 printf("\tDriver Name: [%s]\n", r
->driver_name
);
1186 printf("\tArchitecture: [%s]\n", r
->architecture
);
1187 printf("\tDriver Path: [%s]\n", r
->driver_path
);
1188 printf("\tDatafile: [%s]\n", r
->data_file
);
1189 printf("\tConfigfile: [%s]\n", r
->config_file
);
1190 printf("\tHelpfile: [%s]\n", r
->help_file
);
1191 printf("\tMonitorname: [%s]\n", r
->monitor_name
);
1192 printf("\tDefaultdatatype: [%s]\n", r
->default_datatype
);
1194 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
] != NULL
; i
++) {
1195 printf("\tDependentfiles: [%s]\n", r
->dependent_files
[i
]);
1198 for (i
=0; r
->previous_names
&& r
->previous_names
[i
] != NULL
; i
++) {
1199 printf("\tPrevious Names: [%s]\n", r
->previous_names
[i
]);
1202 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r
->driver_date
));
1203 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r
->driver_version
);
1204 printf("\tManufacturer Name: [%s]\n", r
->manufacturer_name
);
1205 printf("\tManufacturer Url: [%s]\n", r
->manufacturer_url
);
1206 printf("\tHardware ID: [%s]\n", r
->hardware_id
);
1207 printf("\tProvider: [%s]\n", r
->provider
);
1208 printf("\tPrint Processor: [%s]\n", r
->print_processor
);
1209 printf("\tVendor Setup: [%s]\n", r
->vendor_setup
);
1210 for (i
=0; r
->color_profiles
&& r
->color_profiles
[i
] != NULL
; i
++) {
1211 printf("\tColor Profiles: [%s]\n", r
->color_profiles
[i
]);
1213 printf("\tInf Path: [%s]\n", r
->inf_path
);
1214 printf("\tPrinter Driver Attributes: [0x%x]\n", r
->printer_driver_attributes
);
1215 for (i
=0; r
->core_driver_dependencies
&& r
->core_driver_dependencies
[i
] != NULL
; i
++) {
1216 printf("\tCore Driver Dependencies: [%s]\n", r
->core_driver_dependencies
[i
]);
1218 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r
->min_inbox_driver_ver_date
));
1219 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1220 (long long unsigned int)r
->min_inbox_driver_ver_version
);
1225 /****************************************************************************
1226 ****************************************************************************/
1228 static WERROR
cmd_spoolss_getdriver(struct rpc_pipe_client
*cli
,
1229 TALLOC_CTX
*mem_ctx
,
1230 int argc
, const char **argv
)
1232 struct policy_handle pol
;
1235 const char *printername
;
1237 bool success
= false;
1238 union spoolss_DriverInfo info
;
1239 uint32_t server_major_version
;
1240 uint32_t server_minor_version
;
1242 if ((argc
== 1) || (argc
> 3)) {
1243 printf("Usage: %s <printername> [level]\n", argv
[0]);
1247 /* get the arguments need to open the printer handle */
1249 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1252 level
= atoi(argv
[2]);
1255 /* Open a printer handle */
1257 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1261 if (!W_ERROR_IS_OK(werror
)) {
1262 printf("Error opening printer handle for %s!\n", printername
);
1266 /* loop through and print driver info level for each architecture */
1268 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1270 werror
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1272 archi_table
[i
].long_archi
,
1275 archi_table
[i
].version
,
1278 &server_major_version
,
1279 &server_minor_version
);
1280 if (!W_ERROR_IS_OK(werror
)) {
1284 /* need at least one success */
1288 printf("\n[%s]\n", archi_table
[i
].long_archi
);
1292 display_print_driver1(&info
.info1
);
1295 display_print_driver2(&info
.info2
);
1298 display_print_driver3(&info
.info3
);
1301 display_print_driver4(&info
.info4
);
1304 display_print_driver5(&info
.info5
);
1307 display_print_driver6(&info
.info6
);
1310 display_print_driver8(&info
.info8
);
1313 printf("unknown info level %d\n", level
);
1320 if (is_valid_policy_hnd(&pol
)) {
1321 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1331 /****************************************************************************
1332 ****************************************************************************/
1334 static WERROR
enum_driver_by_architecture(struct rpc_pipe_client
*cli
,
1335 TALLOC_CTX
*mem_ctx
,
1336 const char *architecture
,
1341 union spoolss_DriverInfo
*info
= NULL
;
1344 werror
= rpccli_spoolss_enumprinterdrivers(cli
, mem_ctx
,
1345 cli
->srv_name_slash
,
1352 if (W_ERROR_EQUAL(werror
, WERR_INVALID_ENVIRONMENT
)) {
1353 printf("Server does not support environment [%s]\n",
1362 if (!W_ERROR_IS_OK(werror
)) {
1363 printf("Error getting driver for environment [%s] - %s\n",
1364 architecture
, win_errstr(werror
));
1368 printf("\n[%s]\n", architecture
);
1372 for (j
=0; j
< count
; j
++) {
1373 display_print_driver1(&info
[j
].info1
);
1377 for (j
=0; j
< count
; j
++) {
1378 display_print_driver2(&info
[j
].info2
);
1382 for (j
=0; j
< count
; j
++) {
1383 display_print_driver3(&info
[j
].info3
);
1387 for (j
=0; j
< count
; j
++) {
1388 display_print_driver4(&info
[j
].info4
);
1392 for (j
=0; j
< count
; j
++) {
1393 display_print_driver5(&info
[j
].info5
);
1397 for (j
=0; j
< count
; j
++) {
1398 display_print_driver6(&info
[j
].info6
);
1402 for (j
=0; j
< count
; j
++) {
1403 display_print_driver8(&info
[j
].info8
);
1407 printf("unknown info level %d\n", level
);
1408 return WERR_UNKNOWN_LEVEL
;
1414 static WERROR
cmd_spoolss_enum_drivers(struct rpc_pipe_client
*cli
,
1415 TALLOC_CTX
*mem_ctx
,
1416 int argc
, const char **argv
)
1418 WERROR werror
= WERR_OK
;
1421 const char *architecture
= NULL
;
1424 printf("Usage: enumdrivers [level] [architecture]\n");
1429 level
= atoi(argv
[1]);
1433 architecture
= argv
[2];
1437 return enum_driver_by_architecture(cli
, mem_ctx
,
1442 /* loop through and print driver info level for each architecture */
1443 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1444 /* check to see if we already asked for this architecture string */
1446 if (i
>0 && strequal(archi_table
[i
].long_archi
, archi_table
[i
-1].long_archi
)) {
1450 werror
= enum_driver_by_architecture(cli
, mem_ctx
,
1451 archi_table
[i
].long_archi
,
1453 if (!W_ERROR_IS_OK(werror
)) {
1461 /****************************************************************************
1462 ****************************************************************************/
1464 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1
*r
)
1466 printf("\tDirectory Name:[%s]\n", r
->directory_name
);
1469 /****************************************************************************
1470 ****************************************************************************/
1472 static WERROR
cmd_spoolss_getdriverdir(struct rpc_pipe_client
*cli
,
1473 TALLOC_CTX
*mem_ctx
,
1474 int argc
, const char **argv
)
1478 const char *env
= SPOOLSS_ARCHITECTURE_NT_X86
;
1481 union spoolss_DriverDirectoryInfo info
;
1485 printf("Usage: %s [environment]\n", argv
[0]);
1489 /* Get the arguments need to open the printer handle */
1495 /* Get the directory. Only use Info level 1 */
1497 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1498 cli
->srv_name_slash
,
1506 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
1508 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
1510 status
= rpccli_spoolss_GetPrinterDriverDirectory(cli
, mem_ctx
,
1511 cli
->srv_name_slash
,
1521 if (W_ERROR_IS_OK(result
)) {
1522 display_printdriverdir_1(&info
.info1
);
1528 /****************************************************************************
1529 ****************************************************************************/
1531 static void set_drv_info_3_env(TALLOC_CTX
*mem_ctx
,
1532 struct spoolss_AddDriverInfo3
*info
,
1538 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1540 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1542 info
->version
= archi_table
[i
].version
;
1543 info
->architecture
= talloc_strdup(mem_ctx
, archi_table
[i
].long_archi
);
1548 if (archi_table
[i
].long_archi
== NULL
)
1550 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1557 /**************************************************************************
1558 wrapper for strtok to get the next parameter from a delimited list.
1559 Needed to handle the empty parameter string denoted by "NULL"
1560 *************************************************************************/
1562 static char *get_driver_3_param(TALLOC_CTX
*mem_ctx
, char *str
,
1563 const char *delim
, const char **dest
,
1568 /* get the next token */
1569 ptr
= strtok_r(str
, delim
, saveptr
);
1571 /* a string of 'NULL' is used to represent an empty
1572 parameter because two consecutive delimiters
1573 will not return an empty string. See man strtok(3)
1575 if (ptr
&& (StrCaseCmp(ptr
, "NULL") == 0)) {
1580 *dest
= talloc_strdup(mem_ctx
, ptr
);
1586 /********************************************************************************
1587 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1588 string in the form of
1589 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1590 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1591 <Default Data Type>:<Comma Separated list of Files>
1592 *******************************************************************************/
1594 static bool init_drv_info_3_members(TALLOC_CTX
*mem_ctx
, struct spoolss_AddDriverInfo3
*r
,
1599 char *saveptr
= NULL
;
1600 struct spoolss_StringArray
*deps
;
1601 const char **file_array
= NULL
;
1604 /* fill in the UNISTR fields */
1605 str
= get_driver_3_param(mem_ctx
, args
, ":", &r
->driver_name
, &saveptr
);
1606 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->driver_path
, &saveptr
);
1607 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->data_file
, &saveptr
);
1608 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->config_file
, &saveptr
);
1609 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->help_file
, &saveptr
);
1610 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->monitor_name
, &saveptr
);
1611 str
= get_driver_3_param(mem_ctx
, NULL
, ":", &r
->default_datatype
, &saveptr
);
1613 /* <Comma Separated List of Dependent Files> */
1614 /* save the beginning of the string */
1615 str2
= get_driver_3_param(mem_ctx
, NULL
, ":", NULL
, &saveptr
);
1618 /* begin to strip out each filename */
1619 str
= strtok_r(str
, ",", &saveptr
);
1621 /* no dependent files, we are done */
1626 deps
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1631 while (str
!= NULL
) {
1632 add_string_to_array(deps
, str
, &file_array
, &count
);
1633 str
= strtok_r(NULL
, ",", &saveptr
);
1636 deps
->string
= talloc_zero_array(deps
, const char *, count
+ 1);
1637 if (!deps
->string
) {
1641 for (i
=0; i
< count
; i
++) {
1642 deps
->string
[i
] = file_array
[i
];
1645 r
->dependent_files
= deps
;
1650 /****************************************************************************
1651 ****************************************************************************/
1653 static WERROR
cmd_spoolss_addprinterdriver(struct rpc_pipe_client
*cli
,
1654 TALLOC_CTX
*mem_ctx
,
1655 int argc
, const char **argv
)
1660 struct spoolss_AddDriverInfoCtr info_ctr
;
1661 struct spoolss_AddDriverInfo3 info3
;
1665 /* parse the command arguments */
1666 if (argc
!= 3 && argc
!= 4)
1668 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1669 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1670 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1671 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1672 printf ("\t[version]\n");
1677 /* Fill in the spoolss_AddDriverInfo3 struct */
1680 arch
= cmd_spoolss_get_short_archi(argv
[1]);
1682 printf ("Error Unknown architechture [%s]\n", argv
[1]);
1683 return WERR_INVALID_PARAM
;
1686 set_drv_info_3_env(mem_ctx
, &info3
, arch
);
1688 driver_args
= talloc_strdup( mem_ctx
, argv
[2] );
1689 if (!init_drv_info_3_members(mem_ctx
, &info3
, driver_args
))
1691 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1692 return WERR_INVALID_PARAM
;
1695 /* if printer driver version specified, override the default version
1696 * used by the architecture. This allows installation of Windows
1697 * 2000 (version 3) printer drivers. */
1700 info3
.version
= atoi(argv
[3]);
1704 info_ctr
.level
= level
;
1705 info_ctr
.info
.info3
= &info3
;
1707 status
= rpccli_spoolss_AddPrinterDriver(cli
, mem_ctx
,
1708 cli
->srv_name_slash
,
1711 if (!NT_STATUS_IS_OK(status
)) {
1712 return ntstatus_to_werror(status
);
1714 if (W_ERROR_IS_OK(result
)) {
1715 printf ("Printer Driver %s successfully installed.\n",
1723 /****************************************************************************
1724 ****************************************************************************/
1726 static WERROR
cmd_spoolss_addprinterex(struct rpc_pipe_client
*cli
,
1727 TALLOC_CTX
*mem_ctx
,
1728 int argc
, const char **argv
)
1731 struct spoolss_SetPrinterInfoCtr info_ctr
;
1732 struct spoolss_SetPrinterInfo2 info2
;
1734 /* parse the command arguments */
1737 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1741 /* Fill in the DRIVER_INFO_2 struct */
1744 info2
.printername
= argv
[1];
1745 info2
.drivername
= argv
[3];
1746 info2
.sharename
= argv
[2];
1747 info2
.portname
= argv
[4];
1748 info2
.comment
= "Created by rpcclient";
1749 info2
.printprocessor
= "winprint";
1750 info2
.datatype
= "RAW";
1751 info2
.devmode_ptr
= 0;
1752 info2
.secdesc_ptr
= 0;
1753 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1755 info2
.defaultpriority
= 0;
1756 info2
.starttime
= 0;
1757 info2
.untiltime
= 0;
1759 /* These three fields must not be used by AddPrinter()
1760 as defined in the MS Platform SDK documentation..
1764 info2.averageppm = 0;
1768 info_ctr
.info
.info2
= &info2
;
1770 result
= rpccli_spoolss_addprinterex(cli
, mem_ctx
,
1772 if (W_ERROR_IS_OK(result
))
1773 printf ("Printer %s successfully installed.\n", argv
[1]);
1778 /****************************************************************************
1779 ****************************************************************************/
1781 static WERROR
cmd_spoolss_setdriver(struct rpc_pipe_client
*cli
,
1782 TALLOC_CTX
*mem_ctx
,
1783 int argc
, const char **argv
)
1785 struct policy_handle pol
;
1789 const char *printername
;
1790 union spoolss_PrinterInfo info
;
1791 struct spoolss_SetPrinterInfoCtr info_ctr
;
1792 struct spoolss_SetPrinterInfo2 info2
;
1793 struct spoolss_DevmodeContainer devmode_ctr
;
1794 struct sec_desc_buf secdesc_ctr
;
1796 ZERO_STRUCT(devmode_ctr
);
1797 ZERO_STRUCT(secdesc_ctr
);
1799 /* parse the command arguments */
1802 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1806 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
1808 /* Get a printer handle */
1810 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
1814 if (!W_ERROR_IS_OK(result
))
1817 /* Get printer info */
1819 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
1824 if (!W_ERROR_IS_OK(result
)) {
1825 printf ("Unable to retrieve printer information!\n");
1829 /* Set the printer driver */
1831 spoolss_printerinfo2_to_setprinterinfo2(&info
.info2
, &info2
);
1832 info2
.drivername
= argv
[2];
1835 info_ctr
.info
.info2
= &info2
;
1837 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
1844 if (!W_ERROR_IS_OK(result
)) {
1845 printf("SetPrinter call failed!\n");
1849 printf("Successfully set %s to driver %s.\n", argv
[1], argv
[2]);
1854 if (is_valid_policy_hnd(&pol
))
1855 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
1861 /****************************************************************************
1862 ****************************************************************************/
1864 static WERROR
cmd_spoolss_deletedriverex(struct rpc_pipe_client
*cli
,
1865 TALLOC_CTX
*mem_ctx
,
1866 int argc
, const char **argv
)
1868 WERROR result
, ret
= WERR_UNKNOWN_PRINTER_DRIVER
;
1874 const char *arch
= NULL
;
1875 uint32_t delete_flags
= 0;
1877 /* parse the command arguments */
1878 if (argc
< 2 || argc
> 4) {
1879 printf ("Usage: %s <driver> [arch] [version]\n", argv
[0]);
1886 vers
= atoi (argv
[3]);
1889 delete_flags
|= DPD_DELETE_SPECIFIC_VERSION
;
1892 /* delete the driver for all architectures */
1893 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1895 if (arch
&& !strequal( archi_table
[i
].long_archi
, arch
))
1898 if (vers
>= 0 && archi_table
[i
].version
!= vers
)
1901 /* make the call to remove the driver */
1902 status
= rpccli_spoolss_DeletePrinterDriverEx(cli
, mem_ctx
,
1903 cli
->srv_name_slash
,
1904 archi_table
[i
].long_archi
,
1907 archi_table
[i
].version
,
1910 if ( !W_ERROR_IS_OK(result
) )
1912 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1913 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1914 argv
[1], archi_table
[i
].long_archi
, archi_table
[i
].version
, win_errstr(result
));
1919 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv
[1],
1920 archi_table
[i
].long_archi
, archi_table
[i
].version
);
1929 /****************************************************************************
1930 ****************************************************************************/
1932 static WERROR
cmd_spoolss_deletedriver(struct rpc_pipe_client
*cli
,
1933 TALLOC_CTX
*mem_ctx
,
1934 int argc
, const char **argv
)
1936 WERROR result
= WERR_OK
;
1940 /* parse the command arguments */
1942 printf ("Usage: %s <driver>\n", argv
[0]);
1946 /* delete the driver for all architectures */
1947 for (i
=0; archi_table
[i
].long_archi
; i
++) {
1950 /* make the call to remove the driver */
1951 status
= rpccli_spoolss_DeletePrinterDriver(cli
, mem_ctx
,
1952 cli
->srv_name_slash
,
1953 archi_table
[i
].long_archi
,
1956 if (!NT_STATUS_IS_OK(status
)) {
1957 if (W_ERROR_IS_OK(result
)) {
1958 result
= ntstatus_to_werror(status
);
1961 if ( !W_ERROR_IS_OK(result
) ) {
1962 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1963 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1964 argv
[1], archi_table
[i
].long_archi
,
1968 printf ("Driver %s removed for arch [%s].\n", argv
[1],
1969 archi_table
[i
].long_archi
);
1976 /****************************************************************************
1977 ****************************************************************************/
1979 static WERROR
cmd_spoolss_getprintprocdir(struct rpc_pipe_client
*cli
,
1980 TALLOC_CTX
*mem_ctx
,
1981 int argc
, const char **argv
)
1985 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
1988 union spoolss_PrintProcessorDirectoryInfo info
;
1991 /* parse the command arguments */
1993 printf ("Usage: %s [environment]\n", argv
[0]);
1998 environment
= argv
[1];
2001 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
2002 cli
->srv_name_slash
,
2010 if (W_ERROR_EQUAL(result
, WERR_INSUFFICIENT_BUFFER
)) {
2012 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2014 status
= rpccli_spoolss_GetPrintProcessorDirectory(cli
, mem_ctx
,
2015 cli
->srv_name_slash
,
2025 if (W_ERROR_IS_OK(result
)) {
2026 printf("%s\n", info
.info1
.directory_name
);
2032 /****************************************************************************
2033 ****************************************************************************/
2035 static WERROR
cmd_spoolss_addform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2036 int argc
, const char **argv
)
2038 struct policy_handle handle
;
2041 const char *printername
;
2042 union spoolss_AddFormInfo info
;
2043 struct spoolss_AddFormInfo1 info1
;
2044 struct spoolss_AddFormInfo2 info2
;
2047 /* Parse the command arguments */
2049 if (argc
< 3 || argc
> 5) {
2050 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2054 /* Get a printer handle */
2056 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2058 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2062 if (!W_ERROR_IS_OK(werror
))
2065 /* Dummy up some values for the form data */
2068 level
= atoi(argv
[3]);
2073 info1
.flags
= SPOOLSS_FORM_USER
;
2074 info1
.form_name
= argv
[2];
2075 info1
.size
.width
= 100;
2076 info1
.size
.height
= 100;
2077 info1
.area
.left
= 0;
2078 info1
.area
.top
= 10;
2079 info1
.area
.right
= 20;
2080 info1
.area
.bottom
= 30;
2082 info
.info1
= &info1
;
2086 info2
.flags
= SPOOLSS_FORM_USER
;
2087 info2
.form_name
= argv
[2];
2088 info2
.size
.width
= 100;
2089 info2
.size
.height
= 100;
2090 info2
.area
.left
= 0;
2091 info2
.area
.top
= 10;
2092 info2
.area
.right
= 20;
2093 info2
.area
.bottom
= 30;
2094 info2
.keyword
= argv
[2];
2095 info2
.string_type
= SPOOLSS_FORM_STRING_TYPE_NONE
;
2096 info2
.mui_dll
= NULL
;
2097 info2
.ressource_id
= 0;
2098 info2
.display_name
= argv
[2];
2101 info
.info2
= &info2
;
2109 status
= rpccli_spoolss_AddForm(cli
, mem_ctx
,
2116 if (is_valid_policy_hnd(&handle
))
2117 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2122 /****************************************************************************
2123 ****************************************************************************/
2125 static WERROR
cmd_spoolss_setform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2126 int argc
, const char **argv
)
2128 struct policy_handle handle
;
2131 const char *printername
;
2132 union spoolss_AddFormInfo info
;
2133 struct spoolss_AddFormInfo1 info1
;
2135 /* Parse the command arguments */
2138 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2142 /* Get a printer handle */
2144 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2146 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2148 SEC_FLAG_MAXIMUM_ALLOWED
,
2150 if (!W_ERROR_IS_OK(werror
))
2153 /* Dummy up some values for the form data */
2155 info1
.flags
= SPOOLSS_FORM_PRINTER
;
2156 info1
.size
.width
= 100;
2157 info1
.size
.height
= 100;
2158 info1
.area
.left
= 0;
2159 info1
.area
.top
= 1000;
2160 info1
.area
.right
= 2000;
2161 info1
.area
.bottom
= 3000;
2162 info1
.form_name
= argv
[2];
2164 info
.info1
= &info1
;
2168 status
= rpccli_spoolss_SetForm(cli
, mem_ctx
,
2176 if (is_valid_policy_hnd(&handle
))
2177 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2182 /****************************************************************************
2183 ****************************************************************************/
2185 static const char *get_form_flag(int form_flag
)
2187 switch (form_flag
) {
2188 case SPOOLSS_FORM_USER
:
2190 case SPOOLSS_FORM_BUILTIN
:
2191 return "FORM_BUILTIN";
2192 case SPOOLSS_FORM_PRINTER
:
2193 return "FORM_PRINTER";
2199 /****************************************************************************
2200 ****************************************************************************/
2202 static void display_form_info1(struct spoolss_FormInfo1
*r
)
2205 "\tflag: %s (%d)\n" \
2206 "\twidth: %d, length: %d\n" \
2207 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2208 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2209 r
->size
.width
, r
->size
.height
,
2210 r
->area
.left
, r
->area
.right
,
2211 r
->area
.top
, r
->area
.bottom
);
2214 /****************************************************************************
2215 ****************************************************************************/
2217 static void display_form_info2(struct spoolss_FormInfo2
*r
)
2220 "\tflag: %s (%d)\n" \
2221 "\twidth: %d, length: %d\n" \
2222 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2223 r
->form_name
, get_form_flag(r
->flags
), r
->flags
,
2224 r
->size
.width
, r
->size
.height
,
2225 r
->area
.left
, r
->area
.right
,
2226 r
->area
.top
, r
->area
.bottom
);
2227 printf("\tkeyword: %s\n", r
->keyword
);
2228 printf("\tstring_type: 0x%08x\n", r
->string_type
);
2229 printf("\tmui_dll: %s\n", r
->mui_dll
);
2230 printf("\tressource_id: 0x%08x\n", r
->ressource_id
);
2231 printf("\tdisplay_name: %s\n", r
->display_name
);
2232 printf("\tlang_id: %d\n", r
->lang_id
);
2236 /****************************************************************************
2237 ****************************************************************************/
2239 static WERROR
cmd_spoolss_getform(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
2240 int argc
, const char **argv
)
2242 struct policy_handle handle
;
2245 const char *printername
;
2247 uint32_t offered
= 0;
2248 union spoolss_FormInfo info
;
2252 /* Parse the command arguments */
2254 if (argc
< 3 || argc
> 5) {
2255 printf ("Usage: %s <printer> <formname> [level]\n", argv
[0]);
2259 /* Get a printer handle */
2261 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2263 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2265 SEC_FLAG_MAXIMUM_ALLOWED
,
2267 if (!W_ERROR_IS_OK(werror
))
2271 level
= atoi(argv
[3]);
2276 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2285 if (W_ERROR_EQUAL(werror
, WERR_INSUFFICIENT_BUFFER
)) {
2286 buffer
= data_blob_talloc_zero(mem_ctx
, needed
);
2288 status
= rpccli_spoolss_GetForm(cli
, mem_ctx
,
2299 if (!NT_STATUS_IS_OK(status
)) {
2305 display_form_info1(&info
.info1
);
2308 display_form_info2(&info
.info2
);
2313 if (is_valid_policy_hnd(&handle
))
2314 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2319 /****************************************************************************
2320 ****************************************************************************/
2322 static WERROR
cmd_spoolss_deleteform(struct rpc_pipe_client
*cli
,
2323 TALLOC_CTX
*mem_ctx
, int argc
,
2326 struct policy_handle handle
;
2329 const char *printername
;
2331 /* Parse the command arguments */
2334 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
2338 /* Get a printer handle */
2340 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2342 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2344 SEC_FLAG_MAXIMUM_ALLOWED
,
2346 if (!W_ERROR_IS_OK(werror
))
2349 /* Delete the form */
2351 status
= rpccli_spoolss_DeleteForm(cli
, mem_ctx
,
2355 if (!NT_STATUS_IS_OK(status
)) {
2356 return ntstatus_to_werror(status
);
2360 if (is_valid_policy_hnd(&handle
))
2361 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2366 /****************************************************************************
2367 ****************************************************************************/
2369 static WERROR
cmd_spoolss_enum_forms(struct rpc_pipe_client
*cli
,
2370 TALLOC_CTX
*mem_ctx
, int argc
,
2373 struct policy_handle handle
;
2375 const char *printername
;
2376 uint32_t num_forms
, level
= 1, i
;
2377 union spoolss_FormInfo
*forms
;
2379 /* Parse the command arguments */
2381 if (argc
< 2 || argc
> 4) {
2382 printf ("Usage: %s <printer> [level]\n", argv
[0]);
2386 /* Get a printer handle */
2388 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2390 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2392 SEC_FLAG_MAXIMUM_ALLOWED
,
2394 if (!W_ERROR_IS_OK(werror
))
2398 level
= atoi(argv
[2]);
2401 /* Enumerate forms */
2403 werror
= rpccli_spoolss_enumforms(cli
, mem_ctx
,
2410 if (!W_ERROR_IS_OK(werror
))
2413 /* Display output */
2415 for (i
= 0; i
< num_forms
; i
++) {
2418 display_form_info1(&forms
[i
].info1
);
2421 display_form_info2(&forms
[i
].info2
);
2427 if (is_valid_policy_hnd(&handle
))
2428 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
2433 /****************************************************************************
2434 ****************************************************************************/
2436 static WERROR
cmd_spoolss_setprinterdata(struct rpc_pipe_client
*cli
,
2437 TALLOC_CTX
*mem_ctx
,
2438 int argc
, const char **argv
)
2442 const char *printername
;
2443 struct policy_handle pol
;
2444 union spoolss_PrinterInfo info
;
2445 enum winreg_Type type
;
2446 union spoolss_PrinterData data
;
2449 /* parse the command arguments */
2451 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2452 " <value> <data>\n",
2457 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2461 if (strequal(argv
[2], "string")) {
2465 if (strequal(argv
[2], "binary")) {
2469 if (strequal(argv
[2], "dword")) {
2473 if (strequal(argv
[2], "multistring")) {
2474 type
= REG_MULTI_SZ
;
2477 if (type
== REG_NONE
) {
2478 printf("Unknown data type: %s\n", argv
[2]);
2479 result
= WERR_INVALID_PARAM
;
2483 /* get a printer handle */
2485 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2487 SEC_FLAG_MAXIMUM_ALLOWED
,
2489 if (!W_ERROR_IS_OK(result
)) {
2493 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2498 if (!W_ERROR_IS_OK(result
)) {
2502 printf("%s\n", current_timestring(mem_ctx
, true));
2503 printf("\tchange_id (before set)\t:[0x%x]\n", info
.info0
.change_id
);
2505 /* Set the printer data */
2509 data
.string
= talloc_strdup(mem_ctx
, argv
[4]);
2510 W_ERROR_HAVE_NO_MEMORY(data
.string
);
2513 data
.value
= strtoul(argv
[4], NULL
, 10);
2516 data
.binary
= strhex_to_data_blob(mem_ctx
, argv
[4]);
2518 case REG_MULTI_SZ
: {
2520 const char **strings
= NULL
;
2522 for (i
=4; i
<argc
; i
++) {
2523 if (strcmp(argv
[i
], "NULL") == 0) {
2526 if (!add_string_to_array(mem_ctx
, argv
[i
],
2529 result
= WERR_NOMEM
;
2533 data
.string_array
= talloc_zero_array(mem_ctx
, const char *, num_strings
+ 1);
2534 if (!data
.string_array
) {
2535 result
= WERR_NOMEM
;
2538 for (i
=0; i
< num_strings
; i
++) {
2539 data
.string_array
[i
] = strings
[i
];
2544 printf("Unknown data type: %s\n", argv
[2]);
2545 result
= WERR_INVALID_PARAM
;
2549 result
= push_spoolss_PrinterData(mem_ctx
, &blob
, type
, &data
);
2550 if (!W_ERROR_IS_OK(result
)) {
2554 status
= rpccli_spoolss_SetPrinterData(cli
, mem_ctx
,
2556 argv
[3], /* value_name */
2561 if (!W_ERROR_IS_OK(result
)) {
2562 printf ("Unable to set [%s=%s]!\n", argv
[3], argv
[4]);
2565 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[3], argv
[4]);
2567 result
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
2572 if (!W_ERROR_IS_OK(result
)) {
2576 printf("%s\n", current_timestring(mem_ctx
, true));
2577 printf("\tchange_id (after set)\t:[0x%x]\n", info
.info0
.change_id
);
2581 if (is_valid_policy_hnd(&pol
)) {
2582 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
2588 /****************************************************************************
2589 ****************************************************************************/
2591 static void display_job_info1(struct spoolss_JobInfo1
*r
)
2593 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r
->position
, r
->job_id
,
2594 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2598 /****************************************************************************
2599 ****************************************************************************/
2601 static void display_job_info2(struct spoolss_JobInfo2
*r
)
2603 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2604 r
->position
, r
->job_id
,
2605 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2606 r
->total_pages
, r
->size
);
2609 /****************************************************************************
2610 ****************************************************************************/
2612 static void display_job_info3(struct spoolss_JobInfo3
*r
)
2614 printf("jobid[%d], next_jobid[%d]\n",
2615 r
->job_id
, r
->next_job_id
);
2618 /****************************************************************************
2619 ****************************************************************************/
2621 static void display_job_info4(struct spoolss_JobInfo4
*r
)
2623 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2624 r
->position
, r
->job_id
,
2625 r
->user_name
, r
->document_name
, r
->text_status
, r
->pages_printed
,
2626 r
->total_pages
, r
->size
, r
->size_high
);
2629 /****************************************************************************
2630 ****************************************************************************/
2632 static WERROR
cmd_spoolss_enum_jobs(struct rpc_pipe_client
*cli
,
2633 TALLOC_CTX
*mem_ctx
, int argc
,
2637 uint32_t level
= 1, count
, i
;
2638 const char *printername
;
2639 struct policy_handle hnd
;
2640 union spoolss_JobInfo
*info
;
2642 if (argc
< 2 || argc
> 3) {
2643 printf("Usage: %s printername [level]\n", argv
[0]);
2648 level
= atoi(argv
[2]);
2651 /* Open printer handle */
2653 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2655 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2657 SEC_FLAG_MAXIMUM_ALLOWED
,
2659 if (!W_ERROR_IS_OK(result
))
2662 /* Enumerate ports */
2664 result
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
2672 if (!W_ERROR_IS_OK(result
)) {
2676 for (i
= 0; i
< count
; i
++) {
2679 display_job_info1(&info
[i
].info1
);
2682 display_job_info2(&info
[i
].info2
);
2685 d_printf("unknown info level %d\n", level
);
2691 if (is_valid_policy_hnd(&hnd
)) {
2692 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2698 /****************************************************************************
2699 ****************************************************************************/
2701 static WERROR
cmd_spoolss_get_job(struct rpc_pipe_client
*cli
,
2702 TALLOC_CTX
*mem_ctx
, int argc
,
2706 const char *printername
;
2707 struct policy_handle hnd
;
2710 union spoolss_JobInfo info
;
2712 if (argc
< 3 || argc
> 4) {
2713 printf("Usage: %s printername job_id [level]\n", argv
[0]);
2717 job_id
= atoi(argv
[2]);
2720 level
= atoi(argv
[3]);
2723 /* Open printer handle */
2725 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2727 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2729 SEC_FLAG_MAXIMUM_ALLOWED
,
2731 if (!W_ERROR_IS_OK(result
)) {
2735 /* Enumerate ports */
2737 result
= rpccli_spoolss_getjob(cli
, mem_ctx
,
2744 if (!W_ERROR_IS_OK(result
)) {
2750 display_job_info1(&info
.info1
);
2753 display_job_info2(&info
.info2
);
2756 display_job_info3(&info
.info3
);
2759 display_job_info4(&info
.info4
);
2762 d_printf("unknown info level %d\n", level
);
2767 if (is_valid_policy_hnd(&hnd
)) {
2768 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2774 /****************************************************************************
2775 ****************************************************************************/
2779 enum spoolss_JobControl val
;
2781 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE
},
2782 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME
},
2783 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL
},
2784 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART
},
2785 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE
},
2786 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
},
2787 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
},
2788 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN
},
2789 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE
}
2792 static enum spoolss_JobControl
parse_setjob_command(const char *cmd
)
2796 for (i
= 0; i
< sizeof(cmdvals
)/sizeof(cmdvals
[0]); i
++) {
2797 if (strequal(cmdvals
[i
].name
, cmd
)) {
2798 return cmdvals
[i
].val
;
2801 return (enum spoolss_JobControl
)atoi(cmd
);
2804 static WERROR
cmd_spoolss_set_job(struct rpc_pipe_client
*cli
,
2805 TALLOC_CTX
*mem_ctx
, int argc
,
2810 const char *printername
;
2811 struct policy_handle hnd
;
2813 enum spoolss_JobControl command
;
2816 printf("Usage: %s printername job_id command\n", argv
[0]);
2817 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2818 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2822 job_id
= atoi(argv
[2]);
2823 command
= parse_setjob_command(argv
[3]);
2825 /* Open printer handle */
2827 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2829 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2831 SEC_FLAG_MAXIMUM_ALLOWED
,
2833 if (!W_ERROR_IS_OK(result
)) {
2839 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
2846 if (!W_ERROR_IS_OK(result
)) {
2851 if (is_valid_policy_hnd(&hnd
)) {
2852 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2858 /****************************************************************************
2859 ****************************************************************************/
2861 static WERROR
cmd_spoolss_enum_data(struct rpc_pipe_client
*cli
,
2862 TALLOC_CTX
*mem_ctx
, int argc
,
2868 const char *printername
;
2869 struct policy_handle hnd
;
2870 uint32_t value_offered
= 0;
2871 const char *value_name
= NULL
;
2872 uint32_t value_needed
;
2873 enum winreg_Type type
;
2874 uint8_t *data
= NULL
;
2875 uint32_t data_offered
= 0;
2876 uint32_t data_needed
;
2879 printf("Usage: %s printername\n", argv
[0]);
2883 /* Open printer handle */
2885 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2887 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2889 SEC_FLAG_MAXIMUM_ALLOWED
,
2891 if (!W_ERROR_IS_OK(result
)) {
2895 /* Enumerate data */
2897 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2909 if (!NT_STATUS_IS_OK(status
)) {
2910 result
= ntstatus_to_werror(status
);
2914 if (!W_ERROR_IS_OK(result
)) {
2918 data_offered
= data_needed
;
2919 value_offered
= value_needed
;
2920 data
= talloc_zero_array(mem_ctx
, uint8_t, data_needed
);
2921 value_name
= talloc_zero_array(mem_ctx
, char, value_needed
);
2923 while (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2925 status
= rpccli_spoolss_EnumPrinterData(cli
, mem_ctx
,
2936 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(result
)) {
2937 struct regval_blob
*v
;
2939 v
= regval_compose(talloc_tos(),
2945 result
= WERR_NOMEM
;
2949 display_reg_value(v
);
2954 if (W_ERROR_V(result
) == ERRnomoreitems
) {
2955 result
= W_ERROR(ERRsuccess
);
2959 if (is_valid_policy_hnd(&hnd
)) {
2960 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
2966 /****************************************************************************
2967 ****************************************************************************/
2969 static WERROR
cmd_spoolss_enum_data_ex( struct rpc_pipe_client
*cli
,
2970 TALLOC_CTX
*mem_ctx
, int argc
,
2975 const char *printername
;
2976 struct policy_handle hnd
;
2978 struct spoolss_PrinterEnumValues
*info
;
2981 printf("Usage: %s printername <keyname>\n", argv
[0]);
2985 /* Open printer handle */
2987 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
2989 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
2991 SEC_FLAG_MAXIMUM_ALLOWED
,
2993 if (!W_ERROR_IS_OK(result
)) {
2997 /* Enumerate subkeys */
2999 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
,
3005 if (!W_ERROR_IS_OK(result
)) {
3009 for (i
=0; i
< count
; i
++) {
3010 display_printer_data(info
[i
].value_name
,
3013 info
[i
].data
->length
);
3017 if (is_valid_policy_hnd(&hnd
)) {
3018 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3024 /****************************************************************************
3025 ****************************************************************************/
3027 static WERROR
cmd_spoolss_enum_printerkey(struct rpc_pipe_client
*cli
,
3028 TALLOC_CTX
*mem_ctx
, int argc
,
3032 const char *printername
;
3033 const char *keyname
= NULL
;
3034 struct policy_handle hnd
;
3035 const char **key_buffer
= NULL
;
3037 uint32_t offered
= 0;
3039 if (argc
< 2 || argc
> 4) {
3040 printf("Usage: %s printername [keyname] [offered]\n", argv
[0]);
3051 offered
= atoi(argv
[3]);
3054 /* Open printer handle */
3056 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3058 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3060 SEC_FLAG_MAXIMUM_ALLOWED
,
3062 if (!W_ERROR_IS_OK(result
)) {
3066 /* Enumerate subkeys */
3068 result
= rpccli_spoolss_enumprinterkey(cli
, mem_ctx
,
3074 if (!W_ERROR_IS_OK(result
)) {
3078 for (i
=0; key_buffer
&& key_buffer
[i
]; i
++) {
3079 printf("%s\n", key_buffer
[i
]);
3084 if (is_valid_policy_hnd(&hnd
)) {
3085 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3091 /****************************************************************************
3092 ****************************************************************************/
3094 static WERROR
cmd_spoolss_rffpcnex(struct rpc_pipe_client
*cli
,
3095 TALLOC_CTX
*mem_ctx
, int argc
,
3098 const char *printername
;
3099 const char *clientname
;
3100 struct policy_handle hnd
;
3103 struct spoolss_NotifyOption option
;
3106 printf("Usage: %s printername\n", argv
[0]);
3113 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3115 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3117 SEC_FLAG_MAXIMUM_ALLOWED
,
3119 if (!W_ERROR_IS_OK(result
)) {
3120 printf("Error opening %s\n", argv
[1]);
3124 /* Create spool options */
3129 option
.types
= talloc_array(mem_ctx
, struct spoolss_NotifyOptionType
, 2);
3130 if (option
.types
== NULL
) {
3131 result
= WERR_NOMEM
;
3135 option
.types
[0].type
= PRINTER_NOTIFY_TYPE
;
3136 option
.types
[0].count
= 1;
3137 option
.types
[0].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3138 if (option
.types
[0].fields
== NULL
) {
3139 result
= WERR_NOMEM
;
3142 option
.types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
3144 option
.types
[1].type
= JOB_NOTIFY_TYPE
;
3145 option
.types
[1].count
= 1;
3146 option
.types
[1].fields
= talloc_array(mem_ctx
, union spoolss_Field
, 1);
3147 if (option
.types
[1].fields
== NULL
) {
3148 result
= WERR_NOMEM
;
3151 option
.types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_PRINTER_NAME
;
3153 clientname
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
3155 result
= WERR_NOMEM
;
3161 status
= rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli
, mem_ctx
,
3169 if (!W_ERROR_IS_OK(result
)) {
3170 printf("Error rffpcnex %s\n", argv
[1]);
3175 if (is_valid_policy_hnd(&hnd
))
3176 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &hnd
, NULL
);
3181 /****************************************************************************
3182 ****************************************************************************/
3184 static bool compare_printer( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3185 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3187 union spoolss_PrinterInfo info1
, info2
;
3189 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer");
3191 printf("Retrieving printer propertiesfor %s...", cli1
->desthost
);
3192 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3197 if ( !W_ERROR_IS_OK(werror
) ) {
3198 printf("failed (%s)\n", win_errstr(werror
));
3199 talloc_destroy(mem_ctx
);
3204 printf("Retrieving printer properties for %s...", cli2
->desthost
);
3205 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3210 if ( !W_ERROR_IS_OK(werror
) ) {
3211 printf("failed (%s)\n", win_errstr(werror
));
3212 talloc_destroy(mem_ctx
);
3217 talloc_destroy(mem_ctx
);
3222 /****************************************************************************
3223 ****************************************************************************/
3225 static bool compare_printer_secdesc( struct rpc_pipe_client
*cli1
, struct policy_handle
*hnd1
,
3226 struct rpc_pipe_client
*cli2
, struct policy_handle
*hnd2
)
3228 union spoolss_PrinterInfo info1
, info2
;
3230 TALLOC_CTX
*mem_ctx
= talloc_init("compare_printer_secdesc");
3231 struct security_descriptor
*sd1
, *sd2
;
3235 printf("Retrieving printer security for %s...", cli1
->desthost
);
3236 werror
= rpccli_spoolss_getprinter(cli1
, mem_ctx
,
3241 if ( !W_ERROR_IS_OK(werror
) ) {
3242 printf("failed (%s)\n", win_errstr(werror
));
3248 printf("Retrieving printer security for %s...", cli2
->desthost
);
3249 werror
= rpccli_spoolss_getprinter(cli2
, mem_ctx
,
3254 if ( !W_ERROR_IS_OK(werror
) ) {
3255 printf("failed (%s)\n", win_errstr(werror
));
3264 sd1
= info1
.info3
.secdesc
;
3265 sd2
= info2
.info3
.secdesc
;
3267 if ( (sd1
!= sd2
) && ( !sd1
|| !sd2
) ) {
3268 printf("NULL secdesc!\n");
3273 if (!security_descriptor_equal( sd1
, sd2
) ) {
3274 printf("Security Descriptors *not* equal!\n");
3279 printf("Security descriptors match\n");
3282 talloc_destroy(mem_ctx
);
3287 /****************************************************************************
3288 ****************************************************************************/
3290 extern struct user_auth_info
*rpcclient_auth_info
;
3292 static WERROR
cmd_spoolss_printercmp(struct rpc_pipe_client
*cli
,
3293 TALLOC_CTX
*mem_ctx
, int argc
,
3296 const char *printername
;
3297 char *printername_path
= NULL
;
3298 struct cli_state
*cli_server2
= NULL
;
3299 struct rpc_pipe_client
*cli2
= NULL
;
3300 struct policy_handle hPrinter1
, hPrinter2
;
3305 printf("Usage: %s <printer> <server>\n", argv
[0]);
3309 printername
= argv
[1];
3311 /* first get the connection to the remote server */
3313 nt_status
= cli_full_connection(&cli_server2
, global_myname(), argv
[2],
3316 get_cmdline_auth_info_username(rpcclient_auth_info
),
3318 get_cmdline_auth_info_password(rpcclient_auth_info
),
3319 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info
) ? CLI_FULL_CONNECTION_USE_KERBEROS
: 0,
3320 get_cmdline_auth_info_signing_state(rpcclient_auth_info
));
3322 if ( !NT_STATUS_IS_OK(nt_status
) )
3323 return WERR_GENERAL_FAILURE
;
3325 nt_status
= cli_rpc_pipe_open_noauth(cli_server2
, &ndr_table_spoolss
.syntax_id
,
3327 if (!NT_STATUS_IS_OK(nt_status
)) {
3328 printf("failed to open spoolss pipe on server %s (%s)\n",
3329 argv
[2], nt_errstr(nt_status
));
3330 return WERR_GENERAL_FAILURE
;
3333 /* now open up both printers */
3335 RPCCLIENT_PRINTERNAME(printername_path
, cli
, printername
);
3337 printf("Opening %s...", printername_path
);
3339 werror
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3343 if ( !W_ERROR_IS_OK(werror
) ) {
3344 printf("failed (%s)\n", win_errstr(werror
));
3349 RPCCLIENT_PRINTERNAME(printername_path
, cli2
, printername
);
3351 printf("Opening %s...", printername_path
);
3352 werror
= rpccli_spoolss_openprinter_ex(cli2
, mem_ctx
,
3356 if ( !W_ERROR_IS_OK(werror
) ) {
3357 printf("failed (%s)\n", win_errstr(werror
));
3362 compare_printer( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3363 compare_printer_secdesc( cli
, &hPrinter1
, cli2
, &hPrinter2
);
3365 compare_printerdata( cli_server1
, &hPrinter1
, cli_server2
, &hPrinter2
);
3372 printf("Closing printers...");
3373 rpccli_spoolss_ClosePrinter( cli
, mem_ctx
, &hPrinter1
, NULL
);
3374 rpccli_spoolss_ClosePrinter( cli2
, mem_ctx
, &hPrinter2
, NULL
);
3377 /* close the second remote connection */
3379 cli_shutdown( cli_server2
);
3383 static void display_proc_info1(struct spoolss_PrintProcessorInfo1
*r
)
3385 printf("print_processor_name: %s\n", r
->print_processor_name
);
3388 static WERROR
cmd_spoolss_enum_procs(struct rpc_pipe_client
*cli
,
3389 TALLOC_CTX
*mem_ctx
, int argc
,
3393 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3394 uint32_t num_procs
, level
= 1, i
;
3395 union spoolss_PrintProcessorInfo
*procs
;
3397 /* Parse the command arguments */
3399 if (argc
< 1 || argc
> 4) {
3400 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3405 environment
= argv
[1];
3409 level
= atoi(argv
[2]);
3412 /* Enumerate Print Processors */
3414 werror
= rpccli_spoolss_enumprintprocessors(cli
, mem_ctx
,
3415 cli
->srv_name_slash
,
3421 if (!W_ERROR_IS_OK(werror
))
3424 /* Display output */
3426 for (i
= 0; i
< num_procs
; i
++) {
3429 display_proc_info1(&procs
[i
].info1
);
3438 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1
*r
)
3440 printf("name_array: %s\n", r
->name_array
);
3443 static WERROR
cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client
*cli
,
3444 TALLOC_CTX
*mem_ctx
, int argc
,
3448 const char *print_processor_name
= "winprint";
3449 uint32_t num_procs
, level
= 1, i
;
3450 union spoolss_PrintProcDataTypesInfo
*procs
;
3452 /* Parse the command arguments */
3454 if (argc
< 1 || argc
> 4) {
3455 printf ("Usage: %s [environment] [level]\n", argv
[0]);
3460 print_processor_name
= argv
[1];
3464 level
= atoi(argv
[2]);
3467 /* Enumerate Print Processor Data Types */
3469 werror
= rpccli_spoolss_enumprintprocessordatatypes(cli
, mem_ctx
,
3470 cli
->srv_name_slash
,
3471 print_processor_name
,
3476 if (!W_ERROR_IS_OK(werror
))
3479 /* Display output */
3481 for (i
= 0; i
< num_procs
; i
++) {
3484 display_proc_data_types_info1(&procs
[i
].info1
);
3493 static void display_monitor1(const struct spoolss_MonitorInfo1
*r
)
3495 printf("monitor_name: %s\n", r
->monitor_name
);
3498 static void display_monitor2(const struct spoolss_MonitorInfo2
*r
)
3500 printf("monitor_name: %s\n", r
->monitor_name
);
3501 printf("environment: %s\n", r
->environment
);
3502 printf("dll_name: %s\n", r
->dll_name
);
3505 static WERROR
cmd_spoolss_enum_monitors(struct rpc_pipe_client
*cli
,
3506 TALLOC_CTX
*mem_ctx
, int argc
,
3510 uint32_t count
, level
= 1, i
;
3511 union spoolss_MonitorInfo
*info
;
3513 /* Parse the command arguments */
3516 printf("Usage: %s [level]\n", argv
[0]);
3521 level
= atoi(argv
[1]);
3524 /* Enumerate Print Monitors */
3526 werror
= rpccli_spoolss_enummonitors(cli
, mem_ctx
,
3527 cli
->srv_name_slash
,
3532 if (!W_ERROR_IS_OK(werror
)) {
3536 /* Display output */
3538 for (i
= 0; i
< count
; i
++) {
3541 display_monitor1(&info
[i
].info1
);
3544 display_monitor2(&info
[i
].info2
);
3553 static WERROR
cmd_spoolss_create_printer_ic(struct rpc_pipe_client
*cli
,
3554 TALLOC_CTX
*mem_ctx
, int argc
,
3559 struct policy_handle handle
, gdi_handle
;
3560 const char *printername
;
3561 struct spoolss_DevmodeContainer devmode_ctr
;
3563 RPCCLIENT_PRINTERNAME(printername
, cli
, argv
[1]);
3565 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
3567 SEC_FLAG_MAXIMUM_ALLOWED
,
3569 if (!W_ERROR_IS_OK(result
)) {
3573 ZERO_STRUCT(devmode_ctr
);
3575 status
= rpccli_spoolss_CreatePrinterIC(cli
, mem_ctx
,
3580 if (!W_ERROR_IS_OK(result
)) {
3585 if (is_valid_policy_hnd(&gdi_handle
)) {
3586 rpccli_spoolss_DeletePrinterIC(cli
, mem_ctx
, &gdi_handle
, NULL
);
3588 if (is_valid_policy_hnd(&handle
)) {
3589 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3595 /* List of commands exported by this module */
3596 struct cmd_set spoolss_commands
[] = {
3600 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a print driver", "" },
3601 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add a printer", "" },
3602 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver", "" },
3603 { "deldriverex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriverex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete a printer driver with files", "" },
3604 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data", "" },
3605 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer data for a key", "" },
3606 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer keys", "" },
3607 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate print jobs", "" },
3608 { "getjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_get_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print job", "" },
3609 { "setjob", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_set_job
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set print job", "" },
3610 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printer ports", "" },
3611 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate installed printer drivers", "" },
3612 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate printers", "" },
3613 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver data", "" },
3614 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer driver data with keyname", ""},
3615 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver information", "" },
3616 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print driver upload directory", "" },
3617 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get printer info", "" },
3618 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer
, &ndr_table_spoolss
.syntax_id
, NULL
, "Open printer handle", "" },
3619 { "openprinter_ex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Open printer handle", "" },
3620 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer driver", "" },
3621 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get print processor directory", "" },
3622 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Add form", "" },
3623 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set form", "" },
3624 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Get form", "" },
3625 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, &ndr_table_spoolss
.syntax_id
, NULL
, "Delete form", "" },
3626 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate forms", "" },
3627 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printer comment", "" },
3628 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set printername", "" },
3629 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, &ndr_table_spoolss
.syntax_id
, NULL
, "Set REG_SZ printer data", "" },
3630 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, &ndr_table_spoolss
.syntax_id
, NULL
, "Rffpcnex test", "" },
3631 { "printercmp", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_printercmp
, &ndr_table_spoolss
.syntax_id
, NULL
, "Printer comparison test", "" },
3632 { "enumprocs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_procs
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processors", "" },
3633 { "enumprocdatatypes", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_proc_data_types
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Processor Data Types", "" },
3634 { "enummonitors", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_monitors
, &ndr_table_spoolss
.syntax_id
, NULL
, "Enumerate Print Monitors", "" },
3635 { "createprinteric", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_create_printer_ic
, &ndr_table_spoolss
.syntax_id
, NULL
, "Create Printer IC", "" },