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"
37 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
39 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
40 _cli->srv_name_slash, _arg); \
41 W_ERROR_HAVE_NO_MEMORY(_printername); \
44 /* The version int is used by getdrivers. Note that
45 all architecture strings that support mutliple
46 versions must be grouped together since enumdrivers
47 uses this property to prevent issuing multiple
48 enumdriver calls for the same arch */
51 static const struct print_architecture_table_node archi_table[]= {
53 {"Windows 4.0", "WIN40", 0 },
54 {"Windows NT x86", "W32X86", 2 },
55 {"Windows NT x86", "W32X86", 3 },
56 {"Windows NT R4000", "W32MIPS", 2 },
57 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
58 {"Windows NT PowerPC", "W32PPC", 2 },
59 {"Windows IA64", "IA64", 3 },
60 {"Windows x64", "x64", 3 },
67 * rpcclient module for SPOOLSS rpc pipe.
69 * This generally just parses and checks command lines, and then calls
70 * a cli_spoolss function.
73 /****************************************************************************
74 function to do the mapping between the long architecture name and
76 ****************************************************************************/
78 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
82 DEBUG(107,("Getting architecture dependent directory\n"));
85 } while ( (archi_table[i].long_archi!=NULL ) &&
86 strcasecmp_m(long_archi, archi_table[i].long_archi) );
88 if (archi_table[i].long_archi==NULL) {
89 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
93 /* this might be client code - but shouldn't this be an fstrcpy etc? */
96 DEBUGADD(108,("index: [%d]\n", i));
97 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
98 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
100 return archi_table[i].short_archi;
103 /****************************************************************************
104 ****************************************************************************/
106 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
108 int argc, const char **argv)
111 struct policy_handle hnd;
112 uint32_t access_mask = PRINTER_ALL_ACCESS;
113 struct dcerpc_binding_handle *b = cli->binding_handle;
116 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
121 sscanf(argv[2], "%x", &access_mask);
124 /* Open the printer handle */
126 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
130 if (W_ERROR_IS_OK(werror)) {
131 printf("Printer %s opened successfully\n", argv[1]);
132 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
134 if (!W_ERROR_IS_OK(werror)) {
135 printf("Error closing printer handle! (%s)\n",
136 get_dos_error_msg(werror));
143 /****************************************************************************
144 ****************************************************************************/
146 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
148 int argc, const char **argv)
151 struct policy_handle hnd;
152 uint32_t access_mask = PRINTER_ALL_ACCESS;
154 struct spoolss_DevmodeContainer devmode_ctr;
155 struct dcerpc_binding_handle *b = cli->binding_handle;
157 ZERO_STRUCT(devmode_ctr);
160 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
165 sscanf(argv[2], "%x", &access_mask);
168 /* Open the printer handle */
170 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
177 if (!NT_STATUS_IS_OK(status)) {
178 return ntstatus_to_werror(status);
180 if (W_ERROR_IS_OK(werror)) {
181 printf("Printer %s opened successfully\n", argv[1]);
182 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
184 if (!W_ERROR_IS_OK(werror)) {
185 printf("Error closing printer handle! (%s)\n",
186 get_dos_error_msg(werror));
193 /****************************************************************************
194 ****************************************************************************/
196 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
201 printf("\tprintername:[%s]\n", r->printername);
202 printf("\tservername:[%s]\n", r->servername);
203 printf("\tcjobs:[0x%x]\n", r->cjobs);
204 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
205 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
206 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
207 r->time.day, r->time.day_of_week);
208 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
209 r->time.second, r->time.millisecond);
211 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
212 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
214 printf("\tversion:[0x%x]\n", r->version);
215 printf("\tfree_build:[0x%x]\n", r->free_build);
216 printf("\tspooling:[0x%x]\n", r->spooling);
217 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
218 printf("\tsession_counter:[0x%x]\n", r->session_counter);
219 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
220 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
221 printf("\tjob_error:[0x%x]\n", r->job_error);
222 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
223 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
224 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
225 printf("\tchange_id:[0x%x]\n", r->change_id);
226 printf("\tlast_error: %s\n", win_errstr(r->last_error));
227 printf("\tstatus:[0x%x]\n", r->status);
228 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
229 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
230 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
231 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
232 printf("\tref_ic:[0x%x]\n", r->ref_ic);
233 printf("\treserved2:[0x%x]\n", r->reserved2);
234 printf("\treserved3:[0x%x]\n", r->reserved3);
239 /****************************************************************************
240 ****************************************************************************/
242 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
244 printf("\tflags:[0x%x]\n", r->flags);
245 printf("\tname:[%s]\n", r->name);
246 printf("\tdescription:[%s]\n", r->description);
247 printf("\tcomment:[%s]\n", r->comment);
252 /****************************************************************************
253 ****************************************************************************/
255 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
257 printf("\tservername:[%s]\n", r->servername);
258 printf("\tprintername:[%s]\n", r->printername);
259 printf("\tsharename:[%s]\n", r->sharename);
260 printf("\tportname:[%s]\n", r->portname);
261 printf("\tdrivername:[%s]\n", r->drivername);
262 printf("\tcomment:[%s]\n", r->comment);
263 printf("\tlocation:[%s]\n", r->location);
264 printf("\tsepfile:[%s]\n", r->sepfile);
265 printf("\tprintprocessor:[%s]\n", r->printprocessor);
266 printf("\tdatatype:[%s]\n", r->datatype);
267 printf("\tparameters:[%s]\n", r->parameters);
268 printf("\tattributes:[0x%x]\n", r->attributes);
269 printf("\tpriority:[0x%x]\n", r->priority);
270 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
271 printf("\tstarttime:[0x%x]\n", r->starttime);
272 printf("\tuntiltime:[0x%x]\n", r->untiltime);
273 printf("\tstatus:[0x%x]\n", r->status);
274 printf("\tcjobs:[0x%x]\n", r->cjobs);
275 printf("\taverageppm:[0x%x]\n", r->averageppm);
278 display_sec_desc(r->secdesc);
283 /****************************************************************************
284 ****************************************************************************/
286 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
288 display_sec_desc(r->secdesc);
293 /****************************************************************************
294 ****************************************************************************/
296 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
298 printf("\tservername:[%s]\n", r->servername);
299 printf("\tprintername:[%s]\n", r->printername);
300 printf("\tattributes:[0x%x]\n", r->attributes);
304 /****************************************************************************
305 ****************************************************************************/
307 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
309 printf("\tprintername:[%s]\n", r->printername);
310 printf("\tportname:[%s]\n", r->portname);
311 printf("\tattributes:[0x%x]\n", r->attributes);
312 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
313 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
317 /****************************************************************************
318 ****************************************************************************/
320 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
322 printf("\tstatus:[0x%x]\n", r->status);
326 /****************************************************************************
327 ****************************************************************************/
329 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
331 printf("\tguid:[%s]\n", r->guid);
332 printf("\taction:[0x%x]\n", r->action);
336 /****************************************************************************
337 ****************************************************************************/
339 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
341 int argc, const char **argv)
345 union spoolss_PrinterInfo *info;
348 uint32_t flags = PRINTER_ENUM_LOCAL;
351 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
356 level = atoi(argv[1]);
362 name = cli->srv_name_slash;
366 flags = atoi(argv[3]);
369 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
376 if (W_ERROR_IS_OK(result)) {
379 printf ("No printers returned.\n");
383 for (i = 0; i < count; i++) {
386 display_print_info0(&info[i].info0);
389 display_print_info1(&info[i].info1);
392 display_print_info2(&info[i].info2);
395 display_print_info3(&info[i].info3);
398 display_print_info4(&info[i].info4);
401 display_print_info5(&info[i].info5);
404 display_print_info6(&info[i].info6);
407 printf("unknown info level %d\n", level);
417 /****************************************************************************
418 ****************************************************************************/
420 static void display_port_info_1(struct spoolss_PortInfo1 *r)
422 printf("\tPort Name:\t[%s]\n", r->port_name);
425 /****************************************************************************
426 ****************************************************************************/
428 static void display_port_info_2(struct spoolss_PortInfo2 *r)
430 printf("\tPort Name:\t[%s]\n", r->port_name);
431 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
432 printf("\tDescription:\t[%s]\n", r->description);
433 printf("\tPort Type:\t" );
435 int comma = 0; /* hack */
437 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
441 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
442 printf( "%sWrite", comma ? ", " : "" );
445 /* These two have slightly different interpretations
446 on 95/98/ME but I'm disregarding that for now */
447 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
448 printf( "%sRedirected", comma ? ", " : "" );
451 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
452 printf( "%sNet-Attached", comma ? ", " : "" );
456 printf( "[Unset]\n" );
458 printf("\tReserved:\t[%d]\n", r->reserved);
462 /****************************************************************************
463 ****************************************************************************/
465 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
466 TALLOC_CTX *mem_ctx, int argc,
472 union spoolss_PortInfo *info;
475 printf("Usage: %s [level]\n", argv[0]);
480 level = atoi(argv[1]);
483 /* Enumerate ports */
485 result = rpccli_spoolss_enumports(cli, mem_ctx,
491 if (W_ERROR_IS_OK(result)) {
494 for (i = 0; i < count; i++) {
497 display_port_info_1(&info[i].info1);
500 display_port_info_2(&info[i].info2);
503 printf("unknown info level %d\n", level);
512 /****************************************************************************
513 ****************************************************************************/
515 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
517 int argc, const char **argv)
519 struct policy_handle pol;
522 uint32_t info_level = 2;
523 union spoolss_PrinterInfo info;
524 struct spoolss_SetPrinterInfoCtr info_ctr;
525 struct spoolss_SetPrinterInfo2 info2;
526 const char *printername, *comment = NULL;
527 struct spoolss_DevmodeContainer devmode_ctr;
528 struct sec_desc_buf secdesc_ctr;
529 struct dcerpc_binding_handle *b = cli->binding_handle;
531 if (argc == 1 || argc > 3) {
532 printf("Usage: %s printername comment\n", argv[0]);
537 /* Open a printer handle */
542 ZERO_STRUCT(devmode_ctr);
543 ZERO_STRUCT(secdesc_ctr);
545 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
547 /* get a printer handle */
548 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
552 if (!W_ERROR_IS_OK(result))
555 /* Get printer info */
556 result = rpccli_spoolss_getprinter(cli, mem_ctx,
561 if (!W_ERROR_IS_OK(result))
565 /* Modify the comment. */
566 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
567 info2.comment = comment;
570 info_ctr.info.info2 = &info2;
572 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
579 if (!NT_STATUS_IS_OK(status)) {
580 result = ntstatus_to_werror(status);
583 if (W_ERROR_IS_OK(result))
584 printf("Success in setting comment.\n");
587 if (is_valid_policy_hnd(&pol)) {
589 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
595 /****************************************************************************
596 ****************************************************************************/
598 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
600 int argc, const char **argv)
602 struct policy_handle pol;
605 uint32_t info_level = 2;
606 union spoolss_PrinterInfo info;
607 const char *printername,
608 *new_printername = NULL;
609 struct spoolss_SetPrinterInfoCtr info_ctr;
610 struct spoolss_SetPrinterInfo2 info2;
611 struct spoolss_DevmodeContainer devmode_ctr;
612 struct sec_desc_buf secdesc_ctr;
613 struct dcerpc_binding_handle *b = cli->binding_handle;
615 ZERO_STRUCT(devmode_ctr);
616 ZERO_STRUCT(secdesc_ctr);
618 if (argc == 1 || argc > 3) {
619 printf("Usage: %s printername new_printername\n", argv[0]);
624 /* Open a printer handle */
626 new_printername = argv[2];
629 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
631 /* get a printer handle */
632 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
636 if (!W_ERROR_IS_OK(result))
639 /* Get printer info */
640 result = rpccli_spoolss_getprinter(cli, mem_ctx,
645 if (!W_ERROR_IS_OK(result))
648 /* Modify the printername. */
649 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
650 info2.printername = new_printername;
653 info_ctr.info.info2 = &info2;
655 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
662 if (!NT_STATUS_IS_OK(status)) {
663 result = ntstatus_to_werror(status);
666 if (W_ERROR_IS_OK(result))
667 printf("Success in setting printername.\n");
670 if (is_valid_policy_hnd(&pol)) {
672 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
678 /****************************************************************************
679 ****************************************************************************/
681 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
683 int argc, const char **argv)
685 struct policy_handle pol;
688 const char *printername;
689 union spoolss_PrinterInfo info;
690 struct dcerpc_binding_handle *b = cli->binding_handle;
692 if (argc == 1 || argc > 3) {
693 printf("Usage: %s <printername> [level]\n", argv[0]);
697 /* Open a printer handle */
699 level = atoi(argv[2]);
702 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
704 /* get a printer handle */
706 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
708 SEC_FLAG_MAXIMUM_ALLOWED,
710 if (!W_ERROR_IS_OK(result)) {
714 /* Get printer info */
716 result = rpccli_spoolss_getprinter(cli, mem_ctx,
721 if (!W_ERROR_IS_OK(result)) {
725 /* Display printer info */
728 display_print_info0(&info.info0);
731 display_print_info1(&info.info1);
734 display_print_info2(&info.info2);
737 display_print_info3(&info.info3);
740 display_print_info4(&info.info4);
743 display_print_info5(&info.info5);
746 display_print_info6(&info.info6);
749 display_print_info7(&info.info7);
752 printf("unknown info level %d\n", level);
756 if (is_valid_policy_hnd(&pol)) {
758 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
764 /****************************************************************************
765 ****************************************************************************/
767 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
769 const char *text = NULL;
773 if (blob.length >= sizeof(uint32_t)) {
774 printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
776 printf("%s: REG_DWORD: <invalid>\n", name);
780 pull_reg_sz(talloc_tos(), &blob, &text);
781 printf("%s: REG_SZ: %s\n", name, text ? text : "");
784 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
786 printf("%s: REG_BINARY:", name);
788 for (i=0; i<len; i++) {
789 if (hex[i] == '\0') {
805 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
806 d_printf("pull_reg_multi_sz failed\n");
810 printf("%s: REG_MULTI_SZ: \n", name);
811 for (i=0; values[i] != NULL; i++) {
812 d_printf("%s\n", values[i]);
818 printf("%s: unknown type %d\n", name, type);
823 /****************************************************************************
824 ****************************************************************************/
826 static void display_printer_data(const char *v,
827 enum winreg_Type type,
832 union spoolss_PrinterData r;
833 DATA_BLOB blob = data_blob_const(data, length);
835 enum ndr_err_code ndr_err;
837 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
838 if (!W_ERROR_IS_OK(result)) {
844 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
847 printf("%s: REG_SZ: %s\n", v, r.string);
850 char *hex = hex_encode_talloc(NULL,
851 r.binary.data, r.binary.length);
853 printf("%s: REG_BINARY:", v);
855 for (i=0; i<len; i++) {
856 if (hex[i] == '\0') {
868 if (strequal(v, "OsVersion")) {
869 struct spoolss_OSVersion os;
870 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
871 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
872 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
874 printf("OsMajor: %u\n", os.major);
875 printf("OsMinor: %u\n", os.minor);
876 printf("OsBuild: %u\n", os.build);
877 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
880 if (strequal(v, "OsVersionEx")) {
881 struct spoolss_OSVersionEx os;
882 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
883 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
884 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
885 printf("OsMajor: %u\n", os.major);
886 printf("OsMinor: %u\n", os.minor);
887 printf("OsBuild: %u\n", os.build);
888 printf("ServicePackMajor: %u\n", os.service_pack_major);
889 printf("ServicePackMinor: %u\n", os.service_pack_minor);
890 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
896 printf("%s: REG_MULTI_SZ: ", v);
897 for (i=0; r.string_array[i] != NULL; i++) {
898 printf("%s ", r.string_array[i]);
903 printf("%s: unknown type 0x%02x:\n", v, type);
908 /****************************************************************************
909 ****************************************************************************/
911 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
913 int argc, const char **argv)
915 struct policy_handle pol;
918 const char *valuename;
919 enum winreg_Type type;
922 struct dcerpc_binding_handle *b = cli->binding_handle;
925 printf("Usage: %s <printername> <valuename>\n", argv[0]);
926 printf("<printername> of . queries print server\n");
931 /* Open a printer handle */
933 if (strncmp(argv[1], ".", sizeof(".")) == 0)
934 fstrcpy(printername, cli->srv_name_slash);
936 slprintf(printername, sizeof(printername)-1, "%s\\%s",
937 cli->srv_name_slash, argv[1]);
939 /* get a printer handle */
941 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
943 SEC_FLAG_MAXIMUM_ALLOWED,
945 if (!W_ERROR_IS_OK(result))
948 /* Get printer info */
950 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
957 if (!W_ERROR_IS_OK(result))
960 /* Display printer data */
962 display_printer_data(valuename, type, data, needed);
965 if (is_valid_policy_hnd(&pol)) {
967 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
973 /****************************************************************************
974 ****************************************************************************/
976 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
978 int argc, const char **argv)
980 struct policy_handle pol;
984 const char *valuename, *keyname;
986 enum winreg_Type type;
987 uint8_t *data = NULL;
988 uint32_t offered = 0;
990 struct dcerpc_binding_handle *b = cli->binding_handle;
993 printf("Usage: %s <printername> <keyname> <valuename>\n",
995 printf("<printername> of . queries print server\n");
1001 /* Open a printer handle */
1003 if (strncmp(argv[1], ".", sizeof(".")) == 0)
1004 fstrcpy(printername, cli->srv_name_slash);
1006 slprintf(printername, sizeof(printername)-1, "%s\\%s",
1007 cli->srv_name_slash, argv[1]);
1009 /* get a printer handle */
1011 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1013 SEC_FLAG_MAXIMUM_ALLOWED,
1015 if (!W_ERROR_IS_OK(result))
1018 /* Get printer info */
1020 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1025 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1034 if (!NT_STATUS_IS_OK(status)) {
1035 result = ntstatus_to_werror(status);
1038 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1040 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1044 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1055 if (!NT_STATUS_IS_OK(status)) {
1056 result = ntstatus_to_werror(status);
1060 if (!W_ERROR_IS_OK(result))
1063 /* Display printer data */
1065 display_printer_data(valuename, type, data, needed);
1069 if (is_valid_policy_hnd(&pol)) {
1071 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1077 /****************************************************************************
1078 ****************************************************************************/
1080 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1086 printf("Printer Driver Info 1:\n");
1087 printf("\tDriver Name: [%s]\n", r->driver_name);
1091 /****************************************************************************
1092 ****************************************************************************/
1094 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1100 printf("Printer Driver Info 2:\n");
1101 printf("\tVersion: [%x]\n", r->version);
1102 printf("\tDriver Name: [%s]\n", r->driver_name);
1103 printf("\tArchitecture: [%s]\n", r->architecture);
1104 printf("\tDriver Path: [%s]\n", r->driver_path);
1105 printf("\tDatafile: [%s]\n", r->data_file);
1106 printf("\tConfigfile: [%s]\n", r->config_file);
1110 /****************************************************************************
1111 ****************************************************************************/
1113 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1121 printf("Printer Driver Info 3:\n");
1122 printf("\tVersion: [%x]\n", r->version);
1123 printf("\tDriver Name: [%s]\n", r->driver_name);
1124 printf("\tArchitecture: [%s]\n", r->architecture);
1125 printf("\tDriver Path: [%s]\n", r->driver_path);
1126 printf("\tDatafile: [%s]\n", r->data_file);
1127 printf("\tConfigfile: [%s]\n", r->config_file);
1128 printf("\tHelpfile: [%s]\n", r->help_file);
1130 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1131 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1134 printf("\tMonitorname: [%s]\n", r->monitor_name);
1135 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1139 /****************************************************************************
1140 ****************************************************************************/
1142 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1150 printf("Printer Driver Info 4:\n");
1151 printf("\tVersion: [%x]\n", r->version);
1152 printf("\tDriver Name: [%s]\n", r->driver_name);
1153 printf("\tArchitecture: [%s]\n", r->architecture);
1154 printf("\tDriver Path: [%s]\n", r->driver_path);
1155 printf("\tDatafile: [%s]\n", r->data_file);
1156 printf("\tConfigfile: [%s]\n", r->config_file);
1157 printf("\tHelpfile: [%s]\n", r->help_file);
1159 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1160 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1163 printf("\tMonitorname: [%s]\n", r->monitor_name);
1164 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1166 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1167 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1172 /****************************************************************************
1173 ****************************************************************************/
1175 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1181 printf("Printer Driver Info 5:\n");
1182 printf("\tVersion: [%x]\n", r->version);
1183 printf("\tDriver Name: [%s]\n", r->driver_name);
1184 printf("\tArchitecture: [%s]\n", r->architecture);
1185 printf("\tDriver Path: [%s]\n", r->driver_path);
1186 printf("\tDatafile: [%s]\n", r->data_file);
1187 printf("\tConfigfile: [%s]\n", r->config_file);
1188 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1189 printf("\tConfig Version: [0x%x]\n", r->config_version);
1190 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1194 /****************************************************************************
1195 ****************************************************************************/
1197 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1205 printf("Printer Driver Info 6:\n");
1206 printf("\tVersion: [%x]\n", r->version);
1207 printf("\tDriver Name: [%s]\n", r->driver_name);
1208 printf("\tArchitecture: [%s]\n", r->architecture);
1209 printf("\tDriver Path: [%s]\n", r->driver_path);
1210 printf("\tDatafile: [%s]\n", r->data_file);
1211 printf("\tConfigfile: [%s]\n", r->config_file);
1212 printf("\tHelpfile: [%s]\n", r->help_file);
1214 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1215 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1218 printf("\tMonitorname: [%s]\n", r->monitor_name);
1219 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1221 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1222 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1225 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1226 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1227 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1228 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1229 printf("\tHardware ID: [%s]\n", r->hardware_id);
1230 printf("\tProvider: [%s]\n", r->provider);
1235 /****************************************************************************
1236 ****************************************************************************/
1238 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1246 printf("Printer Driver Info 8:\n");
1247 printf("\tVersion: [%x]\n", r->version);
1248 printf("\tDriver Name: [%s]\n", r->driver_name);
1249 printf("\tArchitecture: [%s]\n", r->architecture);
1250 printf("\tDriver Path: [%s]\n", r->driver_path);
1251 printf("\tDatafile: [%s]\n", r->data_file);
1252 printf("\tConfigfile: [%s]\n", r->config_file);
1253 printf("\tHelpfile: [%s]\n", r->help_file);
1254 printf("\tMonitorname: [%s]\n", r->monitor_name);
1255 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1257 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1258 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1261 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1262 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1265 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1266 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1267 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1268 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1269 printf("\tHardware ID: [%s]\n", r->hardware_id);
1270 printf("\tProvider: [%s]\n", r->provider);
1271 printf("\tPrint Processor: [%s]\n", r->print_processor);
1272 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1273 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1274 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1276 printf("\tInf Path: [%s]\n", r->inf_path);
1277 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1278 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1279 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1281 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1282 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1283 (long long unsigned int)r->min_inbox_driver_ver_version);
1288 /****************************************************************************
1289 ****************************************************************************/
1291 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1292 TALLOC_CTX *mem_ctx,
1293 int argc, const char **argv)
1295 struct policy_handle pol;
1298 const char *printername;
1300 bool success = false;
1301 union spoolss_DriverInfo info;
1302 uint32_t server_major_version;
1303 uint32_t server_minor_version;
1304 struct dcerpc_binding_handle *b = cli->binding_handle;
1306 if ((argc == 1) || (argc > 3)) {
1307 printf("Usage: %s <printername> [level]\n", argv[0]);
1311 /* get the arguments need to open the printer handle */
1313 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1316 level = atoi(argv[2]);
1319 /* Open a printer handle */
1321 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1325 if (!W_ERROR_IS_OK(werror)) {
1326 printf("Error opening printer handle for %s!\n", printername);
1330 /* loop through and print driver info level for each architecture */
1332 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1334 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1336 archi_table[i].long_archi,
1339 archi_table[i].version,
1342 &server_major_version,
1343 &server_minor_version);
1344 if (!W_ERROR_IS_OK(werror)) {
1348 /* need at least one success */
1352 printf("\n[%s]\n", archi_table[i].long_archi);
1356 display_print_driver1(&info.info1);
1359 display_print_driver2(&info.info2);
1362 display_print_driver3(&info.info3);
1365 display_print_driver4(&info.info4);
1368 display_print_driver5(&info.info5);
1371 display_print_driver6(&info.info6);
1374 display_print_driver8(&info.info8);
1377 printf("unknown info level %d\n", level);
1384 if (is_valid_policy_hnd(&pol)) {
1386 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1396 /****************************************************************************
1397 ****************************************************************************/
1399 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1400 TALLOC_CTX *mem_ctx,
1401 const char *architecture,
1406 union spoolss_DriverInfo *info = NULL;
1409 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1410 cli->srv_name_slash,
1417 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1418 printf("Server does not support environment [%s]\n",
1427 if (!W_ERROR_IS_OK(werror)) {
1428 printf("Error getting driver for environment [%s] - %s\n",
1429 architecture, win_errstr(werror));
1433 printf("\n[%s]\n", architecture);
1437 for (j=0; j < count; j++) {
1438 display_print_driver1(&info[j].info1);
1442 for (j=0; j < count; j++) {
1443 display_print_driver2(&info[j].info2);
1447 for (j=0; j < count; j++) {
1448 display_print_driver3(&info[j].info3);
1452 for (j=0; j < count; j++) {
1453 display_print_driver4(&info[j].info4);
1457 for (j=0; j < count; j++) {
1458 display_print_driver5(&info[j].info5);
1462 for (j=0; j < count; j++) {
1463 display_print_driver6(&info[j].info6);
1467 for (j=0; j < count; j++) {
1468 display_print_driver8(&info[j].info8);
1472 printf("unknown info level %d\n", level);
1473 return WERR_INVALID_LEVEL;
1479 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1480 TALLOC_CTX *mem_ctx,
1481 int argc, const char **argv)
1483 WERROR werror = WERR_OK;
1486 const char *architecture = NULL;
1489 printf("Usage: enumdrivers [level] [architecture]\n");
1494 level = atoi(argv[1]);
1498 architecture = argv[2];
1502 return enum_driver_by_architecture(cli, mem_ctx,
1507 /* loop through and print driver info level for each architecture */
1508 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1509 /* check to see if we already asked for this architecture string */
1511 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1515 werror = enum_driver_by_architecture(cli, mem_ctx,
1516 archi_table[i].long_archi,
1518 if (!W_ERROR_IS_OK(werror)) {
1526 /****************************************************************************
1527 ****************************************************************************/
1529 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1531 printf("\tDirectory Name:[%s]\n", r->directory_name);
1534 /****************************************************************************
1535 ****************************************************************************/
1537 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1538 TALLOC_CTX *mem_ctx,
1539 int argc, const char **argv)
1543 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1546 union spoolss_DriverDirectoryInfo info;
1548 struct dcerpc_binding_handle *b = cli->binding_handle;
1551 printf("Usage: %s [environment]\n", argv[0]);
1555 /* Get the arguments need to open the printer handle */
1561 /* Get the directory. Only use Info level 1 */
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);
1575 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1577 buffer = data_blob_talloc_zero(mem_ctx, needed);
1579 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1580 cli->srv_name_slash,
1588 if (!NT_STATUS_IS_OK(status)) {
1589 return ntstatus_to_werror(status);
1593 if (W_ERROR_IS_OK(result)) {
1594 display_printdriverdir_1(&info.info1);
1600 /****************************************************************************
1601 ****************************************************************************/
1603 static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1604 TALLOC_CTX *mem_ctx,
1605 int argc, const char **argv)
1609 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1612 struct dcerpc_binding_handle *b = cli->binding_handle;
1613 const char *package_id = "";
1614 const char *cab = NULL;
1617 printf("Usage: %s [environment] [package_id]\n", argv[0]);
1621 /* Get the arguments need to open the printer handle */
1628 package_id = argv[2];
1632 cab = talloc_array(mem_ctx, char, offered);
1633 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1634 cli->srv_name_slash,
1642 if (!NT_STATUS_IS_OK(status)) {
1643 return ntstatus_to_werror(status);
1646 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1648 cab = talloc_zero_array(mem_ctx, char, offered);
1650 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1651 cli->srv_name_slash,
1659 if (!NT_STATUS_IS_OK(status)) {
1660 return ntstatus_to_werror(status);
1664 return W_ERROR(WIN32_FROM_HRESULT(hresult));
1668 /****************************************************************************
1669 ****************************************************************************/
1671 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1672 struct spoolss_AddDriverInfo3 *info,
1678 for (i=0; archi_table[i].long_archi != NULL; i++)
1680 if (strcmp(arch, archi_table[i].short_archi) == 0)
1682 info->version = archi_table[i].version;
1683 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1688 if (archi_table[i].long_archi == NULL)
1690 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1697 /**************************************************************************
1698 wrapper for strtok to get the next parameter from a delimited list.
1699 Needed to handle the empty parameter string denoted by "NULL"
1700 *************************************************************************/
1702 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1703 const char *delim, const char **dest,
1708 /* get the next token */
1709 ptr = strtok_r(str, delim, saveptr);
1711 /* a string of 'NULL' is used to represent an empty
1712 parameter because two consecutive delimiters
1713 will not return an empty string. See man strtok(3)
1715 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1720 *dest = talloc_strdup(mem_ctx, ptr);
1726 /********************************************************************************
1727 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1728 string in the form of
1729 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1730 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1731 <Default Data Type>:<Comma Separated list of Files>
1732 *******************************************************************************/
1734 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1739 char *saveptr = NULL;
1740 struct spoolss_StringArray *deps;
1741 const char **file_array = NULL;
1744 /* fill in the UNISTR fields */
1745 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1746 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1747 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1748 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1749 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1750 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1751 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1753 /* <Comma Separated List of Dependent Files> */
1754 /* save the beginning of the string */
1755 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1758 /* begin to strip out each filename */
1759 str = strtok_r(str, ",", &saveptr);
1761 /* no dependent files, we are done */
1766 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1771 while (str != NULL) {
1773 ok = add_string_to_array(deps, str, &file_array, &count);
1777 str = strtok_r(NULL, ",", &saveptr);
1780 deps->string = talloc_zero_array(deps, const char *, count + 1);
1781 if (!deps->string) {
1785 for (i=0; i < count; i++) {
1786 deps->string[i] = file_array[i];
1789 r->dependent_files = deps;
1794 /****************************************************************************
1795 ****************************************************************************/
1797 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1798 TALLOC_CTX *mem_ctx,
1799 int argc, const char **argv)
1804 struct spoolss_AddDriverInfoCtr info_ctr;
1805 struct spoolss_AddDriverInfo3 info3;
1808 struct dcerpc_binding_handle *b = cli->binding_handle;
1810 /* parse the command arguments */
1811 if (argc != 3 && argc != 4)
1813 printf ("Usage: %s <Environment> \\\n", argv[0]);
1814 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1815 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1816 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1817 printf ("\t[version]\n");
1822 /* Fill in the spoolss_AddDriverInfo3 struct */
1825 arch = cmd_spoolss_get_short_archi(argv[1]);
1827 printf ("Error Unknown architecture [%s]\n", argv[1]);
1828 return WERR_INVALID_PARAMETER;
1831 set_drv_info_3_env(mem_ctx, &info3, arch);
1833 driver_args = talloc_strdup( mem_ctx, argv[2] );
1834 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1836 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1837 return WERR_INVALID_PARAMETER;
1840 /* if printer driver version specified, override the default version
1841 * used by the architecture. This allows installation of Windows
1842 * 2000 (version 3) printer drivers. */
1845 info3.version = atoi(argv[3]);
1849 info_ctr.level = level;
1850 info_ctr.info.info3 = &info3;
1852 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1853 cli->srv_name_slash,
1856 if (!NT_STATUS_IS_OK(status)) {
1857 return ntstatus_to_werror(status);
1859 if (W_ERROR_IS_OK(result)) {
1860 printf ("Printer Driver %s successfully installed.\n",
1868 /****************************************************************************
1869 ****************************************************************************/
1871 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1872 TALLOC_CTX *mem_ctx,
1873 int argc, const char **argv)
1876 struct spoolss_SetPrinterInfoCtr info_ctr;
1877 struct spoolss_SetPrinterInfo2 info2;
1879 /* parse the command arguments */
1882 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1886 /* Fill in the DRIVER_INFO_2 struct */
1889 info2.printername = argv[1];
1890 info2.drivername = argv[3];
1891 info2.sharename = argv[2];
1892 info2.portname = argv[4];
1893 info2.comment = "Created by rpcclient";
1894 info2.printprocessor = "winprint";
1895 info2.datatype = "RAW";
1896 info2.devmode_ptr = 0;
1897 info2.secdesc_ptr = 0;
1898 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1900 info2.defaultpriority = 0;
1901 info2.starttime = 0;
1902 info2.untiltime = 0;
1904 /* These three fields must not be used by AddPrinter()
1905 as defined in the MS Platform SDK documentation..
1909 info2.averageppm = 0;
1913 info_ctr.info.info2 = &info2;
1915 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1917 if (W_ERROR_IS_OK(result))
1918 printf ("Printer %s successfully installed.\n", argv[1]);
1923 /****************************************************************************
1924 ****************************************************************************/
1926 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1927 TALLOC_CTX *mem_ctx,
1928 int argc, const char **argv)
1930 struct policy_handle pol;
1934 const char *printername;
1935 union spoolss_PrinterInfo info;
1936 struct spoolss_SetPrinterInfoCtr info_ctr;
1937 struct spoolss_SetPrinterInfo2 info2;
1938 struct spoolss_DevmodeContainer devmode_ctr;
1939 struct sec_desc_buf secdesc_ctr;
1940 struct dcerpc_binding_handle *b = cli->binding_handle;
1942 ZERO_STRUCT(devmode_ctr);
1943 ZERO_STRUCT(secdesc_ctr);
1945 /* parse the command arguments */
1948 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1952 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1954 /* Get a printer handle */
1956 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1960 if (!W_ERROR_IS_OK(result))
1963 /* Get printer info */
1965 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1970 if (!W_ERROR_IS_OK(result)) {
1971 printf ("Unable to retrieve printer information!\n");
1975 /* Set the printer driver */
1977 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1978 info2.drivername = argv[2];
1981 info_ctr.info.info2 = &info2;
1983 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1990 if (!NT_STATUS_IS_OK(status)) {
1991 result = ntstatus_to_werror(status);
1994 if (!W_ERROR_IS_OK(result)) {
1995 printf("SetPrinter call failed!\n");
1999 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
2004 if (is_valid_policy_hnd(&pol)) {
2006 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2013 /****************************************************************************
2014 ****************************************************************************/
2016 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2017 TALLOC_CTX *mem_ctx,
2018 int argc, const char **argv)
2020 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2022 struct dcerpc_binding_handle *b = cli->binding_handle;
2027 const char *arch = NULL;
2028 uint32_t delete_flags = 0;
2030 /* parse the command arguments */
2031 if (argc < 2 || argc > 5) {
2032 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2039 vers = atoi(argv[3]);
2040 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2043 delete_flags = atoi(argv[4]);
2045 /* delete the driver for all architectures */
2046 for (i=0; archi_table[i].long_archi; i++) {
2048 if (arch && !strequal(archi_table[i].long_archi, arch))
2051 if (vers >= 0 && archi_table[i].version != vers)
2054 /* make the call to remove the driver */
2055 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2056 cli->srv_name_slash,
2057 archi_table[i].long_archi,
2060 archi_table[i].version,
2062 if (!NT_STATUS_IS_OK(status)) {
2063 return ntstatus_to_werror(status);
2065 if ( !W_ERROR_IS_OK(result) )
2067 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2068 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2069 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2074 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2075 archi_table[i].long_archi, archi_table[i].version);
2084 /****************************************************************************
2085 ****************************************************************************/
2087 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2088 TALLOC_CTX *mem_ctx,
2089 int argc, const char **argv)
2091 WERROR result = WERR_OK;
2094 struct dcerpc_binding_handle *b = cli->binding_handle;
2096 /* parse the command arguments */
2098 printf ("Usage: %s <driver>\n", argv[0]);
2102 /* delete the driver for all architectures */
2103 for (i=0; archi_table[i].long_archi; i++) {
2106 /* make the call to remove the driver */
2107 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2108 cli->srv_name_slash,
2109 archi_table[i].long_archi,
2112 if (!NT_STATUS_IS_OK(status)) {
2113 result = ntstatus_to_werror(status);
2116 if ( !W_ERROR_IS_OK(result) ) {
2117 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2118 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2119 argv[1], archi_table[i].long_archi,
2120 win_errstr(result));
2123 printf ("Driver %s removed for arch [%s].\n", argv[1],
2124 archi_table[i].long_archi);
2131 /****************************************************************************
2132 ****************************************************************************/
2134 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2135 TALLOC_CTX *mem_ctx,
2136 int argc, const char **argv)
2140 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2143 union spoolss_PrintProcessorDirectoryInfo info;
2145 struct dcerpc_binding_handle *b = cli->binding_handle;
2147 /* parse the command arguments */
2149 printf ("Usage: %s [environment]\n", argv[0]);
2154 environment = argv[1];
2157 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2158 cli->srv_name_slash,
2166 if (!NT_STATUS_IS_OK(status)) {
2167 return ntstatus_to_werror(status);
2169 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2171 buffer = data_blob_talloc_zero(mem_ctx, needed);
2173 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2174 cli->srv_name_slash,
2182 if (!NT_STATUS_IS_OK(status)) {
2183 return ntstatus_to_werror(status);
2187 if (W_ERROR_IS_OK(result)) {
2188 printf("%s\n", info.info1.directory_name);
2194 /****************************************************************************
2195 ****************************************************************************/
2197 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2198 int argc, const char **argv)
2200 struct policy_handle handle;
2203 const char *printername;
2204 struct spoolss_AddFormInfoCtr info_ctr;
2205 struct spoolss_AddFormInfo1 info1;
2206 struct spoolss_AddFormInfo2 info2;
2208 struct dcerpc_binding_handle *b = cli->binding_handle;
2210 /* Parse the command arguments */
2212 if (argc < 3 || argc > 5) {
2213 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2217 /* Get a printer handle */
2219 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2221 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2225 if (!W_ERROR_IS_OK(werror))
2228 /* Dummy up some values for the form data */
2231 level = atoi(argv[3]);
2236 info1.flags = SPOOLSS_FORM_USER;
2237 info1.form_name = argv[2];
2238 info1.size.width = 100;
2239 info1.size.height = 100;
2240 info1.area.left = 0;
2241 info1.area.top = 10;
2242 info1.area.right = 20;
2243 info1.area.bottom = 30;
2246 info_ctr.info.info1 = &info1;
2250 info2.flags = SPOOLSS_FORM_USER;
2251 info2.form_name = argv[2];
2252 info2.size.width = 100;
2253 info2.size.height = 100;
2254 info2.area.left = 0;
2255 info2.area.top = 10;
2256 info2.area.right = 20;
2257 info2.area.bottom = 30;
2258 info2.keyword = argv[2];
2259 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2260 info2.mui_dll = NULL;
2261 info2.ressource_id = 0;
2262 info2.display_name = argv[2];
2266 info_ctr.info.info2 = &info2;
2270 werror = WERR_INVALID_PARAMETER;
2276 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2280 if (!NT_STATUS_IS_OK(status)) {
2281 werror = ntstatus_to_werror(status);
2285 if (is_valid_policy_hnd(&handle)) {
2287 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2293 /****************************************************************************
2294 ****************************************************************************/
2296 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2297 int argc, const char **argv)
2299 struct policy_handle handle;
2302 const char *printername;
2303 struct spoolss_AddFormInfoCtr info_ctr;
2304 struct spoolss_AddFormInfo1 info1;
2305 struct dcerpc_binding_handle *b = cli->binding_handle;
2307 /* Parse the command arguments */
2310 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2314 /* Get a printer handle */
2316 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2318 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2320 SEC_FLAG_MAXIMUM_ALLOWED,
2322 if (!W_ERROR_IS_OK(werror))
2325 /* Dummy up some values for the form data */
2327 info1.flags = SPOOLSS_FORM_PRINTER;
2328 info1.size.width = 100;
2329 info1.size.height = 100;
2330 info1.area.left = 0;
2331 info1.area.top = 1000;
2332 info1.area.right = 2000;
2333 info1.area.bottom = 3000;
2334 info1.form_name = argv[2];
2336 info_ctr.info.info1 = &info1;
2341 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2346 if (!NT_STATUS_IS_OK(status)) {
2347 werror = ntstatus_to_werror(status);
2351 if (is_valid_policy_hnd(&handle)) {
2353 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2359 /****************************************************************************
2360 ****************************************************************************/
2362 static const char *get_form_flag(int form_flag)
2364 switch (form_flag) {
2365 case SPOOLSS_FORM_USER:
2367 case SPOOLSS_FORM_BUILTIN:
2368 return "FORM_BUILTIN";
2369 case SPOOLSS_FORM_PRINTER:
2370 return "FORM_PRINTER";
2376 /****************************************************************************
2377 ****************************************************************************/
2379 static void display_form_info1(struct spoolss_FormInfo1 *r)
2382 "\tflag: %s (%d)\n" \
2383 "\twidth: %d, length: %d\n" \
2384 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2385 r->form_name, get_form_flag(r->flags), r->flags,
2386 r->size.width, r->size.height,
2387 r->area.left, r->area.right,
2388 r->area.top, r->area.bottom);
2391 /****************************************************************************
2392 ****************************************************************************/
2394 static void display_form_info2(struct spoolss_FormInfo2 *r)
2397 "\tflag: %s (%d)\n" \
2398 "\twidth: %d, length: %d\n" \
2399 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2400 r->form_name, get_form_flag(r->flags), r->flags,
2401 r->size.width, r->size.height,
2402 r->area.left, r->area.right,
2403 r->area.top, r->area.bottom);
2404 printf("\tkeyword: %s\n", r->keyword);
2405 printf("\tstring_type: 0x%08x\n", r->string_type);
2406 printf("\tmui_dll: %s\n", r->mui_dll);
2407 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2408 printf("\tdisplay_name: %s\n", r->display_name);
2409 printf("\tlang_id: %d\n", r->lang_id);
2413 /****************************************************************************
2414 ****************************************************************************/
2416 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2417 int argc, const char **argv)
2419 struct policy_handle handle;
2422 const char *printername;
2424 uint32_t offered = 0;
2425 union spoolss_FormInfo info;
2428 struct dcerpc_binding_handle *b = cli->binding_handle;
2430 /* Parse the command arguments */
2432 if (argc < 3 || argc > 5) {
2433 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2437 /* Get a printer handle */
2439 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2441 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2443 SEC_FLAG_MAXIMUM_ALLOWED,
2445 if (!W_ERROR_IS_OK(werror))
2449 level = atoi(argv[3]);
2454 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2463 if (!NT_STATUS_IS_OK(status)) {
2464 werror = ntstatus_to_werror(status);
2467 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2468 buffer = data_blob_talloc_zero(mem_ctx, needed);
2470 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2479 if (!NT_STATUS_IS_OK(status)) {
2480 werror = ntstatus_to_werror(status);
2485 if (!W_ERROR_IS_OK(werror)) {
2491 display_form_info1(&info.info1);
2494 display_form_info2(&info.info2);
2499 if (is_valid_policy_hnd(&handle)) {
2501 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2507 /****************************************************************************
2508 ****************************************************************************/
2510 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2511 TALLOC_CTX *mem_ctx, int argc,
2514 struct policy_handle handle;
2517 const char *printername;
2518 struct dcerpc_binding_handle *b = cli->binding_handle;
2520 /* Parse the command arguments */
2523 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2527 /* Get a printer handle */
2529 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2531 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2533 SEC_FLAG_MAXIMUM_ALLOWED,
2535 if (!W_ERROR_IS_OK(werror))
2538 /* Delete the form */
2540 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2544 if (!NT_STATUS_IS_OK(status)) {
2545 werror = ntstatus_to_werror(status);
2550 if (is_valid_policy_hnd(&handle)) {
2552 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2558 /****************************************************************************
2559 ****************************************************************************/
2561 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2562 TALLOC_CTX *mem_ctx, int argc,
2565 struct policy_handle handle;
2567 const char *printername;
2568 uint32_t num_forms, level = 1, i;
2569 union spoolss_FormInfo *forms;
2570 struct dcerpc_binding_handle *b = cli->binding_handle;
2572 /* Parse the command arguments */
2574 if (argc < 2 || argc > 4) {
2575 printf ("Usage: %s <printer> [level]\n", argv[0]);
2579 /* Get a printer handle */
2581 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2583 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2585 SEC_FLAG_MAXIMUM_ALLOWED,
2587 if (!W_ERROR_IS_OK(werror))
2591 level = atoi(argv[2]);
2594 /* Enumerate forms */
2596 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2603 if (!W_ERROR_IS_OK(werror))
2606 /* Display output */
2608 for (i = 0; i < num_forms; i++) {
2611 display_form_info1(&forms[i].info1);
2614 display_form_info2(&forms[i].info2);
2620 if (is_valid_policy_hnd(&handle)) {
2622 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2628 /****************************************************************************
2629 ****************************************************************************/
2631 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2632 TALLOC_CTX *mem_ctx,
2633 int argc, const char **argv)
2637 const char *printername;
2638 struct policy_handle pol = { 0, };
2639 union spoolss_PrinterInfo info;
2640 enum winreg_Type type;
2641 union spoolss_PrinterData data;
2643 struct dcerpc_binding_handle *b = cli->binding_handle;
2645 /* parse the command arguments */
2647 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2648 " <value> <data>\n",
2653 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2657 if (strequal(argv[2], "string")) {
2661 if (strequal(argv[2], "binary")) {
2665 if (strequal(argv[2], "dword")) {
2669 if (strequal(argv[2], "multistring")) {
2670 type = REG_MULTI_SZ;
2673 if (type == REG_NONE) {
2674 printf("Unknown data type: %s\n", argv[2]);
2675 result = WERR_INVALID_PARAMETER;
2679 /* get a printer handle */
2681 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2683 SEC_FLAG_MAXIMUM_ALLOWED,
2685 if (!W_ERROR_IS_OK(result)) {
2689 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2694 if (!W_ERROR_IS_OK(result)) {
2698 printf("%s\n", current_timestring(mem_ctx, true));
2699 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2701 /* Set the printer data */
2705 data.string = talloc_strdup(mem_ctx, argv[4]);
2706 W_ERROR_HAVE_NO_MEMORY(data.string);
2709 data.value = strtoul(argv[4], NULL, 10);
2712 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2714 case REG_MULTI_SZ: {
2717 const char **strings = NULL;
2721 for (i=4; i<argc; i++) {
2722 if (strcmp(argv[i], "NULL") == 0) {
2725 if (!add_string_to_array(mem_ctx, argv[i],
2728 result = WERR_NOT_ENOUGH_MEMORY;
2732 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2733 if (!data.string_array) {
2734 result = WERR_NOT_ENOUGH_MEMORY;
2737 for (i=0; i < num_strings; i++) {
2738 data.string_array[i] = strings[i];
2743 printf("Unknown data type: %s\n", argv[2]);
2744 result = WERR_INVALID_PARAMETER;
2748 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2749 if (!W_ERROR_IS_OK(result)) {
2753 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2755 argv[3], /* value_name */
2760 if (!NT_STATUS_IS_OK(status)) {
2761 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2762 result = ntstatus_to_werror(status);
2765 if (!W_ERROR_IS_OK(result)) {
2766 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2769 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2771 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2776 if (!W_ERROR_IS_OK(result)) {
2780 printf("%s\n", current_timestring(mem_ctx, true));
2781 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2785 if (is_valid_policy_hnd(&pol)) {
2787 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2793 /****************************************************************************
2794 ****************************************************************************/
2796 static void display_job_info1(struct spoolss_JobInfo1 *r)
2798 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2799 r->user_name, r->document_name, r->text_status, r->pages_printed,
2803 /****************************************************************************
2804 ****************************************************************************/
2806 static void display_job_info2(struct spoolss_JobInfo2 *r)
2808 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2809 r->position, r->job_id,
2810 r->user_name, r->document_name, r->text_status, r->pages_printed,
2811 r->total_pages, r->size);
2814 /****************************************************************************
2815 ****************************************************************************/
2817 static void display_job_info3(struct spoolss_JobInfo3 *r)
2819 printf("jobid[%d], next_jobid[%d]\n",
2820 r->job_id, r->next_job_id);
2823 /****************************************************************************
2824 ****************************************************************************/
2826 static void display_job_info4(struct spoolss_JobInfo4 *r)
2828 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2829 r->position, r->job_id,
2830 r->user_name, r->document_name, r->text_status, r->pages_printed,
2831 r->total_pages, r->size, r->size_high);
2834 /****************************************************************************
2835 ****************************************************************************/
2837 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2838 TALLOC_CTX *mem_ctx, int argc,
2842 uint32_t level = 1, count, i;
2843 const char *printername;
2844 struct policy_handle hnd;
2845 union spoolss_JobInfo *info;
2846 struct dcerpc_binding_handle *b = cli->binding_handle;
2848 if (argc < 2 || argc > 3) {
2849 printf("Usage: %s printername [level]\n", argv[0]);
2854 level = atoi(argv[2]);
2857 /* Open printer handle */
2859 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2861 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2863 SEC_FLAG_MAXIMUM_ALLOWED,
2865 if (!W_ERROR_IS_OK(result))
2868 /* Enumerate ports */
2870 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2878 if (!W_ERROR_IS_OK(result)) {
2882 for (i = 0; i < count; i++) {
2885 display_job_info1(&info[i].info1);
2888 display_job_info2(&info[i].info2);
2891 d_printf("unknown info level %d\n", level);
2897 if (is_valid_policy_hnd(&hnd)) {
2899 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2905 /****************************************************************************
2906 ****************************************************************************/
2908 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2909 TALLOC_CTX *mem_ctx, int argc,
2913 const char *printername;
2914 struct policy_handle hnd;
2917 union spoolss_JobInfo info;
2918 struct dcerpc_binding_handle *b = cli->binding_handle;
2920 if (argc < 3 || argc > 4) {
2921 printf("Usage: %s printername job_id [level]\n", argv[0]);
2925 job_id = atoi(argv[2]);
2928 level = atoi(argv[3]);
2931 /* Open printer handle */
2933 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2935 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2937 SEC_FLAG_MAXIMUM_ALLOWED,
2939 if (!W_ERROR_IS_OK(result)) {
2943 /* Enumerate ports */
2945 result = rpccli_spoolss_getjob(cli, mem_ctx,
2952 if (!W_ERROR_IS_OK(result)) {
2958 display_job_info1(&info.info1);
2961 display_job_info2(&info.info2);
2964 display_job_info3(&info.info3);
2967 display_job_info4(&info.info4);
2970 d_printf("unknown info level %d\n", level);
2975 if (is_valid_policy_hnd(&hnd)) {
2977 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2983 /****************************************************************************
2984 ****************************************************************************/
2988 enum spoolss_JobControl val;
2990 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2991 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2992 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2993 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2994 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2995 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2996 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2997 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2998 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3001 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3005 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3006 if (strequal(cmdvals[i].name, cmd)) {
3007 return cmdvals[i].val;
3010 return (enum spoolss_JobControl)atoi(cmd);
3013 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3014 TALLOC_CTX *mem_ctx, int argc,
3019 const char *printername;
3020 struct policy_handle hnd;
3022 enum spoolss_JobControl command;
3023 struct dcerpc_binding_handle *b = cli->binding_handle;
3026 printf("Usage: %s printername job_id command\n", argv[0]);
3027 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3028 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3032 job_id = atoi(argv[2]);
3033 command = parse_setjob_command(argv[3]);
3035 /* Open printer handle */
3037 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3039 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3041 SEC_FLAG_MAXIMUM_ALLOWED,
3043 if (!W_ERROR_IS_OK(result)) {
3049 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3055 if (!NT_STATUS_IS_OK(status)) {
3056 result = ntstatus_to_werror(status);
3059 if (!W_ERROR_IS_OK(result)) {
3064 if (is_valid_policy_hnd(&hnd)) {
3066 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3072 /****************************************************************************
3073 ****************************************************************************/
3075 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3076 TALLOC_CTX *mem_ctx, int argc,
3081 const char *printername;
3082 struct policy_handle hnd;
3083 uint32_t value_needed;
3084 enum winreg_Type type;
3085 uint32_t data_needed;
3086 struct dcerpc_binding_handle *b = cli->binding_handle;
3087 struct spoolss_EnumPrinterData r;
3090 printf("Usage: %s printername\n", argv[0]);
3094 /* Open printer handle */
3096 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3098 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3100 SEC_FLAG_MAXIMUM_ALLOWED,
3102 if (!W_ERROR_IS_OK(result)) {
3106 /* Enumerate data */
3109 r.in.enum_index = 0;
3110 r.in.value_offered = 0;
3111 r.in.data_offered = 0;
3112 r.out.value_name = NULL;
3113 r.out.value_needed = &value_needed;
3116 r.out.data_needed = &data_needed;
3118 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3119 if (!NT_STATUS_IS_OK(status)) {
3120 result = ntstatus_to_werror(status);
3124 if (!W_ERROR_IS_OK(r.out.result)) {
3125 result = r.out.result;
3129 r.in.data_offered = *r.out.data_needed;
3130 r.in.value_offered = *r.out.value_needed;
3131 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3132 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3136 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3137 if (!NT_STATUS_IS_OK(status)) {
3138 result = ntstatus_to_werror(status);
3142 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3149 display_reg_value(r.out.value_name, *r.out.type,
3150 data_blob_const(r.out.data, r.in.data_offered));
3152 } while (W_ERROR_IS_OK(r.out.result));
3155 if (is_valid_policy_hnd(&hnd)) {
3157 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3163 /****************************************************************************
3164 ****************************************************************************/
3166 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3167 TALLOC_CTX *mem_ctx, int argc,
3172 const char *printername;
3173 struct policy_handle hnd;
3175 struct spoolss_PrinterEnumValues *info;
3176 struct dcerpc_binding_handle *b = cli->binding_handle;
3179 printf("Usage: %s printername <keyname>\n", argv[0]);
3183 /* Open printer handle */
3185 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3187 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3189 SEC_FLAG_MAXIMUM_ALLOWED,
3191 if (!W_ERROR_IS_OK(result)) {
3195 /* Enumerate subkeys */
3197 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3203 if (!W_ERROR_IS_OK(result)) {
3207 for (i=0; i < count; i++) {
3208 display_printer_data(info[i].value_name,
3211 info[i].data->length);
3215 if (is_valid_policy_hnd(&hnd)) {
3217 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3223 /****************************************************************************
3224 ****************************************************************************/
3226 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3227 TALLOC_CTX *mem_ctx, int argc,
3231 const char *printername;
3232 const char *keyname = NULL;
3233 struct policy_handle hnd;
3234 const char **key_buffer = NULL;
3236 uint32_t offered = 0;
3237 struct dcerpc_binding_handle *b = cli->binding_handle;
3239 if (argc < 2 || argc > 4) {
3240 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3251 offered = atoi(argv[3]);
3254 /* Open printer handle */
3256 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3258 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3260 SEC_FLAG_MAXIMUM_ALLOWED,
3262 if (!W_ERROR_IS_OK(result)) {
3266 /* Enumerate subkeys */
3268 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3274 if (!W_ERROR_IS_OK(result)) {
3278 for (i=0; key_buffer && key_buffer[i]; i++) {
3279 printf("%s\n", key_buffer[i]);
3284 if (is_valid_policy_hnd(&hnd)) {
3286 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3292 /****************************************************************************
3293 ****************************************************************************/
3295 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3296 TALLOC_CTX *mem_ctx, int argc,
3299 const char *printername;
3300 const char *clientname;
3301 struct policy_handle hnd = { 0, };
3304 struct spoolss_NotifyOption option;
3305 struct dcerpc_binding_handle *b = cli->binding_handle;
3308 printf("Usage: %s printername\n", argv[0]);
3315 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3317 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3319 SEC_FLAG_MAXIMUM_ALLOWED,
3321 if (!W_ERROR_IS_OK(result)) {
3322 printf("Error opening %s\n", argv[1]);
3326 /* Create spool options */
3331 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3332 if (option.types == NULL) {
3333 result = WERR_NOT_ENOUGH_MEMORY;
3337 option.types[0].type = PRINTER_NOTIFY_TYPE;
3338 option.types[0].count = 1;
3339 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3340 if (option.types[0].fields == NULL) {
3341 result = WERR_NOT_ENOUGH_MEMORY;
3344 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3346 option.types[1].type = JOB_NOTIFY_TYPE;
3347 option.types[1].count = 1;
3348 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3349 if (option.types[1].fields == NULL) {
3350 result = WERR_NOT_ENOUGH_MEMORY;
3353 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3355 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3357 result = WERR_NOT_ENOUGH_MEMORY;
3363 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3371 if (!NT_STATUS_IS_OK(status)) {
3372 result = ntstatus_to_werror(status);
3375 if (!W_ERROR_IS_OK(result)) {
3376 printf("Error rffpcnex %s\n", argv[1]);
3381 if (is_valid_policy_hnd(&hnd)) {
3383 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3389 /****************************************************************************
3390 ****************************************************************************/
3392 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3393 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3395 union spoolss_PrinterInfo info1, info2;
3397 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3399 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3400 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3405 if ( !W_ERROR_IS_OK(werror) ) {
3406 printf("failed (%s)\n", win_errstr(werror));
3407 talloc_destroy(mem_ctx);
3412 printf("Retrieving printer properties for %s...", cli2->desthost);
3413 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3418 if ( !W_ERROR_IS_OK(werror) ) {
3419 printf("failed (%s)\n", win_errstr(werror));
3420 talloc_destroy(mem_ctx);
3425 talloc_destroy(mem_ctx);
3430 /****************************************************************************
3431 ****************************************************************************/
3433 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3434 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3436 union spoolss_PrinterInfo info1, info2;
3438 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3439 struct security_descriptor *sd1, *sd2;
3443 printf("Retrieving printer security for %s...", cli1->desthost);
3444 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3449 if ( !W_ERROR_IS_OK(werror) ) {
3450 printf("failed (%s)\n", win_errstr(werror));
3456 printf("Retrieving printer security for %s...", cli2->desthost);
3457 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3462 if ( !W_ERROR_IS_OK(werror) ) {
3463 printf("failed (%s)\n", win_errstr(werror));
3472 sd1 = info1.info3.secdesc;
3473 sd2 = info2.info3.secdesc;
3475 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3476 printf("NULL secdesc!\n");
3481 if (!security_descriptor_equal( sd1, sd2 ) ) {
3482 printf("Security Descriptors *not* equal!\n");
3487 printf("Security descriptors match\n");
3490 talloc_destroy(mem_ctx);
3495 /****************************************************************************
3496 ****************************************************************************/
3498 extern struct user_auth_info *rpcclient_auth_info;
3500 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3501 TALLOC_CTX *mem_ctx, int argc,
3504 const char *printername;
3505 char *printername_path = NULL;
3506 struct cli_state *cli_server2 = NULL;
3507 struct rpc_pipe_client *cli2 = NULL;
3508 struct policy_handle hPrinter1, hPrinter2;
3513 printf("Usage: %s <printer> <server>\n", argv[0]);
3517 printername = argv[1];
3519 /* first get the connection to the remote server */
3521 nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
3524 get_cmdline_auth_info_username(rpcclient_auth_info),
3526 get_cmdline_auth_info_password(rpcclient_auth_info),
3527 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3528 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3530 if ( !NT_STATUS_IS_OK(nt_status) )
3531 return WERR_GEN_FAILURE;
3533 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3535 if (!NT_STATUS_IS_OK(nt_status)) {
3536 printf("failed to open spoolss pipe on server %s (%s)\n",
3537 argv[2], nt_errstr(nt_status));
3538 return WERR_GEN_FAILURE;
3541 /* now open up both printers */
3543 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3545 printf("Opening %s...", printername_path);
3547 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3551 if ( !W_ERROR_IS_OK(werror) ) {
3552 printf("failed (%s)\n", win_errstr(werror));
3557 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3559 printf("Opening %s...", printername_path);
3560 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3564 if ( !W_ERROR_IS_OK(werror) ) {
3565 printf("failed (%s)\n", win_errstr(werror));
3570 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3571 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3573 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3580 printf("Closing printers...");
3583 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3584 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3588 /* close the second remote connection */
3590 cli_shutdown( cli_server2 );
3594 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3596 printf("print_processor_name: %s\n", r->print_processor_name);
3599 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3600 TALLOC_CTX *mem_ctx, int argc,
3604 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3605 uint32_t num_procs, level = 1, i;
3606 union spoolss_PrintProcessorInfo *procs;
3608 /* Parse the command arguments */
3610 if (argc < 1 || argc > 4) {
3611 printf ("Usage: %s [environment] [level]\n", argv[0]);
3616 environment = argv[1];
3620 level = atoi(argv[2]);
3623 /* Enumerate Print Processors */
3625 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3626 cli->srv_name_slash,
3632 if (!W_ERROR_IS_OK(werror))
3635 /* Display output */
3637 for (i = 0; i < num_procs; i++) {
3640 display_proc_info1(&procs[i].info1);
3649 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3651 printf("name_array: %s\n", r->name_array);
3654 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3655 TALLOC_CTX *mem_ctx, int argc,
3659 const char *print_processor_name = "winprint";
3660 uint32_t num_procs, level = 1, i;
3661 union spoolss_PrintProcDataTypesInfo *procs;
3663 /* Parse the command arguments */
3665 if (argc < 1 || argc > 4) {
3666 printf ("Usage: %s [environment] [level]\n", argv[0]);
3671 print_processor_name = argv[1];
3675 level = atoi(argv[2]);
3678 /* Enumerate Print Processor Data Types */
3680 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3681 cli->srv_name_slash,
3682 print_processor_name,
3687 if (!W_ERROR_IS_OK(werror))
3690 /* Display output */
3692 for (i = 0; i < num_procs; i++) {
3695 display_proc_data_types_info1(&procs[i].info1);
3704 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3706 printf("monitor_name: %s\n", r->monitor_name);
3709 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3711 printf("monitor_name: %s\n", r->monitor_name);
3712 printf("environment: %s\n", r->environment);
3713 printf("dll_name: %s\n", r->dll_name);
3716 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3717 TALLOC_CTX *mem_ctx, int argc,
3721 uint32_t count, level = 1, i;
3722 union spoolss_MonitorInfo *info;
3724 /* Parse the command arguments */
3727 printf("Usage: %s [level]\n", argv[0]);
3732 level = atoi(argv[1]);
3735 /* Enumerate Print Monitors */
3737 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3738 cli->srv_name_slash,
3743 if (!W_ERROR_IS_OK(werror)) {
3747 /* Display output */
3749 for (i = 0; i < count; i++) {
3752 display_monitor1(&info[i].info1);
3755 display_monitor2(&info[i].info2);
3764 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3765 TALLOC_CTX *mem_ctx, int argc,
3770 struct policy_handle handle, gdi_handle;
3771 const char *printername;
3772 struct spoolss_DevmodeContainer devmode_ctr;
3773 struct dcerpc_binding_handle *b = cli->binding_handle;
3775 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3777 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3779 SEC_FLAG_MAXIMUM_ALLOWED,
3781 if (!W_ERROR_IS_OK(result)) {
3785 ZERO_STRUCT(devmode_ctr);
3787 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3792 if (!NT_STATUS_IS_OK(status)) {
3793 result = ntstatus_to_werror(status);
3796 if (!W_ERROR_IS_OK(result)) {
3801 if (is_valid_policy_hnd(&gdi_handle)) {
3803 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3805 if (is_valid_policy_hnd(&handle)) {
3807 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3813 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3814 TALLOC_CTX *mem_ctx, int argc,
3819 struct policy_handle handle, gdi_handle;
3820 const char *printername;
3821 struct spoolss_DevmodeContainer devmode_ctr;
3822 struct dcerpc_binding_handle *b = cli->binding_handle;
3826 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3828 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3830 SEC_FLAG_MAXIMUM_ALLOWED,
3832 if (!W_ERROR_IS_OK(result)) {
3836 ZERO_STRUCT(devmode_ctr);
3838 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3843 if (!NT_STATUS_IS_OK(status)) {
3844 result = ntstatus_to_werror(status);
3847 if (!W_ERROR_IS_OK(result)) {
3851 in = data_blob_string_const("");
3852 out = data_blob_talloc_zero(mem_ctx, 4);
3854 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3862 if (!NT_STATUS_IS_OK(status)) {
3863 result = ntstatus_to_werror(status);
3866 if (!W_ERROR_IS_OK(result)) {
3870 count = IVAL(out.data, 0);
3872 out = data_blob_talloc_zero(mem_ctx,
3873 count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3875 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3883 if (!NT_STATUS_IS_OK(status)) {
3884 result = ntstatus_to_werror(status);
3887 if (!W_ERROR_IS_OK(result)) {
3892 enum ndr_err_code ndr_err;
3893 struct UNIVERSAL_FONT_ID_ctr r;
3895 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3896 (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3897 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3898 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3903 if (is_valid_policy_hnd(&gdi_handle)) {
3905 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3907 if (is_valid_policy_hnd(&handle)) {
3909 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3915 /* List of commands exported by this module */
3916 struct cmd_set spoolss_commands[] = {
3920 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss, NULL, "Add a print driver", "" },
3921 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss, NULL, "Add a printer", "" },
3922 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss, NULL, "Delete a printer driver", "" },
3923 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss, NULL, "Delete a printer driver with files", "" },
3924 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss, NULL, "Enumerate printer data", "" },
3925 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss, NULL, "Enumerate printer data for a key", "" },
3926 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss, NULL, "Enumerate printer keys", "" },
3927 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss, NULL, "Enumerate print jobs", "" },
3928 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss, NULL, "Get print job", "" },
3929 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss, NULL, "Set print job", "" },
3930 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss, NULL, "Enumerate printer ports", "" },
3931 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss, NULL, "Enumerate installed printer drivers", "" },
3932 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss, NULL, "Enumerate printers", "" },
3933 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss, NULL, "Get print driver data", "" },
3934 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss, NULL, "Get printer driver data with keyname", ""},
3935 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss, NULL, "Get print driver information", "" },
3936 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss, NULL, "Get print driver upload directory", "" },
3937 { "getdriverpackagepath", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverpackagepath, &ndr_table_spoolss, NULL, "Get print driver package download directory", "" },
3938 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss, NULL, "Get printer info", "" },
3939 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss, NULL, "Open printer handle", "" },
3940 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss, NULL, "Open printer handle", "" },
3941 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss, NULL, "Set printer driver", "" },
3942 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss, NULL, "Get print processor directory", "" },
3943 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss, NULL, "Add form", "" },
3944 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss, NULL, "Set form", "" },
3945 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss, NULL, "Get form", "" },
3946 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss, NULL, "Delete form", "" },
3947 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss, NULL, "Enumerate forms", "" },
3948 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss, NULL, "Set printer comment", "" },
3949 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss, NULL, "Set printername", "" },
3950 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss, NULL, "Set REG_SZ printer data", "" },
3951 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss, NULL, "Rffpcnex test", "" },
3952 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss, NULL, "Printer comparison test", "" },
3953 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss, NULL, "Enumerate Print Processors", "" },
3954 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3955 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss, NULL, "Enumerate Print Monitors", "" },
3956 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss, NULL, "Create Printer IC", "" },
3957 { "playgdiscriptonprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_play_gdi_script_on_printer_ic, &ndr_table_spoolss, NULL, "Create Printer IC", "" },