2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
31 #include "nt_printing.h"
32 #include "../libcli/security/display_sec.h"
33 #include "../libcli/security/security_descriptor.h"
34 #include "../libcli/registry/util_reg.h"
35 #include "libsmb/libsmb.h"
36 #include "popt_common_cmdline.h"
37 #include "lib/util/smb_strtox.h"
39 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
41 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
42 _cli->srv_name_slash, _arg); \
43 W_ERROR_HAVE_NO_MEMORY(_printername); \
46 /* The version int is used by getdrivers. Note that
47 all architecture strings that support mutliple
48 versions must be grouped together since enumdrivers
49 uses this property to prevent issuing multiple
50 enumdriver calls for the same arch */
53 static const struct print_architecture_table_node archi_table[]= {
55 {"Windows 4.0", "WIN40", 0 },
56 {"Windows NT x86", "W32X86", 2 },
57 {"Windows NT x86", "W32X86", 3 },
58 {"Windows NT R4000", "W32MIPS", 2 },
59 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
60 {"Windows NT PowerPC", "W32PPC", 2 },
61 {"Windows IA64", "IA64", 3 },
62 {"Windows x64", "x64", 3 },
69 * rpcclient module for SPOOLSS rpc pipe.
71 * This generally just parses and checks command lines, and then calls
72 * a cli_spoolss function.
75 /****************************************************************************
76 function to do the mapping between the long architecture name and
78 ****************************************************************************/
80 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
84 DEBUG(107,("Getting architecture dependent directory\n"));
87 } while ( (archi_table[i].long_archi!=NULL ) &&
88 strcasecmp_m(long_archi, archi_table[i].long_archi) );
90 if (archi_table[i].long_archi==NULL) {
91 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
95 /* this might be client code - but shouldn't this be an fstrcpy etc? */
98 DEBUGADD(108,("index: [%d]\n", i));
99 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
100 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
102 return archi_table[i].short_archi;
105 /****************************************************************************
106 ****************************************************************************/
108 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
110 int argc, const char **argv)
113 struct policy_handle hnd;
114 uint32_t access_mask = PRINTER_ALL_ACCESS;
115 struct dcerpc_binding_handle *b = cli->binding_handle;
118 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
123 sscanf(argv[2], "%x", &access_mask);
126 /* Open the printer handle */
128 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
132 if (W_ERROR_IS_OK(werror)) {
133 printf("Printer %s opened successfully\n", argv[1]);
134 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
136 if (!W_ERROR_IS_OK(werror)) {
137 printf("Error closing printer handle! (%s)\n",
138 get_dos_error_msg(werror));
145 /****************************************************************************
146 ****************************************************************************/
148 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
150 int argc, const char **argv)
153 struct policy_handle hnd;
154 uint32_t access_mask = PRINTER_ALL_ACCESS;
156 struct spoolss_DevmodeContainer devmode_ctr;
157 struct dcerpc_binding_handle *b = cli->binding_handle;
159 ZERO_STRUCT(devmode_ctr);
162 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
167 sscanf(argv[2], "%x", &access_mask);
170 /* Open the printer handle */
172 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
179 if (!NT_STATUS_IS_OK(status)) {
180 return ntstatus_to_werror(status);
182 if (W_ERROR_IS_OK(werror)) {
183 printf("Printer %s opened successfully\n", argv[1]);
184 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
186 if (!W_ERROR_IS_OK(werror)) {
187 printf("Error closing printer handle! (%s)\n",
188 get_dos_error_msg(werror));
195 /****************************************************************************
196 ****************************************************************************/
198 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
203 printf("\tprintername:[%s]\n", r->printername);
204 printf("\tservername:[%s]\n", r->servername);
205 printf("\tcjobs:[0x%x]\n", r->cjobs);
206 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
207 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
208 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
209 r->time.day, r->time.day_of_week);
210 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
211 r->time.second, r->time.millisecond);
213 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
214 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
216 printf("\tversion:[0x%x]\n", r->version);
217 printf("\tfree_build:[0x%x]\n", r->free_build);
218 printf("\tspooling:[0x%x]\n", r->spooling);
219 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
220 printf("\tsession_counter:[0x%x]\n", r->session_counter);
221 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
222 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
223 printf("\tjob_error:[0x%x]\n", r->job_error);
224 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
225 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
226 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
227 printf("\tchange_id:[0x%x]\n", r->change_id);
228 printf("\tlast_error: %s\n", win_errstr(r->last_error));
229 printf("\tstatus:[0x%x]\n", r->status);
230 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
231 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
232 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
233 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
234 printf("\tref_ic:[0x%x]\n", r->ref_ic);
235 printf("\treserved2:[0x%x]\n", r->reserved2);
236 printf("\treserved3:[0x%x]\n", r->reserved3);
241 /****************************************************************************
242 ****************************************************************************/
244 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
246 printf("\tflags:[0x%x]\n", r->flags);
247 printf("\tname:[%s]\n", r->name);
248 printf("\tdescription:[%s]\n", r->description);
249 printf("\tcomment:[%s]\n", r->comment);
254 /****************************************************************************
255 ****************************************************************************/
257 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
259 printf("\tservername:[%s]\n", r->servername);
260 printf("\tprintername:[%s]\n", r->printername);
261 printf("\tsharename:[%s]\n", r->sharename);
262 printf("\tportname:[%s]\n", r->portname);
263 printf("\tdrivername:[%s]\n", r->drivername);
264 printf("\tcomment:[%s]\n", r->comment);
265 printf("\tlocation:[%s]\n", r->location);
266 printf("\tsepfile:[%s]\n", r->sepfile);
267 printf("\tprintprocessor:[%s]\n", r->printprocessor);
268 printf("\tdatatype:[%s]\n", r->datatype);
269 printf("\tparameters:[%s]\n", r->parameters);
270 printf("\tattributes:[0x%x]\n", r->attributes);
271 printf("\tpriority:[0x%x]\n", r->priority);
272 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
273 printf("\tstarttime:[0x%x]\n", r->starttime);
274 printf("\tuntiltime:[0x%x]\n", r->untiltime);
275 printf("\tstatus:[0x%x]\n", r->status);
276 printf("\tcjobs:[0x%x]\n", r->cjobs);
277 printf("\taverageppm:[0x%x]\n", r->averageppm);
280 display_sec_desc(r->secdesc);
285 /****************************************************************************
286 ****************************************************************************/
288 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
290 display_sec_desc(r->secdesc);
295 /****************************************************************************
296 ****************************************************************************/
298 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
300 printf("\tservername:[%s]\n", r->servername);
301 printf("\tprintername:[%s]\n", r->printername);
302 printf("\tattributes:[0x%x]\n", r->attributes);
306 /****************************************************************************
307 ****************************************************************************/
309 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
311 printf("\tprintername:[%s]\n", r->printername);
312 printf("\tportname:[%s]\n", r->portname);
313 printf("\tattributes:[0x%x]\n", r->attributes);
314 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
315 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
319 /****************************************************************************
320 ****************************************************************************/
322 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
324 printf("\tstatus:[0x%x]\n", r->status);
328 /****************************************************************************
329 ****************************************************************************/
331 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
333 printf("\tguid:[%s]\n", r->guid);
334 printf("\taction:[0x%x]\n", r->action);
338 /****************************************************************************
339 ****************************************************************************/
341 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
343 int argc, const char **argv)
347 union spoolss_PrinterInfo *info;
350 uint32_t flags = PRINTER_ENUM_LOCAL;
353 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
358 level = atoi(argv[1]);
364 name = cli->srv_name_slash;
368 flags = atoi(argv[3]);
371 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
378 if (W_ERROR_IS_OK(result)) {
381 printf ("No printers returned.\n");
385 for (i = 0; i < count; i++) {
388 display_print_info0(&info[i].info0);
391 display_print_info1(&info[i].info1);
394 display_print_info2(&info[i].info2);
397 display_print_info3(&info[i].info3);
400 display_print_info4(&info[i].info4);
403 display_print_info5(&info[i].info5);
406 display_print_info6(&info[i].info6);
409 printf("unknown info level %d\n", level);
419 /****************************************************************************
420 ****************************************************************************/
422 static void display_port_info_1(struct spoolss_PortInfo1 *r)
424 printf("\tPort Name:\t[%s]\n", r->port_name);
427 /****************************************************************************
428 ****************************************************************************/
430 static void display_port_info_2(struct spoolss_PortInfo2 *r)
432 printf("\tPort Name:\t[%s]\n", r->port_name);
433 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
434 printf("\tDescription:\t[%s]\n", r->description);
435 printf("\tPort Type:\t" );
437 int comma = 0; /* hack */
439 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
443 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
444 printf( "%sWrite", comma ? ", " : "" );
447 /* These two have slightly different interpretations
448 on 95/98/ME but I'm disregarding that for now */
449 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
450 printf( "%sRedirected", comma ? ", " : "" );
453 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
454 printf( "%sNet-Attached", comma ? ", " : "" );
458 printf( "[Unset]\n" );
460 printf("\tReserved:\t[%d]\n", r->reserved);
464 /****************************************************************************
465 ****************************************************************************/
467 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
468 TALLOC_CTX *mem_ctx, int argc,
474 union spoolss_PortInfo *info;
477 printf("Usage: %s [level]\n", argv[0]);
482 level = atoi(argv[1]);
485 /* Enumerate ports */
487 result = rpccli_spoolss_enumports(cli, mem_ctx,
493 if (W_ERROR_IS_OK(result)) {
496 for (i = 0; i < count; i++) {
499 display_port_info_1(&info[i].info1);
502 display_port_info_2(&info[i].info2);
505 printf("unknown info level %d\n", level);
514 /****************************************************************************
515 ****************************************************************************/
517 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
519 int argc, const char **argv)
521 struct policy_handle pol;
524 uint32_t info_level = 2;
525 union spoolss_PrinterInfo info;
526 struct spoolss_SetPrinterInfoCtr info_ctr;
527 struct spoolss_SetPrinterInfo2 info2;
528 const char *printername, *comment = NULL;
529 struct spoolss_DevmodeContainer devmode_ctr;
530 struct sec_desc_buf secdesc_ctr;
531 struct dcerpc_binding_handle *b = cli->binding_handle;
533 if (argc == 1 || argc > 3) {
534 printf("Usage: %s printername comment\n", argv[0]);
539 /* Open a printer handle */
544 ZERO_STRUCT(devmode_ctr);
545 ZERO_STRUCT(secdesc_ctr);
547 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
549 /* get a printer handle */
550 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
554 if (!W_ERROR_IS_OK(result))
557 /* Get printer info */
558 result = rpccli_spoolss_getprinter(cli, mem_ctx,
563 if (!W_ERROR_IS_OK(result))
567 /* Modify the comment. */
568 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
569 info2.comment = comment;
572 info_ctr.info.info2 = &info2;
574 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
581 if (!NT_STATUS_IS_OK(status)) {
582 result = ntstatus_to_werror(status);
585 if (W_ERROR_IS_OK(result))
586 printf("Success in setting comment.\n");
589 if (is_valid_policy_hnd(&pol)) {
591 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
597 /****************************************************************************
598 ****************************************************************************/
600 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
602 int argc, const char **argv)
604 struct policy_handle pol;
607 uint32_t info_level = 2;
608 union spoolss_PrinterInfo info;
609 const char *printername,
610 *new_printername = NULL;
611 struct spoolss_SetPrinterInfoCtr info_ctr;
612 struct spoolss_SetPrinterInfo2 info2;
613 struct spoolss_DevmodeContainer devmode_ctr;
614 struct sec_desc_buf secdesc_ctr;
615 struct dcerpc_binding_handle *b = cli->binding_handle;
617 ZERO_STRUCT(devmode_ctr);
618 ZERO_STRUCT(secdesc_ctr);
620 if (argc == 1 || argc > 3) {
621 printf("Usage: %s printername new_printername\n", argv[0]);
626 /* Open a printer handle */
628 new_printername = argv[2];
631 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
633 /* get a printer handle */
634 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
638 if (!W_ERROR_IS_OK(result))
641 /* Get printer info */
642 result = rpccli_spoolss_getprinter(cli, mem_ctx,
647 if (!W_ERROR_IS_OK(result))
650 /* Modify the printername. */
651 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
652 info2.printername = new_printername;
655 info_ctr.info.info2 = &info2;
657 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
664 if (!NT_STATUS_IS_OK(status)) {
665 result = ntstatus_to_werror(status);
668 if (W_ERROR_IS_OK(result))
669 printf("Success in setting printername.\n");
672 if (is_valid_policy_hnd(&pol)) {
674 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
680 /****************************************************************************
681 ****************************************************************************/
683 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
685 int argc, const char **argv)
687 struct policy_handle pol;
690 const char *printername;
691 union spoolss_PrinterInfo info;
692 struct dcerpc_binding_handle *b = cli->binding_handle;
694 if (argc == 1 || argc > 3) {
695 printf("Usage: %s <printername> [level]\n", argv[0]);
699 /* Open a printer handle */
701 level = atoi(argv[2]);
704 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
706 /* get a printer handle */
708 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
710 SEC_FLAG_MAXIMUM_ALLOWED,
712 if (!W_ERROR_IS_OK(result)) {
716 /* Get printer info */
718 result = rpccli_spoolss_getprinter(cli, mem_ctx,
723 if (!W_ERROR_IS_OK(result)) {
727 /* Display printer info */
730 display_print_info0(&info.info0);
733 display_print_info1(&info.info1);
736 display_print_info2(&info.info2);
739 display_print_info3(&info.info3);
742 display_print_info4(&info.info4);
745 display_print_info5(&info.info5);
748 display_print_info6(&info.info6);
751 display_print_info7(&info.info7);
754 printf("unknown info level %d\n", level);
758 if (is_valid_policy_hnd(&pol)) {
760 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
766 /****************************************************************************
767 ****************************************************************************/
769 static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
771 const char *text = NULL;
775 if (blob.length >= sizeof(uint32_t)) {
776 printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
778 printf("%s: REG_DWORD: <invalid>\n", name);
782 pull_reg_sz(talloc_tos(), &blob, &text);
783 printf("%s: REG_SZ: %s\n", name, text ? text : "");
786 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
788 printf("%s: REG_BINARY:", name);
790 for (i=0; i<len; i++) {
791 if (hex[i] == '\0') {
807 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
808 d_printf("pull_reg_multi_sz failed\n");
812 printf("%s: REG_MULTI_SZ: \n", name);
813 for (i=0; values[i] != NULL; i++) {
814 d_printf("%s\n", values[i]);
820 printf("%s: unknown type %d\n", name, type);
825 /****************************************************************************
826 ****************************************************************************/
828 static void display_printer_data(const char *v,
829 enum winreg_Type type,
834 union spoolss_PrinterData r;
835 DATA_BLOB blob = data_blob_const(data, length);
837 enum ndr_err_code ndr_err;
839 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
840 if (!W_ERROR_IS_OK(result)) {
846 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
849 printf("%s: REG_SZ: %s\n", v, r.string);
852 char *hex = hex_encode_talloc(NULL,
853 r.binary.data, r.binary.length);
855 printf("%s: REG_BINARY:", v);
857 for (i=0; i<len; i++) {
858 if (hex[i] == '\0') {
870 if (strequal(v, "OsVersion")) {
871 struct spoolss_OSVersion os;
872 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
873 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
874 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
876 printf("OsMajor: %u\n", os.major);
877 printf("OsMinor: %u\n", os.minor);
878 printf("OsBuild: %u\n", os.build);
879 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
882 if (strequal(v, "OsVersionEx")) {
883 struct spoolss_OSVersionEx os;
884 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
885 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
886 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
887 printf("OsMajor: %u\n", os.major);
888 printf("OsMinor: %u\n", os.minor);
889 printf("OsBuild: %u\n", os.build);
890 printf("ServicePackMajor: %u\n", os.service_pack_major);
891 printf("ServicePackMinor: %u\n", os.service_pack_minor);
892 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
898 printf("%s: REG_MULTI_SZ: ", v);
899 for (i=0; r.string_array[i] != NULL; i++) {
900 printf("%s ", r.string_array[i]);
905 printf("%s: unknown type 0x%02x:\n", v, type);
910 /****************************************************************************
911 ****************************************************************************/
913 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
915 int argc, const char **argv)
917 struct policy_handle pol;
920 const char *valuename;
921 enum winreg_Type type;
924 struct dcerpc_binding_handle *b = cli->binding_handle;
927 printf("Usage: %s <printername> <valuename>\n", argv[0]);
928 printf("<printername> of . queries print server\n");
933 /* Open a printer handle */
935 if (strncmp(argv[1], ".", sizeof(".")) == 0)
936 fstrcpy(printername, cli->srv_name_slash);
938 slprintf(printername, sizeof(printername)-1, "%s\\%s",
939 cli->srv_name_slash, argv[1]);
941 /* get a printer handle */
943 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
945 SEC_FLAG_MAXIMUM_ALLOWED,
947 if (!W_ERROR_IS_OK(result))
950 /* Get printer info */
952 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
959 if (!W_ERROR_IS_OK(result))
962 /* Display printer data */
964 display_printer_data(valuename, type, data, needed);
967 if (is_valid_policy_hnd(&pol)) {
969 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
975 /****************************************************************************
976 ****************************************************************************/
978 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
980 int argc, const char **argv)
982 struct policy_handle pol;
986 const char *valuename, *keyname;
988 enum winreg_Type type;
989 uint8_t *data = NULL;
990 uint32_t offered = 0;
992 struct dcerpc_binding_handle *b = cli->binding_handle;
995 printf("Usage: %s <printername> <keyname> <valuename>\n",
997 printf("<printername> of . queries print server\n");
1000 valuename = argv[3];
1003 /* Open a printer handle */
1005 if (strncmp(argv[1], ".", sizeof(".")) == 0)
1006 fstrcpy(printername, cli->srv_name_slash);
1008 slprintf(printername, sizeof(printername)-1, "%s\\%s",
1009 cli->srv_name_slash, argv[1]);
1011 /* get a printer handle */
1013 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1015 SEC_FLAG_MAXIMUM_ALLOWED,
1017 if (!W_ERROR_IS_OK(result))
1020 /* Get printer info */
1022 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1027 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1036 if (!NT_STATUS_IS_OK(status)) {
1037 result = ntstatus_to_werror(status);
1040 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1042 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1046 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1057 if (!NT_STATUS_IS_OK(status)) {
1058 result = ntstatus_to_werror(status);
1062 if (!W_ERROR_IS_OK(result))
1065 /* Display printer data */
1067 display_printer_data(valuename, type, data, needed);
1071 if (is_valid_policy_hnd(&pol)) {
1073 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1079 /****************************************************************************
1080 ****************************************************************************/
1082 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1088 printf("Printer Driver Info 1:\n");
1089 printf("\tDriver Name: [%s]\n", r->driver_name);
1093 /****************************************************************************
1094 ****************************************************************************/
1096 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1102 printf("Printer Driver Info 2:\n");
1103 printf("\tVersion: [%x]\n", r->version);
1104 printf("\tDriver Name: [%s]\n", r->driver_name);
1105 printf("\tArchitecture: [%s]\n", r->architecture);
1106 printf("\tDriver Path: [%s]\n", r->driver_path);
1107 printf("\tDatafile: [%s]\n", r->data_file);
1108 printf("\tConfigfile: [%s]\n", r->config_file);
1112 /****************************************************************************
1113 ****************************************************************************/
1115 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1123 printf("Printer Driver Info 3:\n");
1124 printf("\tVersion: [%x]\n", r->version);
1125 printf("\tDriver Name: [%s]\n", r->driver_name);
1126 printf("\tArchitecture: [%s]\n", r->architecture);
1127 printf("\tDriver Path: [%s]\n", r->driver_path);
1128 printf("\tDatafile: [%s]\n", r->data_file);
1129 printf("\tConfigfile: [%s]\n", r->config_file);
1130 printf("\tHelpfile: [%s]\n", r->help_file);
1132 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1133 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1136 printf("\tMonitorname: [%s]\n", r->monitor_name);
1137 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1141 /****************************************************************************
1142 ****************************************************************************/
1144 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1152 printf("Printer Driver Info 4:\n");
1153 printf("\tVersion: [%x]\n", r->version);
1154 printf("\tDriver Name: [%s]\n", r->driver_name);
1155 printf("\tArchitecture: [%s]\n", r->architecture);
1156 printf("\tDriver Path: [%s]\n", r->driver_path);
1157 printf("\tDatafile: [%s]\n", r->data_file);
1158 printf("\tConfigfile: [%s]\n", r->config_file);
1159 printf("\tHelpfile: [%s]\n", r->help_file);
1161 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1162 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1165 printf("\tMonitorname: [%s]\n", r->monitor_name);
1166 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1168 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1169 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1174 /****************************************************************************
1175 ****************************************************************************/
1177 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1183 printf("Printer Driver Info 5:\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("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1191 printf("\tConfig Version: [0x%x]\n", r->config_version);
1192 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1196 /****************************************************************************
1197 ****************************************************************************/
1199 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1207 printf("Printer Driver Info 6:\n");
1208 printf("\tVersion: [%x]\n", r->version);
1209 printf("\tDriver Name: [%s]\n", r->driver_name);
1210 printf("\tArchitecture: [%s]\n", r->architecture);
1211 printf("\tDriver Path: [%s]\n", r->driver_path);
1212 printf("\tDatafile: [%s]\n", r->data_file);
1213 printf("\tConfigfile: [%s]\n", r->config_file);
1214 printf("\tHelpfile: [%s]\n", r->help_file);
1216 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1217 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1220 printf("\tMonitorname: [%s]\n", r->monitor_name);
1221 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1223 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1224 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1227 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1228 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1229 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1230 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1231 printf("\tHardware ID: [%s]\n", r->hardware_id);
1232 printf("\tProvider: [%s]\n", r->provider);
1237 /****************************************************************************
1238 ****************************************************************************/
1240 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1248 printf("Printer Driver Info 8:\n");
1249 printf("\tVersion: [%x]\n", r->version);
1250 printf("\tDriver Name: [%s]\n", r->driver_name);
1251 printf("\tArchitecture: [%s]\n", r->architecture);
1252 printf("\tDriver Path: [%s]\n", r->driver_path);
1253 printf("\tDatafile: [%s]\n", r->data_file);
1254 printf("\tConfigfile: [%s]\n", r->config_file);
1255 printf("\tHelpfile: [%s]\n", r->help_file);
1256 printf("\tMonitorname: [%s]\n", r->monitor_name);
1257 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1259 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1260 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1263 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1264 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1267 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1268 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1269 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1270 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1271 printf("\tHardware ID: [%s]\n", r->hardware_id);
1272 printf("\tProvider: [%s]\n", r->provider);
1273 printf("\tPrint Processor: [%s]\n", r->print_processor);
1274 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1275 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1276 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1278 printf("\tInf Path: [%s]\n", r->inf_path);
1279 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1280 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1281 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1283 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1284 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1285 (long long unsigned int)r->min_inbox_driver_ver_version);
1290 /****************************************************************************
1291 ****************************************************************************/
1293 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1294 TALLOC_CTX *mem_ctx,
1295 int argc, const char **argv)
1297 struct policy_handle pol;
1300 const char *printername;
1302 bool success = false;
1303 union spoolss_DriverInfo info;
1304 uint32_t server_major_version;
1305 uint32_t server_minor_version;
1306 struct dcerpc_binding_handle *b = cli->binding_handle;
1308 if ((argc == 1) || (argc > 3)) {
1309 printf("Usage: %s <printername> [level]\n", argv[0]);
1313 /* get the arguments need to open the printer handle */
1315 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1318 level = atoi(argv[2]);
1321 /* Open a printer handle */
1323 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1327 if (!W_ERROR_IS_OK(werror)) {
1328 printf("Error opening printer handle for %s!\n", printername);
1332 /* loop through and print driver info level for each architecture */
1334 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1336 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1338 archi_table[i].long_archi,
1341 archi_table[i].version,
1344 &server_major_version,
1345 &server_minor_version);
1346 if (!W_ERROR_IS_OK(werror)) {
1350 /* need at least one success */
1354 printf("\n[%s]\n", archi_table[i].long_archi);
1358 display_print_driver1(&info.info1);
1361 display_print_driver2(&info.info2);
1364 display_print_driver3(&info.info3);
1367 display_print_driver4(&info.info4);
1370 display_print_driver5(&info.info5);
1373 display_print_driver6(&info.info6);
1376 display_print_driver8(&info.info8);
1379 printf("unknown info level %d\n", level);
1386 if (is_valid_policy_hnd(&pol)) {
1388 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1398 /****************************************************************************
1399 ****************************************************************************/
1401 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1402 TALLOC_CTX *mem_ctx,
1403 const char *architecture,
1408 union spoolss_DriverInfo *info = NULL;
1411 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1412 cli->srv_name_slash,
1419 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1420 printf("Server does not support environment [%s]\n",
1429 if (!W_ERROR_IS_OK(werror)) {
1430 printf("Error getting driver for environment [%s] - %s\n",
1431 architecture, win_errstr(werror));
1435 printf("\n[%s]\n", architecture);
1439 for (j=0; j < count; j++) {
1440 display_print_driver1(&info[j].info1);
1444 for (j=0; j < count; j++) {
1445 display_print_driver2(&info[j].info2);
1449 for (j=0; j < count; j++) {
1450 display_print_driver3(&info[j].info3);
1454 for (j=0; j < count; j++) {
1455 display_print_driver4(&info[j].info4);
1459 for (j=0; j < count; j++) {
1460 display_print_driver5(&info[j].info5);
1464 for (j=0; j < count; j++) {
1465 display_print_driver6(&info[j].info6);
1469 for (j=0; j < count; j++) {
1470 display_print_driver8(&info[j].info8);
1474 printf("unknown info level %d\n", level);
1475 return WERR_INVALID_LEVEL;
1481 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1482 TALLOC_CTX *mem_ctx,
1483 int argc, const char **argv)
1485 WERROR werror = WERR_OK;
1488 const char *architecture = NULL;
1491 printf("Usage: enumdrivers [level] [architecture]\n");
1496 level = atoi(argv[1]);
1500 architecture = argv[2];
1504 return enum_driver_by_architecture(cli, mem_ctx,
1509 /* loop through and print driver info level for each architecture */
1510 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1511 /* check to see if we already asked for this architecture string */
1513 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1517 werror = enum_driver_by_architecture(cli, mem_ctx,
1518 archi_table[i].long_archi,
1520 if (!W_ERROR_IS_OK(werror)) {
1528 /****************************************************************************
1529 ****************************************************************************/
1531 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1533 printf("\tDirectory Name:[%s]\n", r->directory_name);
1536 /****************************************************************************
1537 ****************************************************************************/
1539 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1540 TALLOC_CTX *mem_ctx,
1541 int argc, const char **argv)
1545 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1548 union spoolss_DriverDirectoryInfo info;
1550 struct dcerpc_binding_handle *b = cli->binding_handle;
1553 printf("Usage: %s [environment]\n", argv[0]);
1557 /* Get the arguments need to open the printer handle */
1563 /* Get the directory. Only use Info level 1 */
1565 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1566 cli->srv_name_slash,
1574 if (!NT_STATUS_IS_OK(status)) {
1575 return ntstatus_to_werror(status);
1577 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1579 buffer = data_blob_talloc_zero(mem_ctx, needed);
1581 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1582 cli->srv_name_slash,
1590 if (!NT_STATUS_IS_OK(status)) {
1591 return ntstatus_to_werror(status);
1595 if (W_ERROR_IS_OK(result)) {
1596 display_printdriverdir_1(&info.info1);
1602 /****************************************************************************
1603 ****************************************************************************/
1605 static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1606 TALLOC_CTX *mem_ctx,
1607 int argc, const char **argv)
1611 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1614 struct dcerpc_binding_handle *b = cli->binding_handle;
1615 const char *package_id = "";
1616 const char *cab = NULL;
1619 printf("Usage: %s [environment] [package_id]\n", argv[0]);
1623 /* Get the arguments need to open the printer handle */
1630 package_id = argv[2];
1634 cab = talloc_zero_array(mem_ctx, char, offered);
1636 return WERR_NOT_ENOUGH_MEMORY;
1638 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1639 cli->srv_name_slash,
1647 if (!NT_STATUS_IS_OK(status)) {
1648 return ntstatus_to_werror(status);
1651 if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1653 cab = talloc_zero_array(mem_ctx, char, offered);
1655 return WERR_NOT_ENOUGH_MEMORY;
1657 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1658 cli->srv_name_slash,
1666 if (!NT_STATUS_IS_OK(status)) {
1667 return ntstatus_to_werror(status);
1671 return W_ERROR(WIN32_FROM_HRESULT(hresult));
1675 /****************************************************************************
1676 ****************************************************************************/
1678 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1679 struct spoolss_AddDriverInfo3 *info,
1685 for (i=0; archi_table[i].long_archi != NULL; i++)
1687 if (strcmp(arch, archi_table[i].short_archi) == 0)
1689 info->version = archi_table[i].version;
1690 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1695 if (archi_table[i].long_archi == NULL)
1697 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1704 /**************************************************************************
1705 wrapper for strtok to get the next parameter from a delimited list.
1706 Needed to handle the empty parameter string denoted by "NULL"
1707 *************************************************************************/
1709 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1710 const char *delim, const char **dest,
1715 /* get the next token */
1716 ptr = strtok_r(str, delim, saveptr);
1718 /* a string of 'NULL' is used to represent an empty
1719 parameter because two consecutive delimiters
1720 will not return an empty string. See man strtok(3)
1722 if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1727 *dest = talloc_strdup(mem_ctx, ptr);
1733 /********************************************************************************
1734 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1735 string in the form of
1736 <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1737 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1738 <Default Data Type>:<Comma Separated list of Files>
1739 *******************************************************************************/
1741 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1746 char *saveptr = NULL;
1747 struct spoolss_StringArray *deps;
1748 const char **file_array = NULL;
1751 /* fill in the UNISTR fields */
1752 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1753 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1754 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1755 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1756 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1757 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1758 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1760 /* <Comma Separated List of Dependent Files> */
1761 /* save the beginning of the string */
1762 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1765 /* begin to strip out each filename */
1766 str = strtok_r(str, ",", &saveptr);
1768 /* no dependent files, we are done */
1773 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1778 while (str != NULL) {
1780 ok = add_string_to_array(deps, str, &file_array, &count);
1784 str = strtok_r(NULL, ",", &saveptr);
1787 deps->string = talloc_zero_array(deps, const char *, count + 1);
1788 if (!deps->string) {
1792 for (i=0; i < count; i++) {
1793 deps->string[i] = file_array[i];
1796 r->dependent_files = deps;
1801 /****************************************************************************
1802 ****************************************************************************/
1804 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1805 TALLOC_CTX *mem_ctx,
1806 int argc, const char **argv)
1811 struct spoolss_AddDriverInfoCtr info_ctr;
1812 struct spoolss_AddDriverInfo3 info3;
1815 struct dcerpc_binding_handle *b = cli->binding_handle;
1817 /* parse the command arguments */
1818 if (argc != 3 && argc != 4)
1820 printf ("Usage: %s <Environment> \\\n", argv[0]);
1821 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1822 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1823 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1824 printf ("\t[version]\n");
1829 /* Fill in the spoolss_AddDriverInfo3 struct */
1832 arch = cmd_spoolss_get_short_archi(argv[1]);
1834 printf ("Error Unknown architecture [%s]\n", argv[1]);
1835 return WERR_INVALID_PARAMETER;
1838 set_drv_info_3_env(mem_ctx, &info3, arch);
1840 driver_args = talloc_strdup( mem_ctx, argv[2] );
1841 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1843 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1844 return WERR_INVALID_PARAMETER;
1847 /* if printer driver version specified, override the default version
1848 * used by the architecture. This allows installation of Windows
1849 * 2000 (version 3) printer drivers. */
1852 info3.version = atoi(argv[3]);
1856 info_ctr.level = level;
1857 info_ctr.info.info3 = &info3;
1859 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1860 cli->srv_name_slash,
1863 if (!NT_STATUS_IS_OK(status)) {
1864 return ntstatus_to_werror(status);
1866 if (W_ERROR_IS_OK(result)) {
1867 printf ("Printer Driver %s successfully installed.\n",
1875 /****************************************************************************
1876 ****************************************************************************/
1878 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1879 TALLOC_CTX *mem_ctx,
1880 int argc, const char **argv)
1883 struct spoolss_SetPrinterInfoCtr info_ctr;
1884 struct spoolss_SetPrinterInfo2 info2;
1886 /* parse the command arguments */
1889 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1893 /* Fill in the DRIVER_INFO_2 struct */
1896 info2.printername = argv[1];
1897 info2.drivername = argv[3];
1898 info2.sharename = argv[2];
1899 info2.portname = argv[4];
1900 info2.comment = "Created by rpcclient";
1901 info2.printprocessor = "winprint";
1902 info2.datatype = "RAW";
1903 info2.devmode_ptr = 0;
1904 info2.secdesc_ptr = 0;
1905 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1907 info2.defaultpriority = 0;
1908 info2.starttime = 0;
1909 info2.untiltime = 0;
1911 /* These three fields must not be used by AddPrinter()
1912 as defined in the MS Platform SDK documentation..
1916 info2.averageppm = 0;
1920 info_ctr.info.info2 = &info2;
1922 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1924 if (W_ERROR_IS_OK(result))
1925 printf ("Printer %s successfully installed.\n", argv[1]);
1930 /****************************************************************************
1931 ****************************************************************************/
1933 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1934 TALLOC_CTX *mem_ctx,
1935 int argc, const char **argv)
1937 struct policy_handle pol;
1941 const char *printername;
1942 union spoolss_PrinterInfo info;
1943 struct spoolss_SetPrinterInfoCtr info_ctr;
1944 struct spoolss_SetPrinterInfo2 info2;
1945 struct spoolss_DevmodeContainer devmode_ctr;
1946 struct sec_desc_buf secdesc_ctr;
1947 struct dcerpc_binding_handle *b = cli->binding_handle;
1949 ZERO_STRUCT(devmode_ctr);
1950 ZERO_STRUCT(secdesc_ctr);
1952 /* parse the command arguments */
1955 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1959 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1961 /* Get a printer handle */
1963 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1967 if (!W_ERROR_IS_OK(result))
1970 /* Get printer info */
1972 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1977 if (!W_ERROR_IS_OK(result)) {
1978 printf ("Unable to retrieve printer information!\n");
1982 /* Set the printer driver */
1984 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1985 info2.drivername = argv[2];
1988 info_ctr.info.info2 = &info2;
1990 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1997 if (!NT_STATUS_IS_OK(status)) {
1998 result = ntstatus_to_werror(status);
2001 if (!W_ERROR_IS_OK(result)) {
2002 printf("SetPrinter call failed!\n");
2006 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
2011 if (is_valid_policy_hnd(&pol)) {
2013 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2020 /****************************************************************************
2021 ****************************************************************************/
2023 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2024 TALLOC_CTX *mem_ctx,
2025 int argc, const char **argv)
2027 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2029 struct dcerpc_binding_handle *b = cli->binding_handle;
2034 const char *arch = NULL;
2035 uint32_t delete_flags = 0;
2037 /* parse the command arguments */
2038 if (argc < 2 || argc > 5) {
2039 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2046 vers = atoi(argv[3]);
2047 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2050 delete_flags = atoi(argv[4]);
2052 /* delete the driver for all architectures */
2053 for (i=0; archi_table[i].long_archi; i++) {
2055 if (arch && !strequal(archi_table[i].long_archi, arch))
2058 if (vers >= 0 && archi_table[i].version != vers)
2061 /* make the call to remove the driver */
2062 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2063 cli->srv_name_slash,
2064 archi_table[i].long_archi,
2067 archi_table[i].version,
2069 if (!NT_STATUS_IS_OK(status)) {
2070 return ntstatus_to_werror(status);
2072 if ( !W_ERROR_IS_OK(result) )
2074 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2075 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2076 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2081 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2082 archi_table[i].long_archi, archi_table[i].version);
2091 /****************************************************************************
2092 ****************************************************************************/
2094 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2095 TALLOC_CTX *mem_ctx,
2096 int argc, const char **argv)
2098 WERROR result = WERR_OK;
2101 struct dcerpc_binding_handle *b = cli->binding_handle;
2103 /* parse the command arguments */
2105 printf ("Usage: %s <driver>\n", argv[0]);
2109 /* delete the driver for all architectures */
2110 for (i=0; archi_table[i].long_archi; i++) {
2113 /* make the call to remove the driver */
2114 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2115 cli->srv_name_slash,
2116 archi_table[i].long_archi,
2119 if (!NT_STATUS_IS_OK(status)) {
2120 result = ntstatus_to_werror(status);
2123 if ( !W_ERROR_IS_OK(result) ) {
2124 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2125 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2126 argv[1], archi_table[i].long_archi,
2127 win_errstr(result));
2130 printf ("Driver %s removed for arch [%s].\n", argv[1],
2131 archi_table[i].long_archi);
2138 /****************************************************************************
2139 ****************************************************************************/
2141 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2142 TALLOC_CTX *mem_ctx,
2143 int argc, const char **argv)
2147 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2150 union spoolss_PrintProcessorDirectoryInfo info;
2152 struct dcerpc_binding_handle *b = cli->binding_handle;
2154 /* parse the command arguments */
2156 printf ("Usage: %s [environment]\n", argv[0]);
2161 environment = argv[1];
2164 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2165 cli->srv_name_slash,
2173 if (!NT_STATUS_IS_OK(status)) {
2174 return ntstatus_to_werror(status);
2176 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2178 buffer = data_blob_talloc_zero(mem_ctx, needed);
2180 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2181 cli->srv_name_slash,
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return ntstatus_to_werror(status);
2194 if (W_ERROR_IS_OK(result)) {
2195 printf("%s\n", info.info1.directory_name);
2201 /****************************************************************************
2202 ****************************************************************************/
2204 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2205 int argc, const char **argv)
2207 struct policy_handle handle;
2210 const char *printername;
2211 struct spoolss_AddFormInfoCtr info_ctr;
2212 struct spoolss_AddFormInfo1 info1;
2213 struct spoolss_AddFormInfo2 info2;
2215 struct dcerpc_binding_handle *b = cli->binding_handle;
2217 /* Parse the command arguments */
2219 if (argc < 3 || argc > 5) {
2220 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2224 /* Get a printer handle */
2226 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2228 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2232 if (!W_ERROR_IS_OK(werror))
2235 /* Dummy up some values for the form data */
2238 level = atoi(argv[3]);
2243 info1.flags = SPOOLSS_FORM_USER;
2244 info1.form_name = argv[2];
2245 info1.size.width = 100;
2246 info1.size.height = 100;
2247 info1.area.left = 0;
2248 info1.area.top = 10;
2249 info1.area.right = 20;
2250 info1.area.bottom = 30;
2253 info_ctr.info.info1 = &info1;
2257 info2.flags = SPOOLSS_FORM_USER;
2258 info2.form_name = argv[2];
2259 info2.size.width = 100;
2260 info2.size.height = 100;
2261 info2.area.left = 0;
2262 info2.area.top = 10;
2263 info2.area.right = 20;
2264 info2.area.bottom = 30;
2265 info2.keyword = argv[2];
2266 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2267 info2.mui_dll = NULL;
2268 info2.ressource_id = 0;
2269 info2.display_name = argv[2];
2273 info_ctr.info.info2 = &info2;
2277 werror = WERR_INVALID_PARAMETER;
2283 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2287 if (!NT_STATUS_IS_OK(status)) {
2288 werror = ntstatus_to_werror(status);
2292 if (is_valid_policy_hnd(&handle)) {
2294 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2300 /****************************************************************************
2301 ****************************************************************************/
2303 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2304 int argc, const char **argv)
2306 struct policy_handle handle;
2309 const char *printername;
2310 struct spoolss_AddFormInfoCtr info_ctr;
2311 struct spoolss_AddFormInfo1 info1;
2312 struct dcerpc_binding_handle *b = cli->binding_handle;
2314 /* Parse the command arguments */
2317 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2321 /* Get a printer handle */
2323 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2325 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2327 SEC_FLAG_MAXIMUM_ALLOWED,
2329 if (!W_ERROR_IS_OK(werror))
2332 /* Dummy up some values for the form data */
2334 info1.flags = SPOOLSS_FORM_PRINTER;
2335 info1.size.width = 100;
2336 info1.size.height = 100;
2337 info1.area.left = 0;
2338 info1.area.top = 1000;
2339 info1.area.right = 2000;
2340 info1.area.bottom = 3000;
2341 info1.form_name = argv[2];
2343 info_ctr.info.info1 = &info1;
2348 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2353 if (!NT_STATUS_IS_OK(status)) {
2354 werror = ntstatus_to_werror(status);
2358 if (is_valid_policy_hnd(&handle)) {
2360 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2366 /****************************************************************************
2367 ****************************************************************************/
2369 static const char *get_form_flag(int form_flag)
2371 switch (form_flag) {
2372 case SPOOLSS_FORM_USER:
2374 case SPOOLSS_FORM_BUILTIN:
2375 return "FORM_BUILTIN";
2376 case SPOOLSS_FORM_PRINTER:
2377 return "FORM_PRINTER";
2383 /****************************************************************************
2384 ****************************************************************************/
2386 static void display_form_info1(struct spoolss_FormInfo1 *r)
2389 "\tflag: %s (%d)\n" \
2390 "\twidth: %d, length: %d\n" \
2391 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2392 r->form_name, get_form_flag(r->flags), r->flags,
2393 r->size.width, r->size.height,
2394 r->area.left, r->area.right,
2395 r->area.top, r->area.bottom);
2398 /****************************************************************************
2399 ****************************************************************************/
2401 static void display_form_info2(struct spoolss_FormInfo2 *r)
2404 "\tflag: %s (%d)\n" \
2405 "\twidth: %d, length: %d\n" \
2406 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2407 r->form_name, get_form_flag(r->flags), r->flags,
2408 r->size.width, r->size.height,
2409 r->area.left, r->area.right,
2410 r->area.top, r->area.bottom);
2411 printf("\tkeyword: %s\n", r->keyword);
2412 printf("\tstring_type: 0x%08x\n", r->string_type);
2413 printf("\tmui_dll: %s\n", r->mui_dll);
2414 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2415 printf("\tdisplay_name: %s\n", r->display_name);
2416 printf("\tlang_id: %d\n", r->lang_id);
2420 /****************************************************************************
2421 ****************************************************************************/
2423 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2424 int argc, const char **argv)
2426 struct policy_handle handle;
2429 const char *printername;
2431 uint32_t offered = 0;
2432 union spoolss_FormInfo info;
2435 struct dcerpc_binding_handle *b = cli->binding_handle;
2437 /* Parse the command arguments */
2439 if (argc < 3 || argc > 5) {
2440 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2444 /* Get a printer handle */
2446 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2448 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2450 SEC_FLAG_MAXIMUM_ALLOWED,
2452 if (!W_ERROR_IS_OK(werror))
2456 level = atoi(argv[3]);
2461 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2470 if (!NT_STATUS_IS_OK(status)) {
2471 werror = ntstatus_to_werror(status);
2474 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2475 buffer = data_blob_talloc_zero(mem_ctx, needed);
2477 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2486 if (!NT_STATUS_IS_OK(status)) {
2487 werror = ntstatus_to_werror(status);
2492 if (!W_ERROR_IS_OK(werror)) {
2498 display_form_info1(&info.info1);
2501 display_form_info2(&info.info2);
2506 if (is_valid_policy_hnd(&handle)) {
2508 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2514 /****************************************************************************
2515 ****************************************************************************/
2517 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2518 TALLOC_CTX *mem_ctx, int argc,
2521 struct policy_handle handle;
2524 const char *printername;
2525 struct dcerpc_binding_handle *b = cli->binding_handle;
2527 /* Parse the command arguments */
2530 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2534 /* Get a printer handle */
2536 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2538 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2540 SEC_FLAG_MAXIMUM_ALLOWED,
2542 if (!W_ERROR_IS_OK(werror))
2545 /* Delete the form */
2547 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2551 if (!NT_STATUS_IS_OK(status)) {
2552 werror = ntstatus_to_werror(status);
2557 if (is_valid_policy_hnd(&handle)) {
2559 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2565 /****************************************************************************
2566 ****************************************************************************/
2568 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2569 TALLOC_CTX *mem_ctx, int argc,
2572 struct policy_handle handle;
2574 const char *printername;
2575 uint32_t num_forms, level = 1, i;
2576 union spoolss_FormInfo *forms;
2577 struct dcerpc_binding_handle *b = cli->binding_handle;
2579 /* Parse the command arguments */
2581 if (argc < 2 || argc > 4) {
2582 printf ("Usage: %s <printer> [level]\n", argv[0]);
2586 /* Get a printer handle */
2588 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2590 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2592 SEC_FLAG_MAXIMUM_ALLOWED,
2594 if (!W_ERROR_IS_OK(werror))
2598 level = atoi(argv[2]);
2601 /* Enumerate forms */
2603 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2610 if (!W_ERROR_IS_OK(werror))
2613 /* Display output */
2615 for (i = 0; i < num_forms; i++) {
2618 display_form_info1(&forms[i].info1);
2621 display_form_info2(&forms[i].info2);
2627 if (is_valid_policy_hnd(&handle)) {
2629 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2635 /****************************************************************************
2636 ****************************************************************************/
2638 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2639 TALLOC_CTX *mem_ctx,
2640 int argc, const char **argv)
2644 const char *printername;
2645 struct policy_handle pol = { 0, };
2646 union spoolss_PrinterInfo info;
2647 enum winreg_Type type;
2648 union spoolss_PrinterData data;
2650 struct dcerpc_binding_handle *b = cli->binding_handle;
2653 /* parse the command arguments */
2655 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2656 " <value> <data>\n",
2661 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2665 if (strequal(argv[2], "string")) {
2669 if (strequal(argv[2], "binary")) {
2673 if (strequal(argv[2], "dword")) {
2677 if (strequal(argv[2], "multistring")) {
2678 type = REG_MULTI_SZ;
2681 if (type == REG_NONE) {
2682 printf("Unknown data type: %s\n", argv[2]);
2683 result = WERR_INVALID_PARAMETER;
2687 /* get a printer handle */
2689 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2691 SEC_FLAG_MAXIMUM_ALLOWED,
2693 if (!W_ERROR_IS_OK(result)) {
2697 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2702 if (!W_ERROR_IS_OK(result)) {
2706 printf("%s\n", current_timestring(mem_ctx, true));
2707 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2709 /* Set the printer data */
2713 data.string = talloc_strdup(mem_ctx, argv[4]);
2714 W_ERROR_HAVE_NO_MEMORY(data.string);
2717 data.value = smb_strtoul(argv[4],
2723 result = WERR_INVALID_PARAMETER;
2729 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2731 case REG_MULTI_SZ: {
2734 const char **strings = NULL;
2738 for (i=4; i<argc; i++) {
2739 if (strcmp(argv[i], "NULL") == 0) {
2742 if (!add_string_to_array(mem_ctx, argv[i],
2745 result = WERR_NOT_ENOUGH_MEMORY;
2749 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2750 if (!data.string_array) {
2751 result = WERR_NOT_ENOUGH_MEMORY;
2754 for (i=0; i < num_strings; i++) {
2755 data.string_array[i] = strings[i];
2760 printf("Unknown data type: %s\n", argv[2]);
2761 result = WERR_INVALID_PARAMETER;
2765 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2766 if (!W_ERROR_IS_OK(result)) {
2770 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2772 argv[3], /* value_name */
2777 if (!NT_STATUS_IS_OK(status)) {
2778 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2779 result = ntstatus_to_werror(status);
2782 if (!W_ERROR_IS_OK(result)) {
2783 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2786 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2788 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2793 if (!W_ERROR_IS_OK(result)) {
2797 printf("%s\n", current_timestring(mem_ctx, true));
2798 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2802 if (is_valid_policy_hnd(&pol)) {
2804 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2810 /****************************************************************************
2811 ****************************************************************************/
2813 static void display_job_info1(struct spoolss_JobInfo1 *r)
2815 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2816 r->user_name, r->document_name, r->text_status, r->pages_printed,
2820 /****************************************************************************
2821 ****************************************************************************/
2823 static void display_job_info2(struct spoolss_JobInfo2 *r)
2825 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2826 r->position, r->job_id,
2827 r->user_name, r->document_name, r->text_status, r->pages_printed,
2828 r->total_pages, r->size);
2831 /****************************************************************************
2832 ****************************************************************************/
2834 static void display_job_info3(struct spoolss_JobInfo3 *r)
2836 printf("jobid[%d], next_jobid[%d]\n",
2837 r->job_id, r->next_job_id);
2840 /****************************************************************************
2841 ****************************************************************************/
2843 static void display_job_info4(struct spoolss_JobInfo4 *r)
2845 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2846 r->position, r->job_id,
2847 r->user_name, r->document_name, r->text_status, r->pages_printed,
2848 r->total_pages, r->size, r->size_high);
2851 /****************************************************************************
2852 ****************************************************************************/
2854 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2855 TALLOC_CTX *mem_ctx, int argc,
2859 uint32_t level = 1, count, i;
2860 const char *printername;
2861 struct policy_handle hnd;
2862 union spoolss_JobInfo *info;
2863 struct dcerpc_binding_handle *b = cli->binding_handle;
2865 if (argc < 2 || argc > 3) {
2866 printf("Usage: %s printername [level]\n", argv[0]);
2871 level = atoi(argv[2]);
2874 /* Open printer handle */
2876 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2878 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2880 SEC_FLAG_MAXIMUM_ALLOWED,
2882 if (!W_ERROR_IS_OK(result))
2885 /* Enumerate ports */
2887 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2895 if (!W_ERROR_IS_OK(result)) {
2899 for (i = 0; i < count; i++) {
2902 display_job_info1(&info[i].info1);
2905 display_job_info2(&info[i].info2);
2908 d_printf("unknown info level %d\n", level);
2914 if (is_valid_policy_hnd(&hnd)) {
2916 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2922 /****************************************************************************
2923 ****************************************************************************/
2925 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2926 TALLOC_CTX *mem_ctx, int argc,
2930 const char *printername;
2931 struct policy_handle hnd;
2934 union spoolss_JobInfo info;
2935 struct dcerpc_binding_handle *b = cli->binding_handle;
2937 if (argc < 3 || argc > 4) {
2938 printf("Usage: %s printername job_id [level]\n", argv[0]);
2942 job_id = atoi(argv[2]);
2945 level = atoi(argv[3]);
2948 /* Open printer handle */
2950 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2952 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2954 SEC_FLAG_MAXIMUM_ALLOWED,
2956 if (!W_ERROR_IS_OK(result)) {
2960 /* Enumerate ports */
2962 result = rpccli_spoolss_getjob(cli, mem_ctx,
2969 if (!W_ERROR_IS_OK(result)) {
2975 display_job_info1(&info.info1);
2978 display_job_info2(&info.info2);
2981 display_job_info3(&info.info3);
2984 display_job_info4(&info.info4);
2987 d_printf("unknown info level %d\n", level);
2992 if (is_valid_policy_hnd(&hnd)) {
2994 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3000 /****************************************************************************
3001 ****************************************************************************/
3005 enum spoolss_JobControl val;
3007 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
3008 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
3009 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
3010 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
3011 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
3012 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
3013 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
3014 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
3015 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
3018 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3022 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3023 if (strequal(cmdvals[i].name, cmd)) {
3024 return cmdvals[i].val;
3027 return (enum spoolss_JobControl)atoi(cmd);
3030 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3031 TALLOC_CTX *mem_ctx, int argc,
3036 const char *printername;
3037 struct policy_handle hnd;
3039 enum spoolss_JobControl command;
3040 struct dcerpc_binding_handle *b = cli->binding_handle;
3043 printf("Usage: %s printername job_id command\n", argv[0]);
3044 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3045 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3049 job_id = atoi(argv[2]);
3050 command = parse_setjob_command(argv[3]);
3052 /* Open printer handle */
3054 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3056 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3058 SEC_FLAG_MAXIMUM_ALLOWED,
3060 if (!W_ERROR_IS_OK(result)) {
3066 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3072 if (!NT_STATUS_IS_OK(status)) {
3073 result = ntstatus_to_werror(status);
3076 if (!W_ERROR_IS_OK(result)) {
3081 if (is_valid_policy_hnd(&hnd)) {
3083 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3089 /****************************************************************************
3090 ****************************************************************************/
3092 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3093 TALLOC_CTX *mem_ctx, int argc,
3098 const char *printername;
3099 struct policy_handle hnd;
3100 uint32_t value_needed;
3101 enum winreg_Type type;
3102 uint32_t data_needed;
3103 struct dcerpc_binding_handle *b = cli->binding_handle;
3104 struct spoolss_EnumPrinterData r;
3107 printf("Usage: %s printername\n", argv[0]);
3111 /* Open printer handle */
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)) {
3123 /* Enumerate data */
3126 r.in.enum_index = 0;
3127 r.in.value_offered = 0;
3128 r.in.data_offered = 0;
3129 r.out.value_name = NULL;
3130 r.out.value_needed = &value_needed;
3133 r.out.data_needed = &data_needed;
3135 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3136 if (!NT_STATUS_IS_OK(status)) {
3137 result = ntstatus_to_werror(status);
3141 if (!W_ERROR_IS_OK(r.out.result)) {
3142 result = r.out.result;
3146 r.in.data_offered = *r.out.data_needed;
3147 r.in.value_offered = *r.out.value_needed;
3148 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3149 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3153 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 result = ntstatus_to_werror(status);
3159 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3166 display_reg_value(r.out.value_name, *r.out.type,
3167 data_blob_const(r.out.data, r.in.data_offered));
3169 } while (W_ERROR_IS_OK(r.out.result));
3172 if (is_valid_policy_hnd(&hnd)) {
3174 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3180 /****************************************************************************
3181 ****************************************************************************/
3183 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3184 TALLOC_CTX *mem_ctx, int argc,
3189 const char *printername;
3190 struct policy_handle hnd;
3192 struct spoolss_PrinterEnumValues *info;
3193 struct dcerpc_binding_handle *b = cli->binding_handle;
3196 printf("Usage: %s printername <keyname>\n", argv[0]);
3200 /* Open printer handle */
3202 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3204 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3206 SEC_FLAG_MAXIMUM_ALLOWED,
3208 if (!W_ERROR_IS_OK(result)) {
3212 /* Enumerate subkeys */
3214 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3220 if (!W_ERROR_IS_OK(result)) {
3224 for (i=0; i < count; i++) {
3225 display_printer_data(info[i].value_name,
3228 info[i].data->length);
3232 if (is_valid_policy_hnd(&hnd)) {
3234 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3240 /****************************************************************************
3241 ****************************************************************************/
3243 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3244 TALLOC_CTX *mem_ctx, int argc,
3248 const char *printername;
3249 const char *keyname = NULL;
3250 struct policy_handle hnd;
3251 const char **key_buffer = NULL;
3253 uint32_t offered = 0;
3254 struct dcerpc_binding_handle *b = cli->binding_handle;
3256 if (argc < 2 || argc > 4) {
3257 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3268 offered = atoi(argv[3]);
3271 /* Open printer handle */
3273 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3275 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3277 SEC_FLAG_MAXIMUM_ALLOWED,
3279 if (!W_ERROR_IS_OK(result)) {
3283 /* Enumerate subkeys */
3285 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3291 if (!W_ERROR_IS_OK(result)) {
3295 for (i=0; key_buffer && key_buffer[i]; i++) {
3296 printf("%s\n", key_buffer[i]);
3301 if (is_valid_policy_hnd(&hnd)) {
3303 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3309 /****************************************************************************
3310 ****************************************************************************/
3312 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3313 TALLOC_CTX *mem_ctx, int argc,
3316 const char *printername;
3317 const char *clientname;
3318 struct policy_handle hnd = { 0, };
3321 struct spoolss_NotifyOption option;
3322 struct dcerpc_binding_handle *b = cli->binding_handle;
3325 printf("Usage: %s printername\n", argv[0]);
3332 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3334 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3336 SEC_FLAG_MAXIMUM_ALLOWED,
3338 if (!W_ERROR_IS_OK(result)) {
3339 printf("Error opening %s\n", argv[1]);
3343 /* Create spool options */
3348 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3349 if (option.types == NULL) {
3350 result = WERR_NOT_ENOUGH_MEMORY;
3354 option.types[0].type = PRINTER_NOTIFY_TYPE;
3355 option.types[0].count = 1;
3356 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3357 if (option.types[0].fields == NULL) {
3358 result = WERR_NOT_ENOUGH_MEMORY;
3361 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3363 option.types[1].type = JOB_NOTIFY_TYPE;
3364 option.types[1].count = 1;
3365 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3366 if (option.types[1].fields == NULL) {
3367 result = WERR_NOT_ENOUGH_MEMORY;
3370 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3372 clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3374 result = WERR_NOT_ENOUGH_MEMORY;
3380 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3388 if (!NT_STATUS_IS_OK(status)) {
3389 result = ntstatus_to_werror(status);
3392 if (!W_ERROR_IS_OK(result)) {
3393 printf("Error rffpcnex %s\n", argv[1]);
3398 if (is_valid_policy_hnd(&hnd)) {
3400 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3406 /****************************************************************************
3407 ****************************************************************************/
3409 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3410 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3412 union spoolss_PrinterInfo info1, info2;
3414 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3416 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3417 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3422 if ( !W_ERROR_IS_OK(werror) ) {
3423 printf("failed (%s)\n", win_errstr(werror));
3424 talloc_destroy(mem_ctx);
3429 printf("Retrieving printer properties for %s...", cli2->desthost);
3430 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3435 if ( !W_ERROR_IS_OK(werror) ) {
3436 printf("failed (%s)\n", win_errstr(werror));
3437 talloc_destroy(mem_ctx);
3442 talloc_destroy(mem_ctx);
3447 /****************************************************************************
3448 ****************************************************************************/
3450 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3451 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3453 union spoolss_PrinterInfo info1, info2;
3455 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3456 struct security_descriptor *sd1, *sd2;
3460 printf("Retrieving printer security for %s...", cli1->desthost);
3461 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3466 if ( !W_ERROR_IS_OK(werror) ) {
3467 printf("failed (%s)\n", win_errstr(werror));
3473 printf("Retrieving printer security for %s...", cli2->desthost);
3474 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3479 if ( !W_ERROR_IS_OK(werror) ) {
3480 printf("failed (%s)\n", win_errstr(werror));
3489 sd1 = info1.info3.secdesc;
3490 sd2 = info2.info3.secdesc;
3492 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3493 printf("NULL secdesc!\n");
3498 if (!security_descriptor_equal( sd1, sd2 ) ) {
3499 printf("Security Descriptors *not* equal!\n");
3504 printf("Security descriptors match\n");
3507 talloc_destroy(mem_ctx);
3512 /****************************************************************************
3513 ****************************************************************************/
3515 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3516 TALLOC_CTX *mem_ctx, int argc,
3519 const char *printername;
3520 char *printername_path = NULL;
3521 struct cli_state *cli_server2 = NULL;
3522 struct rpc_pipe_client *cli2 = NULL;
3523 struct policy_handle hPrinter1, hPrinter2;
3528 printf("Usage: %s <printer> <server>\n", argv[0]);
3532 printername = argv[1];
3534 /* first get the connection to the remote server */
3536 nt_status = cli_full_connection_creds(&cli_server2, lp_netbios_name(), argv[2],
3539 get_cmdline_auth_info_creds(
3540 popt_get_cmdline_auth_info()),
3541 CLI_FULL_CONNECTION_IPC,
3542 get_cmdline_auth_info_signing_state(
3543 popt_get_cmdline_auth_info()));
3545 if ( !NT_STATUS_IS_OK(nt_status) )
3546 return WERR_GEN_FAILURE;
3548 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3550 if (!NT_STATUS_IS_OK(nt_status)) {
3551 printf("failed to open spoolss pipe on server %s (%s)\n",
3552 argv[2], nt_errstr(nt_status));
3553 return WERR_GEN_FAILURE;
3556 /* now open up both printers */
3558 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3560 printf("Opening %s...", printername_path);
3562 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3566 if ( !W_ERROR_IS_OK(werror) ) {
3567 printf("failed (%s)\n", win_errstr(werror));
3572 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3574 printf("Opening %s...", printername_path);
3575 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3579 if ( !W_ERROR_IS_OK(werror) ) {
3580 printf("failed (%s)\n", win_errstr(werror));
3585 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3586 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3588 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3595 printf("Closing printers...");
3598 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3599 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3603 /* close the second remote connection */
3605 cli_shutdown( cli_server2 );
3609 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3611 printf("print_processor_name: %s\n", r->print_processor_name);
3614 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3615 TALLOC_CTX *mem_ctx, int argc,
3619 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3620 uint32_t num_procs, level = 1, i;
3621 union spoolss_PrintProcessorInfo *procs;
3623 /* Parse the command arguments */
3625 if (argc < 1 || argc > 4) {
3626 printf ("Usage: %s [environment] [level]\n", argv[0]);
3631 environment = argv[1];
3635 level = atoi(argv[2]);
3638 /* Enumerate Print Processors */
3640 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3641 cli->srv_name_slash,
3647 if (!W_ERROR_IS_OK(werror))
3650 /* Display output */
3652 for (i = 0; i < num_procs; i++) {
3655 display_proc_info1(&procs[i].info1);
3664 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3666 printf("name_array: %s\n", r->name_array);
3669 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3670 TALLOC_CTX *mem_ctx, int argc,
3674 const char *print_processor_name = "winprint";
3675 uint32_t num_procs, level = 1, i;
3676 union spoolss_PrintProcDataTypesInfo *procs;
3678 /* Parse the command arguments */
3680 if (argc < 1 || argc > 4) {
3681 printf ("Usage: %s [environment] [level]\n", argv[0]);
3686 print_processor_name = argv[1];
3690 level = atoi(argv[2]);
3693 /* Enumerate Print Processor Data Types */
3695 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3696 cli->srv_name_slash,
3697 print_processor_name,
3702 if (!W_ERROR_IS_OK(werror))
3705 /* Display output */
3707 for (i = 0; i < num_procs; i++) {
3710 display_proc_data_types_info1(&procs[i].info1);
3719 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3721 printf("monitor_name: %s\n", r->monitor_name);
3724 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3726 printf("monitor_name: %s\n", r->monitor_name);
3727 printf("environment: %s\n", r->environment);
3728 printf("dll_name: %s\n", r->dll_name);
3731 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3732 TALLOC_CTX *mem_ctx, int argc,
3736 uint32_t count, level = 1, i;
3737 union spoolss_MonitorInfo *info;
3739 /* Parse the command arguments */
3742 printf("Usage: %s [level]\n", argv[0]);
3747 level = atoi(argv[1]);
3750 /* Enumerate Print Monitors */
3752 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3753 cli->srv_name_slash,
3758 if (!W_ERROR_IS_OK(werror)) {
3762 /* Display output */
3764 for (i = 0; i < count; i++) {
3767 display_monitor1(&info[i].info1);
3770 display_monitor2(&info[i].info2);
3779 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3780 TALLOC_CTX *mem_ctx, int argc,
3785 struct policy_handle handle, gdi_handle;
3786 const char *printername;
3787 struct spoolss_DevmodeContainer devmode_ctr;
3788 struct dcerpc_binding_handle *b = cli->binding_handle;
3790 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3792 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3794 SEC_FLAG_MAXIMUM_ALLOWED,
3796 if (!W_ERROR_IS_OK(result)) {
3800 ZERO_STRUCT(devmode_ctr);
3802 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3807 if (!NT_STATUS_IS_OK(status)) {
3808 result = ntstatus_to_werror(status);
3811 if (!W_ERROR_IS_OK(result)) {
3816 if (is_valid_policy_hnd(&gdi_handle)) {
3818 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3820 if (is_valid_policy_hnd(&handle)) {
3822 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3828 static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3829 TALLOC_CTX *mem_ctx, int argc,
3834 struct policy_handle handle, gdi_handle;
3835 const char *printername;
3836 struct spoolss_DevmodeContainer devmode_ctr;
3837 struct dcerpc_binding_handle *b = cli->binding_handle;
3841 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3843 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3845 SEC_FLAG_MAXIMUM_ALLOWED,
3847 if (!W_ERROR_IS_OK(result)) {
3851 ZERO_STRUCT(devmode_ctr);
3853 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3858 if (!NT_STATUS_IS_OK(status)) {
3859 result = ntstatus_to_werror(status);
3862 if (!W_ERROR_IS_OK(result)) {
3866 in = data_blob_string_const("");
3867 out = data_blob_talloc_zero(mem_ctx, 4);
3869 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3877 if (!NT_STATUS_IS_OK(status)) {
3878 result = ntstatus_to_werror(status);
3881 if (!W_ERROR_IS_OK(result)) {
3885 count = IVAL(out.data, 0);
3887 out = data_blob_talloc_zero(mem_ctx,
3888 count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3890 status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3898 if (!NT_STATUS_IS_OK(status)) {
3899 result = ntstatus_to_werror(status);
3902 if (!W_ERROR_IS_OK(result)) {
3907 enum ndr_err_code ndr_err;
3908 struct UNIVERSAL_FONT_ID_ctr r;
3910 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3911 (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3912 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3913 NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3918 if (is_valid_policy_hnd(&gdi_handle)) {
3920 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3922 if (is_valid_policy_hnd(&handle)) {
3924 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3930 static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
3931 TALLOC_CTX *mem_ctx, int argc,
3936 struct dcerpc_binding_handle *b = cli->binding_handle;
3937 const char *architecture = SPOOLSS_ARCHITECTURE_x64;
3938 struct spoolss_CorePrinterDriver core_printer_drivers;
3947 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3948 if (array == NULL) {
3949 return WERR_NOT_ENOUGH_MEMORY;
3951 array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
3952 if (array[0] == NULL) {
3953 return WERR_NOT_ENOUGH_MEMORY;
3957 array = talloc_zero_array(mem_ctx, const char *, count + 1);
3958 if (array == NULL) {
3959 return WERR_NOT_ENOUGH_MEMORY;
3961 for (i = 0; i < argc - 1; i++) {
3962 array[i] = talloc_strdup(array, argv[i + 1]);
3963 if (array[i] == NULL) {
3964 return WERR_NOT_ENOUGH_MEMORY;
3969 ok = push_reg_multi_sz(mem_ctx, &blob, array);
3971 return WERR_NOT_ENOUGH_MEMORY;
3974 status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
3975 cli->srv_name_slash,
3978 (uint16_t *)blob.data,
3980 &core_printer_drivers,
3982 if (!NT_STATUS_IS_OK(status)) {
3983 return ntstatus_to_werror(status);
3986 if (!HRES_IS_OK(result)) {
3987 return W_ERROR(WIN32_FROM_HRESULT(result));
3993 static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
3994 TALLOC_CTX *mem_ctx, int argc,
3999 struct dcerpc_binding_handle *b = cli->binding_handle;
4000 const char *servername = cli->srv_name_slash;
4001 DATA_BLOB in = data_blob_null;
4002 struct spoolss_PrinterInfo4 *info;
4003 uint32_t needed, count;
4006 printf("usage: %s [servername]\n", argv[0]);
4011 servername = argv[1];
4014 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4022 if (!NT_STATUS_IS_OK(status)) {
4023 return ntstatus_to_werror(status);
4026 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
4027 in = data_blob_talloc_zero(mem_ctx, needed);
4028 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4036 if (!NT_STATUS_IS_OK(status)) {
4037 return ntstatus_to_werror(status);
4044 static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
4045 TALLOC_CTX *mem_ctx, int argc,
4050 struct dcerpc_binding_handle *b = cli->binding_handle;
4051 const char *servername = cli->srv_name_slash;
4052 const char *printername = "Microsoft Print to PDF";
4053 const char *printserver = "samba.org";
4054 const char *provider = ""; /* refers to Win32spl.dll then */
4055 const char *composed_printername;
4058 printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
4063 servername = argv[1];
4066 printername = argv[2];
4069 printserver = argv[3];
4075 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4077 if (composed_printername == NULL) {
4078 return WERR_NOT_ENOUGH_MEMORY;
4080 status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
4082 composed_printername,
4086 if (!NT_STATUS_IS_OK(status)) {
4087 return ntstatus_to_werror(status);
4093 static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
4094 TALLOC_CTX *mem_ctx, int argc,
4099 struct dcerpc_binding_handle *b = cli->binding_handle;
4100 const char *servername = cli->srv_name_slash;
4101 const char *printername = "Microsoft Print to PDF";
4102 const char *composed_printername;
4105 printf("usage: %s [servername] [printername]\n", argv[0]);
4110 servername = argv[1];
4113 printername = argv[2];
4116 composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4118 if (composed_printername == NULL) {
4119 return WERR_NOT_ENOUGH_MEMORY;
4122 status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
4124 composed_printername,
4126 if (!NT_STATUS_IS_OK(status)) {
4127 return ntstatus_to_werror(status);
4133 /* List of commands exported by this module */
4134 struct cmd_set spoolss_commands[] = {
4141 .name = "adddriver",
4142 .returntype = RPC_RTYPE_WERROR,
4144 .wfn = cmd_spoolss_addprinterdriver,
4145 .table = &ndr_table_spoolss,
4147 .description = "Add a print driver",
4149 .use_netlogon_creds = false,
4152 .name = "addprinter",
4153 .returntype = RPC_RTYPE_WERROR,
4155 .wfn = cmd_spoolss_addprinterex,
4156 .table = &ndr_table_spoolss,
4158 .description = "Add a printer",
4162 .name = "deldriver",
4163 .returntype = RPC_RTYPE_WERROR,
4165 .wfn = cmd_spoolss_deletedriver,
4166 .table = &ndr_table_spoolss,
4168 .description = "Delete a printer driver",
4172 .name = "deldriverex",
4173 .returntype = RPC_RTYPE_WERROR,
4175 .wfn = cmd_spoolss_deletedriverex,
4176 .table = &ndr_table_spoolss,
4178 .description = "Delete a printer driver with files",
4183 .returntype = RPC_RTYPE_WERROR,
4185 .wfn = cmd_spoolss_enum_data,
4186 .table = &ndr_table_spoolss,
4188 .description = "Enumerate printer data",
4192 .name = "enumdataex",
4193 .returntype = RPC_RTYPE_WERROR,
4195 .wfn = cmd_spoolss_enum_data_ex,
4196 .table = &ndr_table_spoolss,
4198 .description = "Enumerate printer data for a key",
4203 .returntype = RPC_RTYPE_WERROR,
4205 .wfn = cmd_spoolss_enum_printerkey,
4206 .table = &ndr_table_spoolss,
4208 .description = "Enumerate printer keys",
4213 .returntype = RPC_RTYPE_WERROR,
4215 .wfn = cmd_spoolss_enum_jobs,
4216 .table = &ndr_table_spoolss,
4218 .description = "Enumerate print jobs",
4223 .returntype = RPC_RTYPE_WERROR,
4225 .wfn = cmd_spoolss_get_job,
4226 .table = &ndr_table_spoolss,
4228 .description = "Get print job",
4233 .returntype = RPC_RTYPE_WERROR,
4235 .wfn = cmd_spoolss_set_job,
4236 .table = &ndr_table_spoolss,
4238 .description = "Set print job",
4242 .name = "enumports",
4243 .returntype = RPC_RTYPE_WERROR,
4245 .wfn = cmd_spoolss_enum_ports,
4246 .table = &ndr_table_spoolss,
4248 .description = "Enumerate printer ports",
4252 .name = "enumdrivers",
4253 .returntype = RPC_RTYPE_WERROR,
4255 .wfn = cmd_spoolss_enum_drivers,
4256 .table = &ndr_table_spoolss,
4258 .description = "Enumerate installed printer drivers",
4262 .name = "enumprinters",
4263 .returntype = RPC_RTYPE_WERROR,
4265 .wfn = cmd_spoolss_enum_printers,
4266 .table = &ndr_table_spoolss,
4268 .description = "Enumerate printers",
4273 .returntype = RPC_RTYPE_WERROR,
4275 .wfn = cmd_spoolss_getprinterdata,
4276 .table = &ndr_table_spoolss,
4278 .description = "Get print driver data",
4282 .name = "getdataex",
4283 .returntype = RPC_RTYPE_WERROR,
4285 .wfn = cmd_spoolss_getprinterdataex,
4286 .table = &ndr_table_spoolss,
4288 .description = "Get printer driver data with keyname",
4292 .name = "getdriver",
4293 .returntype = RPC_RTYPE_WERROR,
4295 .wfn = cmd_spoolss_getdriver,
4296 .table = &ndr_table_spoolss,
4298 .description = "Get print driver information",
4302 .name = "getdriverdir",
4303 .returntype = RPC_RTYPE_WERROR,
4305 .wfn = cmd_spoolss_getdriverdir,
4306 .table = &ndr_table_spoolss,
4308 .description = "Get print driver upload directory",
4312 .name = "getdriverpackagepath",
4313 .returntype = RPC_RTYPE_WERROR,
4315 .wfn = cmd_spoolss_getdriverpackagepath,
4316 .table = &ndr_table_spoolss,
4318 .description = "Get print driver package download directory",
4322 .name = "getprinter",
4323 .returntype = RPC_RTYPE_WERROR,
4325 .wfn = cmd_spoolss_getprinter,
4326 .table = &ndr_table_spoolss,
4328 .description = "Get printer info",
4332 .name = "openprinter",
4333 .returntype = RPC_RTYPE_WERROR,
4335 .wfn = cmd_spoolss_open_printer,
4336 .table = &ndr_table_spoolss,
4338 .description = "Open printer handle",
4342 .name = "openprinter_ex",
4343 .returntype = RPC_RTYPE_WERROR,
4345 .wfn = cmd_spoolss_open_printer_ex,
4346 .table = &ndr_table_spoolss,
4348 .description = "Open printer handle",
4352 .name = "setdriver",
4353 .returntype = RPC_RTYPE_WERROR,
4355 .wfn = cmd_spoolss_setdriver,
4356 .table = &ndr_table_spoolss,
4358 .description = "Set printer driver",
4362 .name = "getprintprocdir",
4363 .returntype = RPC_RTYPE_WERROR,
4365 .wfn = cmd_spoolss_getprintprocdir,
4366 .table = &ndr_table_spoolss,
4368 .description = "Get print processor directory",
4373 .returntype = RPC_RTYPE_WERROR,
4375 .wfn = cmd_spoolss_addform,
4376 .table = &ndr_table_spoolss,
4378 .description = "Add form",
4383 .returntype = RPC_RTYPE_WERROR,
4385 .wfn = cmd_spoolss_setform,
4386 .table = &ndr_table_spoolss,
4388 .description = "Set form",
4393 .returntype = RPC_RTYPE_WERROR,
4395 .wfn = cmd_spoolss_getform,
4396 .table = &ndr_table_spoolss,
4398 .description = "Get form",
4402 .name = "deleteform",
4403 .returntype = RPC_RTYPE_WERROR,
4405 .wfn = cmd_spoolss_deleteform,
4406 .table = &ndr_table_spoolss,
4408 .description = "Delete form",
4412 .name = "enumforms",
4413 .returntype = RPC_RTYPE_WERROR,
4415 .wfn = cmd_spoolss_enum_forms,
4416 .table = &ndr_table_spoolss,
4418 .description = "Enumerate forms",
4422 .name = "setprinter",
4423 .returntype = RPC_RTYPE_WERROR,
4425 .wfn = cmd_spoolss_setprinter,
4426 .table = &ndr_table_spoolss,
4428 .description = "Set printer comment",
4432 .name = "setprintername",
4433 .returntype = RPC_RTYPE_WERROR,
4435 .wfn = cmd_spoolss_setprintername,
4436 .table = &ndr_table_spoolss,
4438 .description = "Set printername",
4442 .name = "setprinterdata",
4443 .returntype = RPC_RTYPE_WERROR,
4445 .wfn = cmd_spoolss_setprinterdata,
4446 .table = &ndr_table_spoolss,
4448 .description = "Set REG_SZ printer data",
4453 .returntype = RPC_RTYPE_WERROR,
4455 .wfn = cmd_spoolss_rffpcnex,
4456 .table = &ndr_table_spoolss,
4458 .description = "Rffpcnex test",
4462 .name = "printercmp",
4463 .returntype = RPC_RTYPE_WERROR,
4465 .wfn = cmd_spoolss_printercmp,
4466 .table = &ndr_table_spoolss,
4468 .description = "Printer comparison test",
4472 .name = "enumprocs",
4473 .returntype = RPC_RTYPE_WERROR,
4475 .wfn = cmd_spoolss_enum_procs,
4476 .table = &ndr_table_spoolss,
4478 .description = "Enumerate Print Processors",
4482 .name = "enumprocdatatypes",
4483 .returntype = RPC_RTYPE_WERROR,
4485 .wfn = cmd_spoolss_enum_proc_data_types,
4486 .table = &ndr_table_spoolss,
4488 .description = "Enumerate Print Processor Data Types",
4492 .name = "enummonitors",
4493 .returntype = RPC_RTYPE_WERROR,
4495 .wfn = cmd_spoolss_enum_monitors,
4496 .table = &ndr_table_spoolss,
4498 .description = "Enumerate Print Monitors",
4502 .name = "createprinteric",
4503 .returntype = RPC_RTYPE_WERROR,
4505 .wfn = cmd_spoolss_create_printer_ic,
4506 .table = &ndr_table_spoolss,
4508 .description = "Create Printer IC",
4512 .name = "playgdiscriptonprinteric",
4513 .returntype = RPC_RTYPE_WERROR,
4515 .wfn = cmd_spoolss_play_gdi_script_on_printer_ic,
4516 .table = &ndr_table_spoolss,
4518 .description = "Create Printer IC",
4522 .name = "getcoreprinterdrivers",
4523 .returntype = RPC_RTYPE_WERROR,
4525 .wfn = cmd_spoolss_get_core_printer_drivers,
4526 .table = &ndr_table_spoolss,
4528 .description = "Get CorePrinterDriver",
4532 .name = "enumpermachineconnections",
4533 .returntype = RPC_RTYPE_WERROR,
4535 .wfn = cmd_spoolss_enum_permachineconnections,
4536 .table = &ndr_table_spoolss,
4538 .description = "Enumerate Per Machine Connections",
4542 .name = "addpermachineconnection",
4543 .returntype = RPC_RTYPE_WERROR,
4545 .wfn = cmd_spoolss_add_permachineconnection,
4546 .table = &ndr_table_spoolss,
4548 .description = "Add Per Machine Connection",
4552 .name = "delpermachineconnection",
4553 .returntype = RPC_RTYPE_WERROR,
4555 .wfn = cmd_spoolss_del_permachineconnection,
4556 .table = &ndr_table_spoolss,
4558 .description = "Delete Per Machine Connection",