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 "rpc_client/cli_pipe.h"
28 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "rpc_client/cli_spoolss.h"
30 #include "rpc_client/init_spoolss.h"
32 #include "registry/reg_objects.h"
33 #include "nt_printing.h"
35 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
37 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
38 _cli->srv_name_slash, _arg); \
39 W_ERROR_HAVE_NO_MEMORY(_printername); \
42 /* The version int is used by getdrivers. Note that
43 all architecture strings that support mutliple
44 versions must be grouped together since enumdrivers
45 uses this property to prevent issuing multiple
46 enumdriver calls for the same arch */
49 static const struct print_architecture_table_node archi_table[]= {
51 {"Windows 4.0", "WIN40", 0 },
52 {"Windows NT x86", "W32X86", 2 },
53 {"Windows NT x86", "W32X86", 3 },
54 {"Windows NT R4000", "W32MIPS", 2 },
55 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
56 {"Windows NT PowerPC", "W32PPC", 2 },
57 {"Windows IA64", "IA64", 3 },
58 {"Windows x64", "x64", 3 },
65 * rpcclient module for SPOOLSS rpc pipe.
67 * This generally just parses and checks command lines, and then calls
68 * a cli_spoolss function.
71 /****************************************************************************
72 function to do the mapping between the long architecture name and
74 ****************************************************************************/
76 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
80 DEBUG(107,("Getting architecture dependant directory\n"));
83 } while ( (archi_table[i].long_archi!=NULL ) &&
84 StrCaseCmp(long_archi, archi_table[i].long_archi) );
86 if (archi_table[i].long_archi==NULL) {
87 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
91 /* this might be client code - but shouldn't this be an fstrcpy etc? */
94 DEBUGADD(108,("index: [%d]\n", i));
95 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
96 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
98 return archi_table[i].short_archi;
101 /****************************************************************************
102 ****************************************************************************/
104 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
106 int argc, const char **argv)
109 struct policy_handle hnd;
110 uint32_t access_mask = PRINTER_ALL_ACCESS;
111 struct dcerpc_binding_handle *b = cli->binding_handle;
114 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
119 sscanf(argv[2], "%x", &access_mask);
122 /* Open the printer handle */
124 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
128 if (W_ERROR_IS_OK(werror)) {
129 printf("Printer %s opened successfully\n", argv[1]);
130 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
132 if (!W_ERROR_IS_OK(werror)) {
133 printf("Error closing printer handle! (%s)\n",
134 get_dos_error_msg(werror));
141 /****************************************************************************
142 ****************************************************************************/
144 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
146 int argc, const char **argv)
149 struct policy_handle hnd;
150 uint32_t access_mask = PRINTER_ALL_ACCESS;
152 struct spoolss_DevmodeContainer devmode_ctr;
153 struct dcerpc_binding_handle *b = cli->binding_handle;
155 ZERO_STRUCT(devmode_ctr);
158 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
163 sscanf(argv[2], "%x", &access_mask);
166 /* Open the printer handle */
168 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
175 if (!NT_STATUS_IS_OK(status)) {
176 return ntstatus_to_werror(status);
178 if (W_ERROR_IS_OK(werror)) {
179 printf("Printer %s opened successfully\n", argv[1]);
180 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
182 if (!W_ERROR_IS_OK(werror)) {
183 printf("Error closing printer handle! (%s)\n",
184 get_dos_error_msg(werror));
191 /****************************************************************************
192 ****************************************************************************/
194 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
199 printf("\tprintername:[%s]\n", r->printername);
200 printf("\tservername:[%s]\n", r->servername);
201 printf("\tcjobs:[0x%x]\n", r->cjobs);
202 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
203 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
204 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
205 r->time.day, r->time.day_of_week);
206 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
207 r->time.second, r->time.millisecond);
209 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
210 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
212 printf("\tversion:[0x%x]\n", r->version);
213 printf("\tfree_build:[0x%x]\n", r->free_build);
214 printf("\tspooling:[0x%x]\n", r->spooling);
215 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
216 printf("\tsession_counter:[0x%x]\n", r->session_counter);
217 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
218 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
219 printf("\tjob_error:[0x%x]\n", r->job_error);
220 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
221 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
222 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
223 printf("\tchange_id:[0x%x]\n", r->change_id);
224 printf("\tlast_error: %s\n", win_errstr(r->last_error));
225 printf("\tstatus:[0x%x]\n", r->status);
226 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
227 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
228 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
229 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
230 printf("\tref_ic:[0x%x]\n", r->ref_ic);
231 printf("\treserved2:[0x%x]\n", r->reserved2);
232 printf("\treserved3:[0x%x]\n", r->reserved3);
237 /****************************************************************************
238 ****************************************************************************/
240 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
242 printf("\tflags:[0x%x]\n", r->flags);
243 printf("\tname:[%s]\n", r->name);
244 printf("\tdescription:[%s]\n", r->description);
245 printf("\tcomment:[%s]\n", r->comment);
250 /****************************************************************************
251 ****************************************************************************/
253 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
255 printf("\tservername:[%s]\n", r->servername);
256 printf("\tprintername:[%s]\n", r->printername);
257 printf("\tsharename:[%s]\n", r->sharename);
258 printf("\tportname:[%s]\n", r->portname);
259 printf("\tdrivername:[%s]\n", r->drivername);
260 printf("\tcomment:[%s]\n", r->comment);
261 printf("\tlocation:[%s]\n", r->location);
262 printf("\tsepfile:[%s]\n", r->sepfile);
263 printf("\tprintprocessor:[%s]\n", r->printprocessor);
264 printf("\tdatatype:[%s]\n", r->datatype);
265 printf("\tparameters:[%s]\n", r->parameters);
266 printf("\tattributes:[0x%x]\n", r->attributes);
267 printf("\tpriority:[0x%x]\n", r->priority);
268 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
269 printf("\tstarttime:[0x%x]\n", r->starttime);
270 printf("\tuntiltime:[0x%x]\n", r->untiltime);
271 printf("\tstatus:[0x%x]\n", r->status);
272 printf("\tcjobs:[0x%x]\n", r->cjobs);
273 printf("\taverageppm:[0x%x]\n", r->averageppm);
276 display_sec_desc(r->secdesc);
281 /****************************************************************************
282 ****************************************************************************/
284 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
286 display_sec_desc(r->secdesc);
291 /****************************************************************************
292 ****************************************************************************/
294 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
296 printf("\tservername:[%s]\n", r->servername);
297 printf("\tprintername:[%s]\n", r->printername);
298 printf("\tattributes:[0x%x]\n", r->attributes);
302 /****************************************************************************
303 ****************************************************************************/
305 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
307 printf("\tprintername:[%s]\n", r->printername);
308 printf("\tportname:[%s]\n", r->portname);
309 printf("\tattributes:[0x%x]\n", r->attributes);
310 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
311 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
315 /****************************************************************************
316 ****************************************************************************/
318 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
320 printf("\tstatus:[0x%x]\n", r->status);
324 /****************************************************************************
325 ****************************************************************************/
327 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
329 printf("\tguid:[%s]\n", r->guid);
330 printf("\taction:[0x%x]\n", r->action);
334 /****************************************************************************
335 ****************************************************************************/
337 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
339 int argc, const char **argv)
343 union spoolss_PrinterInfo *info;
346 uint32_t flags = PRINTER_ENUM_LOCAL;
349 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
354 level = atoi(argv[1]);
360 name = cli->srv_name_slash;
364 flags = atoi(argv[3]);
367 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
374 if (W_ERROR_IS_OK(result)) {
377 printf ("No printers returned.\n");
381 for (i = 0; i < count; i++) {
384 display_print_info0(&info[i].info0);
387 display_print_info1(&info[i].info1);
390 display_print_info2(&info[i].info2);
393 display_print_info3(&info[i].info3);
396 display_print_info4(&info[i].info4);
399 display_print_info5(&info[i].info5);
402 display_print_info6(&info[i].info6);
405 printf("unknown info level %d\n", level);
415 /****************************************************************************
416 ****************************************************************************/
418 static void display_port_info_1(struct spoolss_PortInfo1 *r)
420 printf("\tPort Name:\t[%s]\n", r->port_name);
423 /****************************************************************************
424 ****************************************************************************/
426 static void display_port_info_2(struct spoolss_PortInfo2 *r)
428 printf("\tPort Name:\t[%s]\n", r->port_name);
429 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
430 printf("\tDescription:\t[%s]\n", r->description);
431 printf("\tPort Type:\t" );
433 int comma = 0; /* hack */
435 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
439 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
440 printf( "%sWrite", comma ? ", " : "" );
443 /* These two have slightly different interpretations
444 on 95/98/ME but I'm disregarding that for now */
445 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
446 printf( "%sRedirected", comma ? ", " : "" );
449 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
450 printf( "%sNet-Attached", comma ? ", " : "" );
454 printf( "[Unset]\n" );
456 printf("\tReserved:\t[%d]\n", r->reserved);
460 /****************************************************************************
461 ****************************************************************************/
463 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
464 TALLOC_CTX *mem_ctx, int argc,
470 union spoolss_PortInfo *info;
473 printf("Usage: %s [level]\n", argv[0]);
478 level = atoi(argv[1]);
481 /* Enumerate ports */
483 result = rpccli_spoolss_enumports(cli, mem_ctx,
489 if (W_ERROR_IS_OK(result)) {
492 for (i = 0; i < count; i++) {
495 display_port_info_1(&info[i].info1);
498 display_port_info_2(&info[i].info2);
501 printf("unknown info level %d\n", level);
510 /****************************************************************************
511 ****************************************************************************/
513 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
515 int argc, const char **argv)
517 struct policy_handle pol;
520 uint32_t info_level = 2;
521 union spoolss_PrinterInfo info;
522 struct spoolss_SetPrinterInfoCtr info_ctr;
523 struct spoolss_SetPrinterInfo2 info2;
524 const char *printername, *comment = NULL;
525 struct spoolss_DevmodeContainer devmode_ctr;
526 struct sec_desc_buf secdesc_ctr;
527 struct dcerpc_binding_handle *b = cli->binding_handle;
529 if (argc == 1 || argc > 3) {
530 printf("Usage: %s printername comment\n", argv[0]);
535 /* Open a printer handle */
540 ZERO_STRUCT(devmode_ctr);
541 ZERO_STRUCT(secdesc_ctr);
543 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
545 /* get a printer handle */
546 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
550 if (!W_ERROR_IS_OK(result))
553 /* Get printer info */
554 result = rpccli_spoolss_getprinter(cli, mem_ctx,
559 if (!W_ERROR_IS_OK(result))
563 /* Modify the comment. */
564 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
565 info2.comment = comment;
568 info_ctr.info.info2 = &info2;
570 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
577 if (!NT_STATUS_IS_OK(status)) {
578 result = ntstatus_to_werror(status);
581 if (W_ERROR_IS_OK(result))
582 printf("Success in setting comment.\n");
585 if (is_valid_policy_hnd(&pol)) {
587 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
593 /****************************************************************************
594 ****************************************************************************/
596 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
598 int argc, const char **argv)
600 struct policy_handle pol;
603 uint32_t info_level = 2;
604 union spoolss_PrinterInfo info;
605 const char *printername,
606 *new_printername = NULL;
607 struct spoolss_SetPrinterInfoCtr info_ctr;
608 struct spoolss_SetPrinterInfo2 info2;
609 struct spoolss_DevmodeContainer devmode_ctr;
610 struct sec_desc_buf secdesc_ctr;
611 struct dcerpc_binding_handle *b = cli->binding_handle;
613 ZERO_STRUCT(devmode_ctr);
614 ZERO_STRUCT(secdesc_ctr);
616 if (argc == 1 || argc > 3) {
617 printf("Usage: %s printername new_printername\n", argv[0]);
622 /* Open a printer handle */
624 new_printername = argv[2];
627 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
629 /* get a printer handle */
630 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
634 if (!W_ERROR_IS_OK(result))
637 /* Get printer info */
638 result = rpccli_spoolss_getprinter(cli, mem_ctx,
643 if (!W_ERROR_IS_OK(result))
646 /* Modify the printername. */
647 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
648 info2.printername = new_printername;
651 info_ctr.info.info2 = &info2;
653 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
660 if (!NT_STATUS_IS_OK(status)) {
661 result = ntstatus_to_werror(status);
664 if (W_ERROR_IS_OK(result))
665 printf("Success in setting printername.\n");
668 if (is_valid_policy_hnd(&pol)) {
670 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
676 /****************************************************************************
677 ****************************************************************************/
679 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
681 int argc, const char **argv)
683 struct policy_handle pol;
686 const char *printername;
687 union spoolss_PrinterInfo info;
688 struct dcerpc_binding_handle *b = cli->binding_handle;
690 if (argc == 1 || argc > 3) {
691 printf("Usage: %s <printername> [level]\n", argv[0]);
695 /* Open a printer handle */
697 level = atoi(argv[2]);
700 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
702 /* get a printer handle */
704 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
706 SEC_FLAG_MAXIMUM_ALLOWED,
708 if (!W_ERROR_IS_OK(result)) {
712 /* Get printer info */
714 result = rpccli_spoolss_getprinter(cli, mem_ctx,
719 if (!W_ERROR_IS_OK(result)) {
723 /* Display printer info */
726 display_print_info0(&info.info0);
729 display_print_info1(&info.info1);
732 display_print_info2(&info.info2);
735 display_print_info3(&info.info3);
738 display_print_info4(&info.info4);
741 display_print_info5(&info.info5);
744 display_print_info6(&info.info6);
747 display_print_info7(&info.info7);
750 printf("unknown info level %d\n", level);
754 if (is_valid_policy_hnd(&pol)) {
756 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
762 /****************************************************************************
763 ****************************************************************************/
765 static void display_reg_value(struct regval_blob *value)
767 const char *text = NULL;
770 switch(regval_type(value)) {
772 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
773 *((uint32_t *) regval_data_p(value)));
776 blob = data_blob_const(regval_data_p(value), regval_size(value));
777 pull_reg_sz(talloc_tos(), &blob, &text);
778 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
781 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
783 printf("%s: REG_BINARY:", regval_name(value));
785 for (i=0; i<len; i++) {
786 if (hex[i] == '\0') {
801 blob = data_blob_const(regval_data_p(value), regval_size(value));
803 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
804 d_printf("pull_reg_multi_sz failed\n");
808 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
809 for (i=0; values[i] != NULL; i++) {
810 d_printf("%s\n", values[i]);
816 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
821 /****************************************************************************
822 ****************************************************************************/
824 static void display_printer_data(const char *v,
825 enum winreg_Type type,
830 union spoolss_PrinterData r;
831 DATA_BLOB blob = data_blob_const(data, length);
834 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
835 if (!W_ERROR_IS_OK(result)) {
841 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
844 printf("%s: REG_SZ: %s\n", v, r.string);
847 char *hex = hex_encode_talloc(NULL,
848 r.binary.data, r.binary.length);
850 printf("%s: REG_BINARY:", v);
852 for (i=0; i<len; i++) {
853 if (hex[i] == '\0') {
866 printf("%s: REG_MULTI_SZ: ", v);
867 for (i=0; r.string_array[i] != NULL; i++) {
868 printf("%s ", r.string_array[i]);
873 printf("%s: unknown type 0x%02x:\n", v, type);
878 /****************************************************************************
879 ****************************************************************************/
881 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
883 int argc, const char **argv)
885 struct policy_handle pol;
888 const char *valuename;
889 enum winreg_Type type;
892 struct dcerpc_binding_handle *b = cli->binding_handle;
895 printf("Usage: %s <printername> <valuename>\n", argv[0]);
896 printf("<printername> of . queries print server\n");
901 /* Open a printer handle */
903 if (strncmp(argv[1], ".", sizeof(".")) == 0)
904 fstrcpy(printername, cli->srv_name_slash);
906 slprintf(printername, sizeof(printername)-1, "%s\\%s",
907 cli->srv_name_slash, argv[1]);
909 /* get a printer handle */
911 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
913 SEC_FLAG_MAXIMUM_ALLOWED,
915 if (!W_ERROR_IS_OK(result))
918 /* Get printer info */
920 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
927 if (!W_ERROR_IS_OK(result))
930 /* Display printer data */
932 display_printer_data(valuename, type, data, needed);
935 if (is_valid_policy_hnd(&pol)) {
937 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
943 /****************************************************************************
944 ****************************************************************************/
946 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
948 int argc, const char **argv)
950 struct policy_handle pol;
954 const char *valuename, *keyname;
956 enum winreg_Type type;
957 uint8_t *data = NULL;
958 uint32_t offered = 0;
960 struct dcerpc_binding_handle *b = cli->binding_handle;
963 printf("Usage: %s <printername> <keyname> <valuename>\n",
965 printf("<printername> of . queries print server\n");
971 /* Open a printer handle */
973 if (strncmp(argv[1], ".", sizeof(".")) == 0)
974 fstrcpy(printername, cli->srv_name_slash);
976 slprintf(printername, sizeof(printername)-1, "%s\\%s",
977 cli->srv_name_slash, argv[1]);
979 /* get a printer handle */
981 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
983 SEC_FLAG_MAXIMUM_ALLOWED,
985 if (!W_ERROR_IS_OK(result))
988 /* Get printer info */
990 data = talloc_zero_array(mem_ctx, uint8_t, offered);
995 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1004 if (!NT_STATUS_IS_OK(status)) {
1005 result = ntstatus_to_werror(status);
1008 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1010 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1014 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1025 if (!NT_STATUS_IS_OK(status)) {
1026 result = ntstatus_to_werror(status);
1030 if (!W_ERROR_IS_OK(result))
1033 /* Display printer data */
1035 display_printer_data(valuename, type, data, needed);
1039 if (is_valid_policy_hnd(&pol)) {
1041 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1047 /****************************************************************************
1048 ****************************************************************************/
1050 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1056 printf("Printer Driver Info 1:\n");
1057 printf("\tDriver Name: [%s]\n", r->driver_name);
1061 /****************************************************************************
1062 ****************************************************************************/
1064 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1070 printf("Printer Driver Info 2:\n");
1071 printf("\tVersion: [%x]\n", r->version);
1072 printf("\tDriver Name: [%s]\n", r->driver_name);
1073 printf("\tArchitecture: [%s]\n", r->architecture);
1074 printf("\tDriver Path: [%s]\n", r->driver_path);
1075 printf("\tDatafile: [%s]\n", r->data_file);
1076 printf("\tConfigfile: [%s]\n", r->config_file);
1080 /****************************************************************************
1081 ****************************************************************************/
1083 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1091 printf("Printer Driver Info 3:\n");
1092 printf("\tVersion: [%x]\n", r->version);
1093 printf("\tDriver Name: [%s]\n", r->driver_name);
1094 printf("\tArchitecture: [%s]\n", r->architecture);
1095 printf("\tDriver Path: [%s]\n", r->driver_path);
1096 printf("\tDatafile: [%s]\n", r->data_file);
1097 printf("\tConfigfile: [%s]\n", r->config_file);
1098 printf("\tHelpfile: [%s]\n", r->help_file);
1100 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1101 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1104 printf("\tMonitorname: [%s]\n", r->monitor_name);
1105 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1109 /****************************************************************************
1110 ****************************************************************************/
1112 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1120 printf("Printer Driver Info 4:\n");
1121 printf("\tVersion: [%x]\n", r->version);
1122 printf("\tDriver Name: [%s]\n", r->driver_name);
1123 printf("\tArchitecture: [%s]\n", r->architecture);
1124 printf("\tDriver Path: [%s]\n", r->driver_path);
1125 printf("\tDatafile: [%s]\n", r->data_file);
1126 printf("\tConfigfile: [%s]\n", r->config_file);
1127 printf("\tHelpfile: [%s]\n", r->help_file);
1129 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1130 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1133 printf("\tMonitorname: [%s]\n", r->monitor_name);
1134 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1136 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1137 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1142 /****************************************************************************
1143 ****************************************************************************/
1145 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1151 printf("Printer Driver Info 5:\n");
1152 printf("\tVersion: [%x]\n", r->version);
1153 printf("\tDriver Name: [%s]\n", r->driver_name);
1154 printf("\tArchitecture: [%s]\n", r->architecture);
1155 printf("\tDriver Path: [%s]\n", r->driver_path);
1156 printf("\tDatafile: [%s]\n", r->data_file);
1157 printf("\tConfigfile: [%s]\n", r->config_file);
1158 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1159 printf("\tConfig Version: [0x%x]\n", r->config_version);
1160 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1164 /****************************************************************************
1165 ****************************************************************************/
1167 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1175 printf("Printer Driver Info 6:\n");
1176 printf("\tVersion: [%x]\n", r->version);
1177 printf("\tDriver Name: [%s]\n", r->driver_name);
1178 printf("\tArchitecture: [%s]\n", r->architecture);
1179 printf("\tDriver Path: [%s]\n", r->driver_path);
1180 printf("\tDatafile: [%s]\n", r->data_file);
1181 printf("\tConfigfile: [%s]\n", r->config_file);
1182 printf("\tHelpfile: [%s]\n", r->help_file);
1184 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1185 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1188 printf("\tMonitorname: [%s]\n", r->monitor_name);
1189 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1191 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1192 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1195 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1196 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1197 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1198 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1199 printf("\tHardware ID: [%s]\n", r->hardware_id);
1200 printf("\tProvider: [%s]\n", r->provider);
1205 /****************************************************************************
1206 ****************************************************************************/
1208 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1216 printf("Printer Driver Info 8:\n");
1217 printf("\tVersion: [%x]\n", r->version);
1218 printf("\tDriver Name: [%s]\n", r->driver_name);
1219 printf("\tArchitecture: [%s]\n", r->architecture);
1220 printf("\tDriver Path: [%s]\n", r->driver_path);
1221 printf("\tDatafile: [%s]\n", r->data_file);
1222 printf("\tConfigfile: [%s]\n", r->config_file);
1223 printf("\tHelpfile: [%s]\n", r->help_file);
1224 printf("\tMonitorname: [%s]\n", r->monitor_name);
1225 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1227 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1228 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1231 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1232 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1235 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1236 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1237 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1238 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1239 printf("\tHardware ID: [%s]\n", r->hardware_id);
1240 printf("\tProvider: [%s]\n", r->provider);
1241 printf("\tPrint Processor: [%s]\n", r->print_processor);
1242 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1243 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1244 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1246 printf("\tInf Path: [%s]\n", r->inf_path);
1247 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1248 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1249 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1251 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1252 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1253 (long long unsigned int)r->min_inbox_driver_ver_version);
1258 /****************************************************************************
1259 ****************************************************************************/
1261 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1262 TALLOC_CTX *mem_ctx,
1263 int argc, const char **argv)
1265 struct policy_handle pol;
1268 const char *printername;
1270 bool success = false;
1271 union spoolss_DriverInfo info;
1272 uint32_t server_major_version;
1273 uint32_t server_minor_version;
1274 struct dcerpc_binding_handle *b = cli->binding_handle;
1276 if ((argc == 1) || (argc > 3)) {
1277 printf("Usage: %s <printername> [level]\n", argv[0]);
1281 /* get the arguments need to open the printer handle */
1283 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1286 level = atoi(argv[2]);
1289 /* Open a printer handle */
1291 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1295 if (!W_ERROR_IS_OK(werror)) {
1296 printf("Error opening printer handle for %s!\n", printername);
1300 /* loop through and print driver info level for each architecture */
1302 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1304 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1306 archi_table[i].long_archi,
1309 archi_table[i].version,
1312 &server_major_version,
1313 &server_minor_version);
1314 if (!W_ERROR_IS_OK(werror)) {
1318 /* need at least one success */
1322 printf("\n[%s]\n", archi_table[i].long_archi);
1326 display_print_driver1(&info.info1);
1329 display_print_driver2(&info.info2);
1332 display_print_driver3(&info.info3);
1335 display_print_driver4(&info.info4);
1338 display_print_driver5(&info.info5);
1341 display_print_driver6(&info.info6);
1344 display_print_driver8(&info.info8);
1347 printf("unknown info level %d\n", level);
1354 if (is_valid_policy_hnd(&pol)) {
1356 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1366 /****************************************************************************
1367 ****************************************************************************/
1369 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1370 TALLOC_CTX *mem_ctx,
1371 const char *architecture,
1376 union spoolss_DriverInfo *info = NULL;
1379 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1380 cli->srv_name_slash,
1387 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1388 printf("Server does not support environment [%s]\n",
1397 if (!W_ERROR_IS_OK(werror)) {
1398 printf("Error getting driver for environment [%s] - %s\n",
1399 architecture, win_errstr(werror));
1403 printf("\n[%s]\n", architecture);
1407 for (j=0; j < count; j++) {
1408 display_print_driver1(&info[j].info1);
1412 for (j=0; j < count; j++) {
1413 display_print_driver2(&info[j].info2);
1417 for (j=0; j < count; j++) {
1418 display_print_driver3(&info[j].info3);
1422 for (j=0; j < count; j++) {
1423 display_print_driver4(&info[j].info4);
1427 for (j=0; j < count; j++) {
1428 display_print_driver5(&info[j].info5);
1432 for (j=0; j < count; j++) {
1433 display_print_driver6(&info[j].info6);
1437 for (j=0; j < count; j++) {
1438 display_print_driver8(&info[j].info8);
1442 printf("unknown info level %d\n", level);
1443 return WERR_UNKNOWN_LEVEL;
1449 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1450 TALLOC_CTX *mem_ctx,
1451 int argc, const char **argv)
1453 WERROR werror = WERR_OK;
1456 const char *architecture = NULL;
1459 printf("Usage: enumdrivers [level] [architecture]\n");
1464 level = atoi(argv[1]);
1468 architecture = argv[2];
1472 return enum_driver_by_architecture(cli, mem_ctx,
1477 /* loop through and print driver info level for each architecture */
1478 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1479 /* check to see if we already asked for this architecture string */
1481 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1485 werror = enum_driver_by_architecture(cli, mem_ctx,
1486 archi_table[i].long_archi,
1488 if (!W_ERROR_IS_OK(werror)) {
1496 /****************************************************************************
1497 ****************************************************************************/
1499 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1501 printf("\tDirectory Name:[%s]\n", r->directory_name);
1504 /****************************************************************************
1505 ****************************************************************************/
1507 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1508 TALLOC_CTX *mem_ctx,
1509 int argc, const char **argv)
1513 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1516 union spoolss_DriverDirectoryInfo info;
1518 struct dcerpc_binding_handle *b = cli->binding_handle;
1521 printf("Usage: %s [environment]\n", argv[0]);
1525 /* Get the arguments need to open the printer handle */
1531 /* Get the directory. Only use Info level 1 */
1533 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1534 cli->srv_name_slash,
1542 if (!NT_STATUS_IS_OK(status)) {
1543 return ntstatus_to_werror(status);
1545 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1547 buffer = data_blob_talloc_zero(mem_ctx, needed);
1549 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1550 cli->srv_name_slash,
1558 if (!NT_STATUS_IS_OK(status)) {
1559 return ntstatus_to_werror(status);
1563 if (W_ERROR_IS_OK(result)) {
1564 display_printdriverdir_1(&info.info1);
1570 /****************************************************************************
1571 ****************************************************************************/
1573 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1574 struct spoolss_AddDriverInfo3 *info,
1580 for (i=0; archi_table[i].long_archi != NULL; i++)
1582 if (strcmp(arch, archi_table[i].short_archi) == 0)
1584 info->version = archi_table[i].version;
1585 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1590 if (archi_table[i].long_archi == NULL)
1592 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1599 /**************************************************************************
1600 wrapper for strtok to get the next parameter from a delimited list.
1601 Needed to handle the empty parameter string denoted by "NULL"
1602 *************************************************************************/
1604 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1605 const char *delim, const char **dest,
1610 /* get the next token */
1611 ptr = strtok_r(str, delim, saveptr);
1613 /* a string of 'NULL' is used to represent an empty
1614 parameter because two consecutive delimiters
1615 will not return an empty string. See man strtok(3)
1617 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1622 *dest = talloc_strdup(mem_ctx, ptr);
1628 /********************************************************************************
1629 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1630 string in the form of
1631 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1632 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1633 <Default Data Type>:<Comma Separated list of Files>
1634 *******************************************************************************/
1636 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1641 char *saveptr = NULL;
1642 struct spoolss_StringArray *deps;
1643 const char **file_array = NULL;
1646 /* fill in the UNISTR fields */
1647 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1648 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1649 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1650 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1653 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1655 /* <Comma Separated List of Dependent Files> */
1656 /* save the beginning of the string */
1657 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1660 /* begin to strip out each filename */
1661 str = strtok_r(str, ",", &saveptr);
1663 /* no dependent files, we are done */
1668 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1673 while (str != NULL) {
1674 add_string_to_array(deps, str, &file_array, &count);
1675 str = strtok_r(NULL, ",", &saveptr);
1678 deps->string = talloc_zero_array(deps, const char *, count + 1);
1679 if (!deps->string) {
1683 for (i=0; i < count; i++) {
1684 deps->string[i] = file_array[i];
1687 r->dependent_files = deps;
1692 /****************************************************************************
1693 ****************************************************************************/
1695 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1696 TALLOC_CTX *mem_ctx,
1697 int argc, const char **argv)
1702 struct spoolss_AddDriverInfoCtr info_ctr;
1703 struct spoolss_AddDriverInfo3 info3;
1706 struct dcerpc_binding_handle *b = cli->binding_handle;
1708 /* parse the command arguments */
1709 if (argc != 3 && argc != 4)
1711 printf ("Usage: %s <Environment> \\\n", argv[0]);
1712 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1713 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1714 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1715 printf ("\t[version]\n");
1720 /* Fill in the spoolss_AddDriverInfo3 struct */
1723 arch = cmd_spoolss_get_short_archi(argv[1]);
1725 printf ("Error Unknown architechture [%s]\n", argv[1]);
1726 return WERR_INVALID_PARAM;
1729 set_drv_info_3_env(mem_ctx, &info3, arch);
1731 driver_args = talloc_strdup( mem_ctx, argv[2] );
1732 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1734 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1735 return WERR_INVALID_PARAM;
1738 /* if printer driver version specified, override the default version
1739 * used by the architecture. This allows installation of Windows
1740 * 2000 (version 3) printer drivers. */
1743 info3.version = atoi(argv[3]);
1747 info_ctr.level = level;
1748 info_ctr.info.info3 = &info3;
1750 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1751 cli->srv_name_slash,
1754 if (!NT_STATUS_IS_OK(status)) {
1755 return ntstatus_to_werror(status);
1757 if (W_ERROR_IS_OK(result)) {
1758 printf ("Printer Driver %s successfully installed.\n",
1766 /****************************************************************************
1767 ****************************************************************************/
1769 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1770 TALLOC_CTX *mem_ctx,
1771 int argc, const char **argv)
1774 struct spoolss_SetPrinterInfoCtr info_ctr;
1775 struct spoolss_SetPrinterInfo2 info2;
1777 /* parse the command arguments */
1780 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1784 /* Fill in the DRIVER_INFO_2 struct */
1787 info2.printername = argv[1];
1788 info2.drivername = argv[3];
1789 info2.sharename = argv[2];
1790 info2.portname = argv[4];
1791 info2.comment = "Created by rpcclient";
1792 info2.printprocessor = "winprint";
1793 info2.datatype = "RAW";
1794 info2.devmode_ptr = 0;
1795 info2.secdesc_ptr = 0;
1796 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1798 info2.defaultpriority = 0;
1799 info2.starttime = 0;
1800 info2.untiltime = 0;
1802 /* These three fields must not be used by AddPrinter()
1803 as defined in the MS Platform SDK documentation..
1807 info2.averageppm = 0;
1811 info_ctr.info.info2 = &info2;
1813 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1815 if (W_ERROR_IS_OK(result))
1816 printf ("Printer %s successfully installed.\n", argv[1]);
1821 /****************************************************************************
1822 ****************************************************************************/
1824 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1825 TALLOC_CTX *mem_ctx,
1826 int argc, const char **argv)
1828 struct policy_handle pol;
1832 const char *printername;
1833 union spoolss_PrinterInfo info;
1834 struct spoolss_SetPrinterInfoCtr info_ctr;
1835 struct spoolss_SetPrinterInfo2 info2;
1836 struct spoolss_DevmodeContainer devmode_ctr;
1837 struct sec_desc_buf secdesc_ctr;
1838 struct dcerpc_binding_handle *b = cli->binding_handle;
1840 ZERO_STRUCT(devmode_ctr);
1841 ZERO_STRUCT(secdesc_ctr);
1843 /* parse the command arguments */
1846 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1850 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1852 /* Get a printer handle */
1854 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1858 if (!W_ERROR_IS_OK(result))
1861 /* Get printer info */
1863 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1868 if (!W_ERROR_IS_OK(result)) {
1869 printf ("Unable to retrieve printer information!\n");
1873 /* Set the printer driver */
1875 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1876 info2.drivername = argv[2];
1879 info_ctr.info.info2 = &info2;
1881 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1888 if (!NT_STATUS_IS_OK(status)) {
1889 result = ntstatus_to_werror(status);
1892 if (!W_ERROR_IS_OK(result)) {
1893 printf("SetPrinter call failed!\n");
1897 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1902 if (is_valid_policy_hnd(&pol)) {
1904 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1911 /****************************************************************************
1912 ****************************************************************************/
1914 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1915 TALLOC_CTX *mem_ctx,
1916 int argc, const char **argv)
1918 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1920 struct dcerpc_binding_handle *b = cli->binding_handle;
1925 const char *arch = NULL;
1926 uint32_t delete_flags = 0;
1928 /* parse the command arguments */
1929 if (argc < 2 || argc > 4) {
1930 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1937 vers = atoi (argv[3]);
1940 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1943 /* delete the driver for all architectures */
1944 for (i=0; archi_table[i].long_archi; i++) {
1946 if (arch && !strequal( archi_table[i].long_archi, arch))
1949 if (vers >= 0 && archi_table[i].version != vers)
1952 /* make the call to remove the driver */
1953 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1954 cli->srv_name_slash,
1955 archi_table[i].long_archi,
1958 archi_table[i].version,
1960 if (!NT_STATUS_IS_OK(status)) {
1961 return ntstatus_to_werror(status);
1963 if ( !W_ERROR_IS_OK(result) )
1965 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1966 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1967 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1972 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1973 archi_table[i].long_archi, archi_table[i].version);
1982 /****************************************************************************
1983 ****************************************************************************/
1985 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1986 TALLOC_CTX *mem_ctx,
1987 int argc, const char **argv)
1989 WERROR result = WERR_OK;
1992 struct dcerpc_binding_handle *b = cli->binding_handle;
1994 /* parse the command arguments */
1996 printf ("Usage: %s <driver>\n", argv[0]);
2000 /* delete the driver for all architectures */
2001 for (i=0; archi_table[i].long_archi; i++) {
2004 /* make the call to remove the driver */
2005 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2006 cli->srv_name_slash,
2007 archi_table[i].long_archi,
2010 if (!NT_STATUS_IS_OK(status)) {
2011 result = ntstatus_to_werror(status);
2014 if ( !W_ERROR_IS_OK(result) ) {
2015 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2016 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2017 argv[1], archi_table[i].long_archi,
2018 win_errstr(result));
2021 printf ("Driver %s removed for arch [%s].\n", argv[1],
2022 archi_table[i].long_archi);
2029 /****************************************************************************
2030 ****************************************************************************/
2032 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2033 TALLOC_CTX *mem_ctx,
2034 int argc, const char **argv)
2038 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2041 union spoolss_PrintProcessorDirectoryInfo info;
2043 struct dcerpc_binding_handle *b = cli->binding_handle;
2045 /* parse the command arguments */
2047 printf ("Usage: %s [environment]\n", argv[0]);
2052 environment = argv[1];
2055 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2056 cli->srv_name_slash,
2064 if (!NT_STATUS_IS_OK(status)) {
2065 return ntstatus_to_werror(status);
2067 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2069 buffer = data_blob_talloc_zero(mem_ctx, needed);
2071 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2072 cli->srv_name_slash,
2080 if (!NT_STATUS_IS_OK(status)) {
2081 return ntstatus_to_werror(status);
2085 if (W_ERROR_IS_OK(result)) {
2086 printf("%s\n", info.info1.directory_name);
2092 /****************************************************************************
2093 ****************************************************************************/
2095 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2096 int argc, const char **argv)
2098 struct policy_handle handle;
2101 const char *printername;
2102 union spoolss_AddFormInfo info;
2103 struct spoolss_AddFormInfo1 info1;
2104 struct spoolss_AddFormInfo2 info2;
2106 struct dcerpc_binding_handle *b = cli->binding_handle;
2108 /* Parse the command arguments */
2110 if (argc < 3 || argc > 5) {
2111 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2115 /* Get a printer handle */
2117 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2119 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2123 if (!W_ERROR_IS_OK(werror))
2126 /* Dummy up some values for the form data */
2129 level = atoi(argv[3]);
2134 info1.flags = SPOOLSS_FORM_USER;
2135 info1.form_name = argv[2];
2136 info1.size.width = 100;
2137 info1.size.height = 100;
2138 info1.area.left = 0;
2139 info1.area.top = 10;
2140 info1.area.right = 20;
2141 info1.area.bottom = 30;
2143 info.info1 = &info1;
2147 info2.flags = SPOOLSS_FORM_USER;
2148 info2.form_name = argv[2];
2149 info2.size.width = 100;
2150 info2.size.height = 100;
2151 info2.area.left = 0;
2152 info2.area.top = 10;
2153 info2.area.right = 20;
2154 info2.area.bottom = 30;
2155 info2.keyword = argv[2];
2156 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2157 info2.mui_dll = NULL;
2158 info2.ressource_id = 0;
2159 info2.display_name = argv[2];
2162 info.info2 = &info2;
2166 werror = WERR_INVALID_PARAM;
2173 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2178 if (!NT_STATUS_IS_OK(status)) {
2179 werror = ntstatus_to_werror(status);
2183 if (is_valid_policy_hnd(&handle)) {
2185 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2191 /****************************************************************************
2192 ****************************************************************************/
2194 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2195 int argc, const char **argv)
2197 struct policy_handle handle;
2200 const char *printername;
2201 union spoolss_AddFormInfo info;
2202 struct spoolss_AddFormInfo1 info1;
2203 struct dcerpc_binding_handle *b = cli->binding_handle;
2205 /* Parse the command arguments */
2208 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2212 /* Get a printer handle */
2214 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2216 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2218 SEC_FLAG_MAXIMUM_ALLOWED,
2220 if (!W_ERROR_IS_OK(werror))
2223 /* Dummy up some values for the form data */
2225 info1.flags = SPOOLSS_FORM_PRINTER;
2226 info1.size.width = 100;
2227 info1.size.height = 100;
2228 info1.area.left = 0;
2229 info1.area.top = 1000;
2230 info1.area.right = 2000;
2231 info1.area.bottom = 3000;
2232 info1.form_name = argv[2];
2234 info.info1 = &info1;
2238 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2244 if (!NT_STATUS_IS_OK(status)) {
2245 werror = ntstatus_to_werror(status);
2249 if (is_valid_policy_hnd(&handle)) {
2251 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2257 /****************************************************************************
2258 ****************************************************************************/
2260 static const char *get_form_flag(int form_flag)
2262 switch (form_flag) {
2263 case SPOOLSS_FORM_USER:
2265 case SPOOLSS_FORM_BUILTIN:
2266 return "FORM_BUILTIN";
2267 case SPOOLSS_FORM_PRINTER:
2268 return "FORM_PRINTER";
2274 /****************************************************************************
2275 ****************************************************************************/
2277 static void display_form_info1(struct spoolss_FormInfo1 *r)
2280 "\tflag: %s (%d)\n" \
2281 "\twidth: %d, length: %d\n" \
2282 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2283 r->form_name, get_form_flag(r->flags), r->flags,
2284 r->size.width, r->size.height,
2285 r->area.left, r->area.right,
2286 r->area.top, r->area.bottom);
2289 /****************************************************************************
2290 ****************************************************************************/
2292 static void display_form_info2(struct spoolss_FormInfo2 *r)
2295 "\tflag: %s (%d)\n" \
2296 "\twidth: %d, length: %d\n" \
2297 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2298 r->form_name, get_form_flag(r->flags), r->flags,
2299 r->size.width, r->size.height,
2300 r->area.left, r->area.right,
2301 r->area.top, r->area.bottom);
2302 printf("\tkeyword: %s\n", r->keyword);
2303 printf("\tstring_type: 0x%08x\n", r->string_type);
2304 printf("\tmui_dll: %s\n", r->mui_dll);
2305 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2306 printf("\tdisplay_name: %s\n", r->display_name);
2307 printf("\tlang_id: %d\n", r->lang_id);
2311 /****************************************************************************
2312 ****************************************************************************/
2314 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2315 int argc, const char **argv)
2317 struct policy_handle handle;
2320 const char *printername;
2322 uint32_t offered = 0;
2323 union spoolss_FormInfo info;
2326 struct dcerpc_binding_handle *b = cli->binding_handle;
2328 /* Parse the command arguments */
2330 if (argc < 3 || argc > 5) {
2331 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2335 /* Get a printer handle */
2337 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2339 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2341 SEC_FLAG_MAXIMUM_ALLOWED,
2343 if (!W_ERROR_IS_OK(werror))
2347 level = atoi(argv[3]);
2352 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2361 if (!NT_STATUS_IS_OK(status)) {
2362 werror = ntstatus_to_werror(status);
2365 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2366 buffer = data_blob_talloc_zero(mem_ctx, needed);
2368 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2377 if (!NT_STATUS_IS_OK(status)) {
2378 werror = ntstatus_to_werror(status);
2383 if (!W_ERROR_IS_OK(werror)) {
2389 display_form_info1(&info.info1);
2392 display_form_info2(&info.info2);
2397 if (is_valid_policy_hnd(&handle)) {
2399 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2405 /****************************************************************************
2406 ****************************************************************************/
2408 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2409 TALLOC_CTX *mem_ctx, int argc,
2412 struct policy_handle handle;
2415 const char *printername;
2416 struct dcerpc_binding_handle *b = cli->binding_handle;
2418 /* Parse the command arguments */
2421 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2425 /* Get a printer handle */
2427 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2429 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2431 SEC_FLAG_MAXIMUM_ALLOWED,
2433 if (!W_ERROR_IS_OK(werror))
2436 /* Delete the form */
2438 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2442 if (!NT_STATUS_IS_OK(status)) {
2443 werror = ntstatus_to_werror(status);
2448 if (is_valid_policy_hnd(&handle)) {
2450 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2456 /****************************************************************************
2457 ****************************************************************************/
2459 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2460 TALLOC_CTX *mem_ctx, int argc,
2463 struct policy_handle handle;
2465 const char *printername;
2466 uint32_t num_forms, level = 1, i;
2467 union spoolss_FormInfo *forms;
2468 struct dcerpc_binding_handle *b = cli->binding_handle;
2470 /* Parse the command arguments */
2472 if (argc < 2 || argc > 4) {
2473 printf ("Usage: %s <printer> [level]\n", argv[0]);
2477 /* Get a printer handle */
2479 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2481 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2483 SEC_FLAG_MAXIMUM_ALLOWED,
2485 if (!W_ERROR_IS_OK(werror))
2489 level = atoi(argv[2]);
2492 /* Enumerate forms */
2494 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2501 if (!W_ERROR_IS_OK(werror))
2504 /* Display output */
2506 for (i = 0; i < num_forms; i++) {
2509 display_form_info1(&forms[i].info1);
2512 display_form_info2(&forms[i].info2);
2518 if (is_valid_policy_hnd(&handle)) {
2520 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2526 /****************************************************************************
2527 ****************************************************************************/
2529 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2530 TALLOC_CTX *mem_ctx,
2531 int argc, const char **argv)
2535 const char *printername;
2536 struct policy_handle pol;
2537 union spoolss_PrinterInfo info;
2538 enum winreg_Type type;
2539 union spoolss_PrinterData data;
2541 struct dcerpc_binding_handle *b = cli->binding_handle;
2543 /* parse the command arguments */
2545 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2546 " <value> <data>\n",
2551 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2555 if (strequal(argv[2], "string")) {
2559 if (strequal(argv[2], "binary")) {
2563 if (strequal(argv[2], "dword")) {
2567 if (strequal(argv[2], "multistring")) {
2568 type = REG_MULTI_SZ;
2571 if (type == REG_NONE) {
2572 printf("Unknown data type: %s\n", argv[2]);
2573 result = WERR_INVALID_PARAM;
2577 /* get a printer handle */
2579 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2581 SEC_FLAG_MAXIMUM_ALLOWED,
2583 if (!W_ERROR_IS_OK(result)) {
2587 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2592 if (!W_ERROR_IS_OK(result)) {
2596 printf("%s\n", current_timestring(mem_ctx, true));
2597 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2599 /* Set the printer data */
2603 data.string = talloc_strdup(mem_ctx, argv[4]);
2604 W_ERROR_HAVE_NO_MEMORY(data.string);
2607 data.value = strtoul(argv[4], NULL, 10);
2610 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2612 case REG_MULTI_SZ: {
2614 const char **strings = NULL;
2616 for (i=4; i<argc; i++) {
2617 if (strcmp(argv[i], "NULL") == 0) {
2620 if (!add_string_to_array(mem_ctx, argv[i],
2623 result = WERR_NOMEM;
2627 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2628 if (!data.string_array) {
2629 result = WERR_NOMEM;
2632 for (i=0; i < num_strings; i++) {
2633 data.string_array[i] = strings[i];
2638 printf("Unknown data type: %s\n", argv[2]);
2639 result = WERR_INVALID_PARAM;
2643 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2644 if (!W_ERROR_IS_OK(result)) {
2648 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2650 argv[3], /* value_name */
2655 if (!NT_STATUS_IS_OK(status)) {
2656 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2657 result = ntstatus_to_werror(status);
2660 if (!W_ERROR_IS_OK(result)) {
2661 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2664 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2666 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2671 if (!W_ERROR_IS_OK(result)) {
2675 printf("%s\n", current_timestring(mem_ctx, true));
2676 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2680 if (is_valid_policy_hnd(&pol)) {
2682 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2688 /****************************************************************************
2689 ****************************************************************************/
2691 static void display_job_info1(struct spoolss_JobInfo1 *r)
2693 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2694 r->user_name, r->document_name, r->text_status, r->pages_printed,
2698 /****************************************************************************
2699 ****************************************************************************/
2701 static void display_job_info2(struct spoolss_JobInfo2 *r)
2703 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2704 r->position, r->job_id,
2705 r->user_name, r->document_name, r->text_status, r->pages_printed,
2706 r->total_pages, r->size);
2709 /****************************************************************************
2710 ****************************************************************************/
2712 static void display_job_info3(struct spoolss_JobInfo3 *r)
2714 printf("jobid[%d], next_jobid[%d]\n",
2715 r->job_id, r->next_job_id);
2718 /****************************************************************************
2719 ****************************************************************************/
2721 static void display_job_info4(struct spoolss_JobInfo4 *r)
2723 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2724 r->position, r->job_id,
2725 r->user_name, r->document_name, r->text_status, r->pages_printed,
2726 r->total_pages, r->size, r->size_high);
2729 /****************************************************************************
2730 ****************************************************************************/
2732 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2733 TALLOC_CTX *mem_ctx, int argc,
2737 uint32_t level = 1, count, i;
2738 const char *printername;
2739 struct policy_handle hnd;
2740 union spoolss_JobInfo *info;
2741 struct dcerpc_binding_handle *b = cli->binding_handle;
2743 if (argc < 2 || argc > 3) {
2744 printf("Usage: %s printername [level]\n", argv[0]);
2749 level = atoi(argv[2]);
2752 /* Open printer handle */
2754 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2756 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2758 SEC_FLAG_MAXIMUM_ALLOWED,
2760 if (!W_ERROR_IS_OK(result))
2763 /* Enumerate ports */
2765 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2773 if (!W_ERROR_IS_OK(result)) {
2777 for (i = 0; i < count; i++) {
2780 display_job_info1(&info[i].info1);
2783 display_job_info2(&info[i].info2);
2786 d_printf("unknown info level %d\n", level);
2792 if (is_valid_policy_hnd(&hnd)) {
2794 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2800 /****************************************************************************
2801 ****************************************************************************/
2803 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2804 TALLOC_CTX *mem_ctx, int argc,
2808 const char *printername;
2809 struct policy_handle hnd;
2812 union spoolss_JobInfo info;
2813 struct dcerpc_binding_handle *b = cli->binding_handle;
2815 if (argc < 3 || argc > 4) {
2816 printf("Usage: %s printername job_id [level]\n", argv[0]);
2820 job_id = atoi(argv[2]);
2823 level = atoi(argv[3]);
2826 /* Open printer handle */
2828 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2830 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2832 SEC_FLAG_MAXIMUM_ALLOWED,
2834 if (!W_ERROR_IS_OK(result)) {
2838 /* Enumerate ports */
2840 result = rpccli_spoolss_getjob(cli, mem_ctx,
2847 if (!W_ERROR_IS_OK(result)) {
2853 display_job_info1(&info.info1);
2856 display_job_info2(&info.info2);
2859 display_job_info3(&info.info3);
2862 display_job_info4(&info.info4);
2865 d_printf("unknown info level %d\n", level);
2870 if (is_valid_policy_hnd(&hnd)) {
2872 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2878 /****************************************************************************
2879 ****************************************************************************/
2883 enum spoolss_JobControl val;
2885 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2886 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2887 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2888 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2889 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2890 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2891 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2892 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2893 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2896 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2900 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2901 if (strequal(cmdvals[i].name, cmd)) {
2902 return cmdvals[i].val;
2905 return (enum spoolss_JobControl)atoi(cmd);
2908 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2909 TALLOC_CTX *mem_ctx, int argc,
2914 const char *printername;
2915 struct policy_handle hnd;
2917 enum spoolss_JobControl command;
2918 struct dcerpc_binding_handle *b = cli->binding_handle;
2921 printf("Usage: %s printername job_id command\n", argv[0]);
2922 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2923 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2927 job_id = atoi(argv[2]);
2928 command = parse_setjob_command(argv[3]);
2930 /* Open printer handle */
2932 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2934 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2936 SEC_FLAG_MAXIMUM_ALLOWED,
2938 if (!W_ERROR_IS_OK(result)) {
2944 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2950 if (!NT_STATUS_IS_OK(status)) {
2951 result = ntstatus_to_werror(status);
2954 if (!W_ERROR_IS_OK(result)) {
2959 if (is_valid_policy_hnd(&hnd)) {
2961 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2967 /****************************************************************************
2968 ****************************************************************************/
2970 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2971 TALLOC_CTX *mem_ctx, int argc,
2976 const char *printername;
2977 struct policy_handle hnd;
2978 uint32_t value_needed;
2979 enum winreg_Type type;
2980 uint32_t data_needed;
2981 struct dcerpc_binding_handle *b = cli->binding_handle;
2982 struct spoolss_EnumPrinterData r;
2985 printf("Usage: %s printername\n", argv[0]);
2989 /* Open printer handle */
2991 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2993 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2995 SEC_FLAG_MAXIMUM_ALLOWED,
2997 if (!W_ERROR_IS_OK(result)) {
3001 /* Enumerate data */
3004 r.in.enum_index = 0;
3005 r.in.value_offered = 0;
3006 r.in.data_offered = 0;
3007 r.out.value_name = NULL;
3008 r.out.value_needed = &value_needed;
3011 r.out.data_needed = &data_needed;
3013 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3014 if (!NT_STATUS_IS_OK(status)) {
3015 result = ntstatus_to_werror(status);
3019 if (!W_ERROR_IS_OK(r.out.result)) {
3020 result = r.out.result;
3024 r.in.data_offered = *r.out.data_needed;
3025 r.in.value_offered = *r.out.value_needed;
3026 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3027 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3031 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3032 if (!NT_STATUS_IS_OK(status)) {
3033 result = ntstatus_to_werror(status);
3037 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3045 struct regval_blob *v;
3047 v = regval_compose(talloc_tos(),
3053 result = WERR_NOMEM;
3057 display_reg_value(v);
3061 } while (W_ERROR_IS_OK(r.out.result));
3064 if (is_valid_policy_hnd(&hnd)) {
3066 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3072 /****************************************************************************
3073 ****************************************************************************/
3075 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3076 TALLOC_CTX *mem_ctx, int argc,
3081 const char *printername;
3082 struct policy_handle hnd;
3084 struct spoolss_PrinterEnumValues *info;
3085 struct dcerpc_binding_handle *b = cli->binding_handle;
3088 printf("Usage: %s printername <keyname>\n", argv[0]);
3092 /* Open printer handle */
3094 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3096 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3098 SEC_FLAG_MAXIMUM_ALLOWED,
3100 if (!W_ERROR_IS_OK(result)) {
3104 /* Enumerate subkeys */
3106 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3112 if (!W_ERROR_IS_OK(result)) {
3116 for (i=0; i < count; i++) {
3117 display_printer_data(info[i].value_name,
3120 info[i].data->length);
3124 if (is_valid_policy_hnd(&hnd)) {
3126 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3132 /****************************************************************************
3133 ****************************************************************************/
3135 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3136 TALLOC_CTX *mem_ctx, int argc,
3140 const char *printername;
3141 const char *keyname = NULL;
3142 struct policy_handle hnd;
3143 const char **key_buffer = NULL;
3145 uint32_t offered = 0;
3146 struct dcerpc_binding_handle *b = cli->binding_handle;
3148 if (argc < 2 || argc > 4) {
3149 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3160 offered = atoi(argv[3]);
3163 /* Open printer handle */
3165 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3167 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3169 SEC_FLAG_MAXIMUM_ALLOWED,
3171 if (!W_ERROR_IS_OK(result)) {
3175 /* Enumerate subkeys */
3177 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3183 if (!W_ERROR_IS_OK(result)) {
3187 for (i=0; key_buffer && key_buffer[i]; i++) {
3188 printf("%s\n", key_buffer[i]);
3193 if (is_valid_policy_hnd(&hnd)) {
3195 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3201 /****************************************************************************
3202 ****************************************************************************/
3204 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3205 TALLOC_CTX *mem_ctx, int argc,
3208 const char *printername;
3209 const char *clientname;
3210 struct policy_handle hnd;
3213 struct spoolss_NotifyOption option;
3214 struct dcerpc_binding_handle *b = cli->binding_handle;
3217 printf("Usage: %s printername\n", argv[0]);
3224 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3226 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3228 SEC_FLAG_MAXIMUM_ALLOWED,
3230 if (!W_ERROR_IS_OK(result)) {
3231 printf("Error opening %s\n", argv[1]);
3235 /* Create spool options */
3240 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3241 if (option.types == NULL) {
3242 result = WERR_NOMEM;
3246 option.types[0].type = PRINTER_NOTIFY_TYPE;
3247 option.types[0].count = 1;
3248 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3249 if (option.types[0].fields == NULL) {
3250 result = WERR_NOMEM;
3253 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3255 option.types[1].type = JOB_NOTIFY_TYPE;
3256 option.types[1].count = 1;
3257 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3258 if (option.types[1].fields == NULL) {
3259 result = WERR_NOMEM;
3262 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3264 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3266 result = WERR_NOMEM;
3272 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3280 if (!NT_STATUS_IS_OK(status)) {
3281 result = ntstatus_to_werror(status);
3284 if (!W_ERROR_IS_OK(result)) {
3285 printf("Error rffpcnex %s\n", argv[1]);
3290 if (is_valid_policy_hnd(&hnd)) {
3292 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3298 /****************************************************************************
3299 ****************************************************************************/
3301 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3302 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3304 union spoolss_PrinterInfo info1, info2;
3306 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3308 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3309 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3314 if ( !W_ERROR_IS_OK(werror) ) {
3315 printf("failed (%s)\n", win_errstr(werror));
3316 talloc_destroy(mem_ctx);
3321 printf("Retrieving printer properties for %s...", cli2->desthost);
3322 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3327 if ( !W_ERROR_IS_OK(werror) ) {
3328 printf("failed (%s)\n", win_errstr(werror));
3329 talloc_destroy(mem_ctx);
3334 talloc_destroy(mem_ctx);
3339 /****************************************************************************
3340 ****************************************************************************/
3342 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3343 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3345 union spoolss_PrinterInfo info1, info2;
3347 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3348 struct security_descriptor *sd1, *sd2;
3352 printf("Retrieving printer security for %s...", cli1->desthost);
3353 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3358 if ( !W_ERROR_IS_OK(werror) ) {
3359 printf("failed (%s)\n", win_errstr(werror));
3365 printf("Retrieving printer security for %s...", cli2->desthost);
3366 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3371 if ( !W_ERROR_IS_OK(werror) ) {
3372 printf("failed (%s)\n", win_errstr(werror));
3381 sd1 = info1.info3.secdesc;
3382 sd2 = info2.info3.secdesc;
3384 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3385 printf("NULL secdesc!\n");
3390 if (!security_descriptor_equal( sd1, sd2 ) ) {
3391 printf("Security Descriptors *not* equal!\n");
3396 printf("Security descriptors match\n");
3399 talloc_destroy(mem_ctx);
3404 /****************************************************************************
3405 ****************************************************************************/
3407 extern struct user_auth_info *rpcclient_auth_info;
3409 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3410 TALLOC_CTX *mem_ctx, int argc,
3413 const char *printername;
3414 char *printername_path = NULL;
3415 struct cli_state *cli_server2 = NULL;
3416 struct rpc_pipe_client *cli2 = NULL;
3417 struct policy_handle hPrinter1, hPrinter2;
3422 printf("Usage: %s <printer> <server>\n", argv[0]);
3426 printername = argv[1];
3428 /* first get the connection to the remote server */
3430 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3433 get_cmdline_auth_info_username(rpcclient_auth_info),
3435 get_cmdline_auth_info_password(rpcclient_auth_info),
3436 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3437 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3439 if ( !NT_STATUS_IS_OK(nt_status) )
3440 return WERR_GENERAL_FAILURE;
3442 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3444 if (!NT_STATUS_IS_OK(nt_status)) {
3445 printf("failed to open spoolss pipe on server %s (%s)\n",
3446 argv[2], nt_errstr(nt_status));
3447 return WERR_GENERAL_FAILURE;
3450 /* now open up both printers */
3452 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3454 printf("Opening %s...", printername_path);
3456 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3460 if ( !W_ERROR_IS_OK(werror) ) {
3461 printf("failed (%s)\n", win_errstr(werror));
3466 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3468 printf("Opening %s...", printername_path);
3469 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3473 if ( !W_ERROR_IS_OK(werror) ) {
3474 printf("failed (%s)\n", win_errstr(werror));
3479 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3480 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3482 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3489 printf("Closing printers...");
3492 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3493 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3497 /* close the second remote connection */
3499 cli_shutdown( cli_server2 );
3503 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3505 printf("print_processor_name: %s\n", r->print_processor_name);
3508 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3509 TALLOC_CTX *mem_ctx, int argc,
3513 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3514 uint32_t num_procs, level = 1, i;
3515 union spoolss_PrintProcessorInfo *procs;
3517 /* Parse the command arguments */
3519 if (argc < 1 || argc > 4) {
3520 printf ("Usage: %s [environment] [level]\n", argv[0]);
3525 environment = argv[1];
3529 level = atoi(argv[2]);
3532 /* Enumerate Print Processors */
3534 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3535 cli->srv_name_slash,
3541 if (!W_ERROR_IS_OK(werror))
3544 /* Display output */
3546 for (i = 0; i < num_procs; i++) {
3549 display_proc_info1(&procs[i].info1);
3558 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3560 printf("name_array: %s\n", r->name_array);
3563 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3564 TALLOC_CTX *mem_ctx, int argc,
3568 const char *print_processor_name = "winprint";
3569 uint32_t num_procs, level = 1, i;
3570 union spoolss_PrintProcDataTypesInfo *procs;
3572 /* Parse the command arguments */
3574 if (argc < 1 || argc > 4) {
3575 printf ("Usage: %s [environment] [level]\n", argv[0]);
3580 print_processor_name = argv[1];
3584 level = atoi(argv[2]);
3587 /* Enumerate Print Processor Data Types */
3589 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3590 cli->srv_name_slash,
3591 print_processor_name,
3596 if (!W_ERROR_IS_OK(werror))
3599 /* Display output */
3601 for (i = 0; i < num_procs; i++) {
3604 display_proc_data_types_info1(&procs[i].info1);
3613 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3615 printf("monitor_name: %s\n", r->monitor_name);
3618 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3620 printf("monitor_name: %s\n", r->monitor_name);
3621 printf("environment: %s\n", r->environment);
3622 printf("dll_name: %s\n", r->dll_name);
3625 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3626 TALLOC_CTX *mem_ctx, int argc,
3630 uint32_t count, level = 1, i;
3631 union spoolss_MonitorInfo *info;
3633 /* Parse the command arguments */
3636 printf("Usage: %s [level]\n", argv[0]);
3641 level = atoi(argv[1]);
3644 /* Enumerate Print Monitors */
3646 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3647 cli->srv_name_slash,
3652 if (!W_ERROR_IS_OK(werror)) {
3656 /* Display output */
3658 for (i = 0; i < count; i++) {
3661 display_monitor1(&info[i].info1);
3664 display_monitor2(&info[i].info2);
3673 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3674 TALLOC_CTX *mem_ctx, int argc,
3679 struct policy_handle handle, gdi_handle;
3680 const char *printername;
3681 struct spoolss_DevmodeContainer devmode_ctr;
3682 struct dcerpc_binding_handle *b = cli->binding_handle;
3684 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3686 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3688 SEC_FLAG_MAXIMUM_ALLOWED,
3690 if (!W_ERROR_IS_OK(result)) {
3694 ZERO_STRUCT(devmode_ctr);
3696 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3701 if (!NT_STATUS_IS_OK(status)) {
3702 result = ntstatus_to_werror(status);
3705 if (!W_ERROR_IS_OK(result)) {
3710 if (is_valid_policy_hnd(&gdi_handle)) {
3712 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3714 if (is_valid_policy_hnd(&handle)) {
3716 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3722 /* List of commands exported by this module */
3723 struct cmd_set spoolss_commands[] = {
3727 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3728 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3729 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3730 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3731 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3732 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3733 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3734 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3735 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3736 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3737 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3738 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3739 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3740 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3741 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3742 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3743 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3744 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3745 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3746 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3747 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3748 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3749 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3750 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3751 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3752 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3753 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3754 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3755 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3756 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3757 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3758 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3759 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3760 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3761 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3762 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },