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"
34 #include "../libcli/security/display_sec.h"
35 #include "../libcli/security/security_descriptor.h"
36 #include "../libcli/registry/util_reg.h"
38 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
40 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
41 _cli->srv_name_slash, _arg); \
42 W_ERROR_HAVE_NO_MEMORY(_printername); \
45 /* The version int is used by getdrivers. Note that
46 all architecture strings that support mutliple
47 versions must be grouped together since enumdrivers
48 uses this property to prevent issuing multiple
49 enumdriver calls for the same arch */
52 static const struct print_architecture_table_node archi_table[]= {
54 {"Windows 4.0", "WIN40", 0 },
55 {"Windows NT x86", "W32X86", 2 },
56 {"Windows NT x86", "W32X86", 3 },
57 {"Windows NT R4000", "W32MIPS", 2 },
58 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
59 {"Windows NT PowerPC", "W32PPC", 2 },
60 {"Windows IA64", "IA64", 3 },
61 {"Windows x64", "x64", 3 },
68 * rpcclient module for SPOOLSS rpc pipe.
70 * This generally just parses and checks command lines, and then calls
71 * a cli_spoolss function.
74 /****************************************************************************
75 function to do the mapping between the long architecture name and
77 ****************************************************************************/
79 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
83 DEBUG(107,("Getting architecture dependent directory\n"));
86 } while ( (archi_table[i].long_archi!=NULL ) &&
87 StrCaseCmp(long_archi, archi_table[i].long_archi) );
89 if (archi_table[i].long_archi==NULL) {
90 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
94 /* this might be client code - but shouldn't this be an fstrcpy etc? */
97 DEBUGADD(108,("index: [%d]\n", i));
98 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
99 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
101 return archi_table[i].short_archi;
104 /****************************************************************************
105 ****************************************************************************/
107 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
109 int argc, const char **argv)
112 struct policy_handle hnd;
113 uint32_t access_mask = PRINTER_ALL_ACCESS;
114 struct dcerpc_binding_handle *b = cli->binding_handle;
117 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
122 sscanf(argv[2], "%x", &access_mask);
125 /* Open the printer handle */
127 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
131 if (W_ERROR_IS_OK(werror)) {
132 printf("Printer %s opened successfully\n", argv[1]);
133 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
135 if (!W_ERROR_IS_OK(werror)) {
136 printf("Error closing printer handle! (%s)\n",
137 get_dos_error_msg(werror));
144 /****************************************************************************
145 ****************************************************************************/
147 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
149 int argc, const char **argv)
152 struct policy_handle hnd;
153 uint32_t access_mask = PRINTER_ALL_ACCESS;
155 struct spoolss_DevmodeContainer devmode_ctr;
156 struct dcerpc_binding_handle *b = cli->binding_handle;
158 ZERO_STRUCT(devmode_ctr);
161 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
166 sscanf(argv[2], "%x", &access_mask);
169 /* Open the printer handle */
171 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
178 if (!NT_STATUS_IS_OK(status)) {
179 return ntstatus_to_werror(status);
181 if (W_ERROR_IS_OK(werror)) {
182 printf("Printer %s opened successfully\n", argv[1]);
183 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
185 if (!W_ERROR_IS_OK(werror)) {
186 printf("Error closing printer handle! (%s)\n",
187 get_dos_error_msg(werror));
194 /****************************************************************************
195 ****************************************************************************/
197 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
202 printf("\tprintername:[%s]\n", r->printername);
203 printf("\tservername:[%s]\n", r->servername);
204 printf("\tcjobs:[0x%x]\n", r->cjobs);
205 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
206 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
207 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
208 r->time.day, r->time.day_of_week);
209 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
210 r->time.second, r->time.millisecond);
212 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
213 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
215 printf("\tversion:[0x%x]\n", r->version);
216 printf("\tfree_build:[0x%x]\n", r->free_build);
217 printf("\tspooling:[0x%x]\n", r->spooling);
218 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
219 printf("\tsession_counter:[0x%x]\n", r->session_counter);
220 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
221 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
222 printf("\tjob_error:[0x%x]\n", r->job_error);
223 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
224 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
225 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
226 printf("\tchange_id:[0x%x]\n", r->change_id);
227 printf("\tlast_error: %s\n", win_errstr(r->last_error));
228 printf("\tstatus:[0x%x]\n", r->status);
229 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
230 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
231 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
232 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
233 printf("\tref_ic:[0x%x]\n", r->ref_ic);
234 printf("\treserved2:[0x%x]\n", r->reserved2);
235 printf("\treserved3:[0x%x]\n", r->reserved3);
240 /****************************************************************************
241 ****************************************************************************/
243 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
245 printf("\tflags:[0x%x]\n", r->flags);
246 printf("\tname:[%s]\n", r->name);
247 printf("\tdescription:[%s]\n", r->description);
248 printf("\tcomment:[%s]\n", r->comment);
253 /****************************************************************************
254 ****************************************************************************/
256 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
258 printf("\tservername:[%s]\n", r->servername);
259 printf("\tprintername:[%s]\n", r->printername);
260 printf("\tsharename:[%s]\n", r->sharename);
261 printf("\tportname:[%s]\n", r->portname);
262 printf("\tdrivername:[%s]\n", r->drivername);
263 printf("\tcomment:[%s]\n", r->comment);
264 printf("\tlocation:[%s]\n", r->location);
265 printf("\tsepfile:[%s]\n", r->sepfile);
266 printf("\tprintprocessor:[%s]\n", r->printprocessor);
267 printf("\tdatatype:[%s]\n", r->datatype);
268 printf("\tparameters:[%s]\n", r->parameters);
269 printf("\tattributes:[0x%x]\n", r->attributes);
270 printf("\tpriority:[0x%x]\n", r->priority);
271 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
272 printf("\tstarttime:[0x%x]\n", r->starttime);
273 printf("\tuntiltime:[0x%x]\n", r->untiltime);
274 printf("\tstatus:[0x%x]\n", r->status);
275 printf("\tcjobs:[0x%x]\n", r->cjobs);
276 printf("\taverageppm:[0x%x]\n", r->averageppm);
279 display_sec_desc(r->secdesc);
284 /****************************************************************************
285 ****************************************************************************/
287 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
289 display_sec_desc(r->secdesc);
294 /****************************************************************************
295 ****************************************************************************/
297 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
299 printf("\tservername:[%s]\n", r->servername);
300 printf("\tprintername:[%s]\n", r->printername);
301 printf("\tattributes:[0x%x]\n", r->attributes);
305 /****************************************************************************
306 ****************************************************************************/
308 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
310 printf("\tprintername:[%s]\n", r->printername);
311 printf("\tportname:[%s]\n", r->portname);
312 printf("\tattributes:[0x%x]\n", r->attributes);
313 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
314 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
318 /****************************************************************************
319 ****************************************************************************/
321 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
323 printf("\tstatus:[0x%x]\n", r->status);
327 /****************************************************************************
328 ****************************************************************************/
330 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
332 printf("\tguid:[%s]\n", r->guid);
333 printf("\taction:[0x%x]\n", r->action);
337 /****************************************************************************
338 ****************************************************************************/
340 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
342 int argc, const char **argv)
346 union spoolss_PrinterInfo *info;
349 uint32_t flags = PRINTER_ENUM_LOCAL;
352 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
357 level = atoi(argv[1]);
363 name = cli->srv_name_slash;
367 flags = atoi(argv[3]);
370 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
377 if (W_ERROR_IS_OK(result)) {
380 printf ("No printers returned.\n");
384 for (i = 0; i < count; i++) {
387 display_print_info0(&info[i].info0);
390 display_print_info1(&info[i].info1);
393 display_print_info2(&info[i].info2);
396 display_print_info3(&info[i].info3);
399 display_print_info4(&info[i].info4);
402 display_print_info5(&info[i].info5);
405 display_print_info6(&info[i].info6);
408 printf("unknown info level %d\n", level);
418 /****************************************************************************
419 ****************************************************************************/
421 static void display_port_info_1(struct spoolss_PortInfo1 *r)
423 printf("\tPort Name:\t[%s]\n", r->port_name);
426 /****************************************************************************
427 ****************************************************************************/
429 static void display_port_info_2(struct spoolss_PortInfo2 *r)
431 printf("\tPort Name:\t[%s]\n", r->port_name);
432 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
433 printf("\tDescription:\t[%s]\n", r->description);
434 printf("\tPort Type:\t" );
436 int comma = 0; /* hack */
438 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
442 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
443 printf( "%sWrite", comma ? ", " : "" );
446 /* These two have slightly different interpretations
447 on 95/98/ME but I'm disregarding that for now */
448 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
449 printf( "%sRedirected", comma ? ", " : "" );
452 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
453 printf( "%sNet-Attached", comma ? ", " : "" );
457 printf( "[Unset]\n" );
459 printf("\tReserved:\t[%d]\n", r->reserved);
463 /****************************************************************************
464 ****************************************************************************/
466 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
467 TALLOC_CTX *mem_ctx, int argc,
473 union spoolss_PortInfo *info;
476 printf("Usage: %s [level]\n", argv[0]);
481 level = atoi(argv[1]);
484 /* Enumerate ports */
486 result = rpccli_spoolss_enumports(cli, mem_ctx,
492 if (W_ERROR_IS_OK(result)) {
495 for (i = 0; i < count; i++) {
498 display_port_info_1(&info[i].info1);
501 display_port_info_2(&info[i].info2);
504 printf("unknown info level %d\n", level);
513 /****************************************************************************
514 ****************************************************************************/
516 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
518 int argc, const char **argv)
520 struct policy_handle pol;
523 uint32_t info_level = 2;
524 union spoolss_PrinterInfo info;
525 struct spoolss_SetPrinterInfoCtr info_ctr;
526 struct spoolss_SetPrinterInfo2 info2;
527 const char *printername, *comment = NULL;
528 struct spoolss_DevmodeContainer devmode_ctr;
529 struct sec_desc_buf secdesc_ctr;
530 struct dcerpc_binding_handle *b = cli->binding_handle;
532 if (argc == 1 || argc > 3) {
533 printf("Usage: %s printername comment\n", argv[0]);
538 /* Open a printer handle */
543 ZERO_STRUCT(devmode_ctr);
544 ZERO_STRUCT(secdesc_ctr);
546 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
548 /* get a printer handle */
549 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
553 if (!W_ERROR_IS_OK(result))
556 /* Get printer info */
557 result = rpccli_spoolss_getprinter(cli, mem_ctx,
562 if (!W_ERROR_IS_OK(result))
566 /* Modify the comment. */
567 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
568 info2.comment = comment;
571 info_ctr.info.info2 = &info2;
573 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
580 if (!NT_STATUS_IS_OK(status)) {
581 result = ntstatus_to_werror(status);
584 if (W_ERROR_IS_OK(result))
585 printf("Success in setting comment.\n");
588 if (is_valid_policy_hnd(&pol)) {
590 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
596 /****************************************************************************
597 ****************************************************************************/
599 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
601 int argc, const char **argv)
603 struct policy_handle pol;
606 uint32_t info_level = 2;
607 union spoolss_PrinterInfo info;
608 const char *printername,
609 *new_printername = NULL;
610 struct spoolss_SetPrinterInfoCtr info_ctr;
611 struct spoolss_SetPrinterInfo2 info2;
612 struct spoolss_DevmodeContainer devmode_ctr;
613 struct sec_desc_buf secdesc_ctr;
614 struct dcerpc_binding_handle *b = cli->binding_handle;
616 ZERO_STRUCT(devmode_ctr);
617 ZERO_STRUCT(secdesc_ctr);
619 if (argc == 1 || argc > 3) {
620 printf("Usage: %s printername new_printername\n", argv[0]);
625 /* Open a printer handle */
627 new_printername = argv[2];
630 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
632 /* get a printer handle */
633 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
637 if (!W_ERROR_IS_OK(result))
640 /* Get printer info */
641 result = rpccli_spoolss_getprinter(cli, mem_ctx,
646 if (!W_ERROR_IS_OK(result))
649 /* Modify the printername. */
650 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
651 info2.printername = new_printername;
654 info_ctr.info.info2 = &info2;
656 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
663 if (!NT_STATUS_IS_OK(status)) {
664 result = ntstatus_to_werror(status);
667 if (W_ERROR_IS_OK(result))
668 printf("Success in setting printername.\n");
671 if (is_valid_policy_hnd(&pol)) {
673 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
679 /****************************************************************************
680 ****************************************************************************/
682 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
684 int argc, const char **argv)
686 struct policy_handle pol;
689 const char *printername;
690 union spoolss_PrinterInfo info;
691 struct dcerpc_binding_handle *b = cli->binding_handle;
693 if (argc == 1 || argc > 3) {
694 printf("Usage: %s <printername> [level]\n", argv[0]);
698 /* Open a printer handle */
700 level = atoi(argv[2]);
703 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
705 /* get a printer handle */
707 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
709 SEC_FLAG_MAXIMUM_ALLOWED,
711 if (!W_ERROR_IS_OK(result)) {
715 /* Get printer info */
717 result = rpccli_spoolss_getprinter(cli, mem_ctx,
722 if (!W_ERROR_IS_OK(result)) {
726 /* Display printer info */
729 display_print_info0(&info.info0);
732 display_print_info1(&info.info1);
735 display_print_info2(&info.info2);
738 display_print_info3(&info.info3);
741 display_print_info4(&info.info4);
744 display_print_info5(&info.info5);
747 display_print_info6(&info.info6);
750 display_print_info7(&info.info7);
753 printf("unknown info level %d\n", level);
757 if (is_valid_policy_hnd(&pol)) {
759 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
765 /****************************************************************************
766 ****************************************************************************/
768 static void display_reg_value(struct regval_blob *value)
770 const char *text = NULL;
773 switch(regval_type(value)) {
775 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
776 *((uint32_t *) regval_data_p(value)));
779 blob = data_blob_const(regval_data_p(value), regval_size(value));
780 pull_reg_sz(talloc_tos(), &blob, &text);
781 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
784 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
786 printf("%s: REG_BINARY:", regval_name(value));
788 for (i=0; i<len; i++) {
789 if (hex[i] == '\0') {
804 blob = data_blob_const(regval_data_p(value), regval_size(value));
806 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
807 d_printf("pull_reg_multi_sz failed\n");
811 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
812 for (i=0; values[i] != NULL; i++) {
813 d_printf("%s\n", values[i]);
819 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
824 /****************************************************************************
825 ****************************************************************************/
827 static void display_printer_data(const char *v,
828 enum winreg_Type type,
833 union spoolss_PrinterData r;
834 DATA_BLOB blob = data_blob_const(data, length);
837 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
838 if (!W_ERROR_IS_OK(result)) {
844 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
847 printf("%s: REG_SZ: %s\n", v, r.string);
850 char *hex = hex_encode_talloc(NULL,
851 r.binary.data, r.binary.length);
853 printf("%s: REG_BINARY:", v);
855 for (i=0; i<len; i++) {
856 if (hex[i] == '\0') {
869 printf("%s: REG_MULTI_SZ: ", v);
870 for (i=0; r.string_array[i] != NULL; i++) {
871 printf("%s ", r.string_array[i]);
876 printf("%s: unknown type 0x%02x:\n", v, type);
881 /****************************************************************************
882 ****************************************************************************/
884 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
886 int argc, const char **argv)
888 struct policy_handle pol;
891 const char *valuename;
892 enum winreg_Type type;
895 struct dcerpc_binding_handle *b = cli->binding_handle;
898 printf("Usage: %s <printername> <valuename>\n", argv[0]);
899 printf("<printername> of . queries print server\n");
904 /* Open a printer handle */
906 if (strncmp(argv[1], ".", sizeof(".")) == 0)
907 fstrcpy(printername, cli->srv_name_slash);
909 slprintf(printername, sizeof(printername)-1, "%s\\%s",
910 cli->srv_name_slash, argv[1]);
912 /* get a printer handle */
914 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
916 SEC_FLAG_MAXIMUM_ALLOWED,
918 if (!W_ERROR_IS_OK(result))
921 /* Get printer info */
923 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
930 if (!W_ERROR_IS_OK(result))
933 /* Display printer data */
935 display_printer_data(valuename, type, data, needed);
938 if (is_valid_policy_hnd(&pol)) {
940 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
946 /****************************************************************************
947 ****************************************************************************/
949 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
951 int argc, const char **argv)
953 struct policy_handle pol;
957 const char *valuename, *keyname;
959 enum winreg_Type type;
960 uint8_t *data = NULL;
961 uint32_t offered = 0;
963 struct dcerpc_binding_handle *b = cli->binding_handle;
966 printf("Usage: %s <printername> <keyname> <valuename>\n",
968 printf("<printername> of . queries print server\n");
974 /* Open a printer handle */
976 if (strncmp(argv[1], ".", sizeof(".")) == 0)
977 fstrcpy(printername, cli->srv_name_slash);
979 slprintf(printername, sizeof(printername)-1, "%s\\%s",
980 cli->srv_name_slash, argv[1]);
982 /* get a printer handle */
984 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
986 SEC_FLAG_MAXIMUM_ALLOWED,
988 if (!W_ERROR_IS_OK(result))
991 /* Get printer info */
993 data = talloc_zero_array(mem_ctx, uint8_t, offered);
998 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1007 if (!NT_STATUS_IS_OK(status)) {
1008 result = ntstatus_to_werror(status);
1011 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1013 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1017 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1028 if (!NT_STATUS_IS_OK(status)) {
1029 result = ntstatus_to_werror(status);
1033 if (!W_ERROR_IS_OK(result))
1036 /* Display printer data */
1038 display_printer_data(valuename, type, data, needed);
1042 if (is_valid_policy_hnd(&pol)) {
1044 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1050 /****************************************************************************
1051 ****************************************************************************/
1053 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1059 printf("Printer Driver Info 1:\n");
1060 printf("\tDriver Name: [%s]\n", r->driver_name);
1064 /****************************************************************************
1065 ****************************************************************************/
1067 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1073 printf("Printer Driver Info 2:\n");
1074 printf("\tVersion: [%x]\n", r->version);
1075 printf("\tDriver Name: [%s]\n", r->driver_name);
1076 printf("\tArchitecture: [%s]\n", r->architecture);
1077 printf("\tDriver Path: [%s]\n", r->driver_path);
1078 printf("\tDatafile: [%s]\n", r->data_file);
1079 printf("\tConfigfile: [%s]\n", r->config_file);
1083 /****************************************************************************
1084 ****************************************************************************/
1086 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1094 printf("Printer Driver Info 3:\n");
1095 printf("\tVersion: [%x]\n", r->version);
1096 printf("\tDriver Name: [%s]\n", r->driver_name);
1097 printf("\tArchitecture: [%s]\n", r->architecture);
1098 printf("\tDriver Path: [%s]\n", r->driver_path);
1099 printf("\tDatafile: [%s]\n", r->data_file);
1100 printf("\tConfigfile: [%s]\n", r->config_file);
1101 printf("\tHelpfile: [%s]\n", r->help_file);
1103 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1104 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1107 printf("\tMonitorname: [%s]\n", r->monitor_name);
1108 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1112 /****************************************************************************
1113 ****************************************************************************/
1115 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1123 printf("Printer Driver Info 4:\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);
1139 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1140 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1145 /****************************************************************************
1146 ****************************************************************************/
1148 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1154 printf("Printer Driver Info 5:\n");
1155 printf("\tVersion: [%x]\n", r->version);
1156 printf("\tDriver Name: [%s]\n", r->driver_name);
1157 printf("\tArchitecture: [%s]\n", r->architecture);
1158 printf("\tDriver Path: [%s]\n", r->driver_path);
1159 printf("\tDatafile: [%s]\n", r->data_file);
1160 printf("\tConfigfile: [%s]\n", r->config_file);
1161 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1162 printf("\tConfig Version: [0x%x]\n", r->config_version);
1163 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1167 /****************************************************************************
1168 ****************************************************************************/
1170 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1178 printf("Printer Driver Info 6:\n");
1179 printf("\tVersion: [%x]\n", r->version);
1180 printf("\tDriver Name: [%s]\n", r->driver_name);
1181 printf("\tArchitecture: [%s]\n", r->architecture);
1182 printf("\tDriver Path: [%s]\n", r->driver_path);
1183 printf("\tDatafile: [%s]\n", r->data_file);
1184 printf("\tConfigfile: [%s]\n", r->config_file);
1185 printf("\tHelpfile: [%s]\n", r->help_file);
1187 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1188 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1191 printf("\tMonitorname: [%s]\n", r->monitor_name);
1192 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1194 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1195 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1198 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1199 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1200 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1201 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1202 printf("\tHardware ID: [%s]\n", r->hardware_id);
1203 printf("\tProvider: [%s]\n", r->provider);
1208 /****************************************************************************
1209 ****************************************************************************/
1211 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1219 printf("Printer Driver Info 8:\n");
1220 printf("\tVersion: [%x]\n", r->version);
1221 printf("\tDriver Name: [%s]\n", r->driver_name);
1222 printf("\tArchitecture: [%s]\n", r->architecture);
1223 printf("\tDriver Path: [%s]\n", r->driver_path);
1224 printf("\tDatafile: [%s]\n", r->data_file);
1225 printf("\tConfigfile: [%s]\n", r->config_file);
1226 printf("\tHelpfile: [%s]\n", r->help_file);
1227 printf("\tMonitorname: [%s]\n", r->monitor_name);
1228 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1230 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1231 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1234 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1235 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1238 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1239 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1240 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1241 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1242 printf("\tHardware ID: [%s]\n", r->hardware_id);
1243 printf("\tProvider: [%s]\n", r->provider);
1244 printf("\tPrint Processor: [%s]\n", r->print_processor);
1245 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1246 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1247 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1249 printf("\tInf Path: [%s]\n", r->inf_path);
1250 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1251 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1252 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1254 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1255 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1256 (long long unsigned int)r->min_inbox_driver_ver_version);
1261 /****************************************************************************
1262 ****************************************************************************/
1264 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1265 TALLOC_CTX *mem_ctx,
1266 int argc, const char **argv)
1268 struct policy_handle pol;
1271 const char *printername;
1273 bool success = false;
1274 union spoolss_DriverInfo info;
1275 uint32_t server_major_version;
1276 uint32_t server_minor_version;
1277 struct dcerpc_binding_handle *b = cli->binding_handle;
1279 if ((argc == 1) || (argc > 3)) {
1280 printf("Usage: %s <printername> [level]\n", argv[0]);
1284 /* get the arguments need to open the printer handle */
1286 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1289 level = atoi(argv[2]);
1292 /* Open a printer handle */
1294 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1298 if (!W_ERROR_IS_OK(werror)) {
1299 printf("Error opening printer handle for %s!\n", printername);
1303 /* loop through and print driver info level for each architecture */
1305 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1307 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1309 archi_table[i].long_archi,
1312 archi_table[i].version,
1315 &server_major_version,
1316 &server_minor_version);
1317 if (!W_ERROR_IS_OK(werror)) {
1321 /* need at least one success */
1325 printf("\n[%s]\n", archi_table[i].long_archi);
1329 display_print_driver1(&info.info1);
1332 display_print_driver2(&info.info2);
1335 display_print_driver3(&info.info3);
1338 display_print_driver4(&info.info4);
1341 display_print_driver5(&info.info5);
1344 display_print_driver6(&info.info6);
1347 display_print_driver8(&info.info8);
1350 printf("unknown info level %d\n", level);
1357 if (is_valid_policy_hnd(&pol)) {
1359 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1369 /****************************************************************************
1370 ****************************************************************************/
1372 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1373 TALLOC_CTX *mem_ctx,
1374 const char *architecture,
1379 union spoolss_DriverInfo *info = NULL;
1382 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1383 cli->srv_name_slash,
1390 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1391 printf("Server does not support environment [%s]\n",
1400 if (!W_ERROR_IS_OK(werror)) {
1401 printf("Error getting driver for environment [%s] - %s\n",
1402 architecture, win_errstr(werror));
1406 printf("\n[%s]\n", architecture);
1410 for (j=0; j < count; j++) {
1411 display_print_driver1(&info[j].info1);
1415 for (j=0; j < count; j++) {
1416 display_print_driver2(&info[j].info2);
1420 for (j=0; j < count; j++) {
1421 display_print_driver3(&info[j].info3);
1425 for (j=0; j < count; j++) {
1426 display_print_driver4(&info[j].info4);
1430 for (j=0; j < count; j++) {
1431 display_print_driver5(&info[j].info5);
1435 for (j=0; j < count; j++) {
1436 display_print_driver6(&info[j].info6);
1440 for (j=0; j < count; j++) {
1441 display_print_driver8(&info[j].info8);
1445 printf("unknown info level %d\n", level);
1446 return WERR_UNKNOWN_LEVEL;
1452 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1453 TALLOC_CTX *mem_ctx,
1454 int argc, const char **argv)
1456 WERROR werror = WERR_OK;
1459 const char *architecture = NULL;
1462 printf("Usage: enumdrivers [level] [architecture]\n");
1467 level = atoi(argv[1]);
1471 architecture = argv[2];
1475 return enum_driver_by_architecture(cli, mem_ctx,
1480 /* loop through and print driver info level for each architecture */
1481 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1482 /* check to see if we already asked for this architecture string */
1484 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1488 werror = enum_driver_by_architecture(cli, mem_ctx,
1489 archi_table[i].long_archi,
1491 if (!W_ERROR_IS_OK(werror)) {
1499 /****************************************************************************
1500 ****************************************************************************/
1502 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1504 printf("\tDirectory Name:[%s]\n", r->directory_name);
1507 /****************************************************************************
1508 ****************************************************************************/
1510 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1511 TALLOC_CTX *mem_ctx,
1512 int argc, const char **argv)
1516 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1519 union spoolss_DriverDirectoryInfo info;
1521 struct dcerpc_binding_handle *b = cli->binding_handle;
1524 printf("Usage: %s [environment]\n", argv[0]);
1528 /* Get the arguments need to open the printer handle */
1534 /* Get the directory. Only use Info level 1 */
1536 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1537 cli->srv_name_slash,
1545 if (!NT_STATUS_IS_OK(status)) {
1546 return ntstatus_to_werror(status);
1548 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1550 buffer = data_blob_talloc_zero(mem_ctx, needed);
1552 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1553 cli->srv_name_slash,
1561 if (!NT_STATUS_IS_OK(status)) {
1562 return ntstatus_to_werror(status);
1566 if (W_ERROR_IS_OK(result)) {
1567 display_printdriverdir_1(&info.info1);
1573 /****************************************************************************
1574 ****************************************************************************/
1576 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1577 struct spoolss_AddDriverInfo3 *info,
1583 for (i=0; archi_table[i].long_archi != NULL; i++)
1585 if (strcmp(arch, archi_table[i].short_archi) == 0)
1587 info->version = archi_table[i].version;
1588 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1593 if (archi_table[i].long_archi == NULL)
1595 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1602 /**************************************************************************
1603 wrapper for strtok to get the next parameter from a delimited list.
1604 Needed to handle the empty parameter string denoted by "NULL"
1605 *************************************************************************/
1607 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1608 const char *delim, const char **dest,
1613 /* get the next token */
1614 ptr = strtok_r(str, delim, saveptr);
1616 /* a string of 'NULL' is used to represent an empty
1617 parameter because two consecutive delimiters
1618 will not return an empty string. See man strtok(3)
1620 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1625 *dest = talloc_strdup(mem_ctx, ptr);
1631 /********************************************************************************
1632 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1633 string in the form of
1634 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1635 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1636 <Default Data Type>:<Comma Separated list of Files>
1637 *******************************************************************************/
1639 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1644 char *saveptr = NULL;
1645 struct spoolss_StringArray *deps;
1646 const char **file_array = NULL;
1649 /* fill in the UNISTR fields */
1650 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1653 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1654 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1655 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1656 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1658 /* <Comma Separated List of Dependent Files> */
1659 /* save the beginning of the string */
1660 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1663 /* begin to strip out each filename */
1664 str = strtok_r(str, ",", &saveptr);
1666 /* no dependent files, we are done */
1671 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1676 while (str != NULL) {
1677 add_string_to_array(deps, str, &file_array, &count);
1678 str = strtok_r(NULL, ",", &saveptr);
1681 deps->string = talloc_zero_array(deps, const char *, count + 1);
1682 if (!deps->string) {
1686 for (i=0; i < count; i++) {
1687 deps->string[i] = file_array[i];
1690 r->dependent_files = deps;
1695 /****************************************************************************
1696 ****************************************************************************/
1698 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1699 TALLOC_CTX *mem_ctx,
1700 int argc, const char **argv)
1705 struct spoolss_AddDriverInfoCtr info_ctr;
1706 struct spoolss_AddDriverInfo3 info3;
1709 struct dcerpc_binding_handle *b = cli->binding_handle;
1711 /* parse the command arguments */
1712 if (argc != 3 && argc != 4)
1714 printf ("Usage: %s <Environment> \\\n", argv[0]);
1715 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1716 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1717 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1718 printf ("\t[version]\n");
1723 /* Fill in the spoolss_AddDriverInfo3 struct */
1726 arch = cmd_spoolss_get_short_archi(argv[1]);
1728 printf ("Error Unknown architecture [%s]\n", argv[1]);
1729 return WERR_INVALID_PARAM;
1732 set_drv_info_3_env(mem_ctx, &info3, arch);
1734 driver_args = talloc_strdup( mem_ctx, argv[2] );
1735 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1737 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1738 return WERR_INVALID_PARAM;
1741 /* if printer driver version specified, override the default version
1742 * used by the architecture. This allows installation of Windows
1743 * 2000 (version 3) printer drivers. */
1746 info3.version = atoi(argv[3]);
1750 info_ctr.level = level;
1751 info_ctr.info.info3 = &info3;
1753 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1754 cli->srv_name_slash,
1757 if (!NT_STATUS_IS_OK(status)) {
1758 return ntstatus_to_werror(status);
1760 if (W_ERROR_IS_OK(result)) {
1761 printf ("Printer Driver %s successfully installed.\n",
1769 /****************************************************************************
1770 ****************************************************************************/
1772 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1773 TALLOC_CTX *mem_ctx,
1774 int argc, const char **argv)
1777 struct spoolss_SetPrinterInfoCtr info_ctr;
1778 struct spoolss_SetPrinterInfo2 info2;
1780 /* parse the command arguments */
1783 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1787 /* Fill in the DRIVER_INFO_2 struct */
1790 info2.printername = argv[1];
1791 info2.drivername = argv[3];
1792 info2.sharename = argv[2];
1793 info2.portname = argv[4];
1794 info2.comment = "Created by rpcclient";
1795 info2.printprocessor = "winprint";
1796 info2.datatype = "RAW";
1797 info2.devmode_ptr = 0;
1798 info2.secdesc_ptr = 0;
1799 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1801 info2.defaultpriority = 0;
1802 info2.starttime = 0;
1803 info2.untiltime = 0;
1805 /* These three fields must not be used by AddPrinter()
1806 as defined in the MS Platform SDK documentation..
1810 info2.averageppm = 0;
1814 info_ctr.info.info2 = &info2;
1816 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1818 if (W_ERROR_IS_OK(result))
1819 printf ("Printer %s successfully installed.\n", argv[1]);
1824 /****************************************************************************
1825 ****************************************************************************/
1827 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1828 TALLOC_CTX *mem_ctx,
1829 int argc, const char **argv)
1831 struct policy_handle pol;
1835 const char *printername;
1836 union spoolss_PrinterInfo info;
1837 struct spoolss_SetPrinterInfoCtr info_ctr;
1838 struct spoolss_SetPrinterInfo2 info2;
1839 struct spoolss_DevmodeContainer devmode_ctr;
1840 struct sec_desc_buf secdesc_ctr;
1841 struct dcerpc_binding_handle *b = cli->binding_handle;
1843 ZERO_STRUCT(devmode_ctr);
1844 ZERO_STRUCT(secdesc_ctr);
1846 /* parse the command arguments */
1849 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1853 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1855 /* Get a printer handle */
1857 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1861 if (!W_ERROR_IS_OK(result))
1864 /* Get printer info */
1866 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1871 if (!W_ERROR_IS_OK(result)) {
1872 printf ("Unable to retrieve printer information!\n");
1876 /* Set the printer driver */
1878 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1879 info2.drivername = argv[2];
1882 info_ctr.info.info2 = &info2;
1884 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1891 if (!NT_STATUS_IS_OK(status)) {
1892 result = ntstatus_to_werror(status);
1895 if (!W_ERROR_IS_OK(result)) {
1896 printf("SetPrinter call failed!\n");
1900 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1905 if (is_valid_policy_hnd(&pol)) {
1907 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1914 /****************************************************************************
1915 ****************************************************************************/
1917 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1918 TALLOC_CTX *mem_ctx,
1919 int argc, const char **argv)
1921 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1923 struct dcerpc_binding_handle *b = cli->binding_handle;
1928 const char *arch = NULL;
1929 uint32_t delete_flags = 0;
1931 /* parse the command arguments */
1932 if (argc < 2 || argc > 4) {
1933 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1940 vers = atoi (argv[3]);
1943 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1946 /* delete the driver for all architectures */
1947 for (i=0; archi_table[i].long_archi; i++) {
1949 if (arch && !strequal( archi_table[i].long_archi, arch))
1952 if (vers >= 0 && archi_table[i].version != vers)
1955 /* make the call to remove the driver */
1956 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1957 cli->srv_name_slash,
1958 archi_table[i].long_archi,
1961 archi_table[i].version,
1963 if (!NT_STATUS_IS_OK(status)) {
1964 return ntstatus_to_werror(status);
1966 if ( !W_ERROR_IS_OK(result) )
1968 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1969 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1970 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1975 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1976 archi_table[i].long_archi, archi_table[i].version);
1985 /****************************************************************************
1986 ****************************************************************************/
1988 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1989 TALLOC_CTX *mem_ctx,
1990 int argc, const char **argv)
1992 WERROR result = WERR_OK;
1995 struct dcerpc_binding_handle *b = cli->binding_handle;
1997 /* parse the command arguments */
1999 printf ("Usage: %s <driver>\n", argv[0]);
2003 /* delete the driver for all architectures */
2004 for (i=0; archi_table[i].long_archi; i++) {
2007 /* make the call to remove the driver */
2008 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2009 cli->srv_name_slash,
2010 archi_table[i].long_archi,
2013 if (!NT_STATUS_IS_OK(status)) {
2014 result = ntstatus_to_werror(status);
2017 if ( !W_ERROR_IS_OK(result) ) {
2018 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2019 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2020 argv[1], archi_table[i].long_archi,
2021 win_errstr(result));
2024 printf ("Driver %s removed for arch [%s].\n", argv[1],
2025 archi_table[i].long_archi);
2032 /****************************************************************************
2033 ****************************************************************************/
2035 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2036 TALLOC_CTX *mem_ctx,
2037 int argc, const char **argv)
2041 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2044 union spoolss_PrintProcessorDirectoryInfo info;
2046 struct dcerpc_binding_handle *b = cli->binding_handle;
2048 /* parse the command arguments */
2050 printf ("Usage: %s [environment]\n", argv[0]);
2055 environment = argv[1];
2058 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2059 cli->srv_name_slash,
2067 if (!NT_STATUS_IS_OK(status)) {
2068 return ntstatus_to_werror(status);
2070 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2072 buffer = data_blob_talloc_zero(mem_ctx, needed);
2074 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2075 cli->srv_name_slash,
2083 if (!NT_STATUS_IS_OK(status)) {
2084 return ntstatus_to_werror(status);
2088 if (W_ERROR_IS_OK(result)) {
2089 printf("%s\n", info.info1.directory_name);
2095 /****************************************************************************
2096 ****************************************************************************/
2098 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2099 int argc, const char **argv)
2101 struct policy_handle handle;
2104 const char *printername;
2105 union spoolss_AddFormInfo info;
2106 struct spoolss_AddFormInfo1 info1;
2107 struct spoolss_AddFormInfo2 info2;
2109 struct dcerpc_binding_handle *b = cli->binding_handle;
2111 /* Parse the command arguments */
2113 if (argc < 3 || argc > 5) {
2114 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2118 /* Get a printer handle */
2120 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2122 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2126 if (!W_ERROR_IS_OK(werror))
2129 /* Dummy up some values for the form data */
2132 level = atoi(argv[3]);
2137 info1.flags = SPOOLSS_FORM_USER;
2138 info1.form_name = argv[2];
2139 info1.size.width = 100;
2140 info1.size.height = 100;
2141 info1.area.left = 0;
2142 info1.area.top = 10;
2143 info1.area.right = 20;
2144 info1.area.bottom = 30;
2146 info.info1 = &info1;
2150 info2.flags = SPOOLSS_FORM_USER;
2151 info2.form_name = argv[2];
2152 info2.size.width = 100;
2153 info2.size.height = 100;
2154 info2.area.left = 0;
2155 info2.area.top = 10;
2156 info2.area.right = 20;
2157 info2.area.bottom = 30;
2158 info2.keyword = argv[2];
2159 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2160 info2.mui_dll = NULL;
2161 info2.ressource_id = 0;
2162 info2.display_name = argv[2];
2165 info.info2 = &info2;
2169 werror = WERR_INVALID_PARAM;
2176 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2181 if (!NT_STATUS_IS_OK(status)) {
2182 werror = ntstatus_to_werror(status);
2186 if (is_valid_policy_hnd(&handle)) {
2188 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2194 /****************************************************************************
2195 ****************************************************************************/
2197 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2198 int argc, const char **argv)
2200 struct policy_handle handle;
2203 const char *printername;
2204 union spoolss_AddFormInfo info;
2205 struct spoolss_AddFormInfo1 info1;
2206 struct dcerpc_binding_handle *b = cli->binding_handle;
2208 /* Parse the command arguments */
2211 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2215 /* Get a printer handle */
2217 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2219 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2221 SEC_FLAG_MAXIMUM_ALLOWED,
2223 if (!W_ERROR_IS_OK(werror))
2226 /* Dummy up some values for the form data */
2228 info1.flags = SPOOLSS_FORM_PRINTER;
2229 info1.size.width = 100;
2230 info1.size.height = 100;
2231 info1.area.left = 0;
2232 info1.area.top = 1000;
2233 info1.area.right = 2000;
2234 info1.area.bottom = 3000;
2235 info1.form_name = argv[2];
2237 info.info1 = &info1;
2241 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2247 if (!NT_STATUS_IS_OK(status)) {
2248 werror = ntstatus_to_werror(status);
2252 if (is_valid_policy_hnd(&handle)) {
2254 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2260 /****************************************************************************
2261 ****************************************************************************/
2263 static const char *get_form_flag(int form_flag)
2265 switch (form_flag) {
2266 case SPOOLSS_FORM_USER:
2268 case SPOOLSS_FORM_BUILTIN:
2269 return "FORM_BUILTIN";
2270 case SPOOLSS_FORM_PRINTER:
2271 return "FORM_PRINTER";
2277 /****************************************************************************
2278 ****************************************************************************/
2280 static void display_form_info1(struct spoolss_FormInfo1 *r)
2283 "\tflag: %s (%d)\n" \
2284 "\twidth: %d, length: %d\n" \
2285 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2286 r->form_name, get_form_flag(r->flags), r->flags,
2287 r->size.width, r->size.height,
2288 r->area.left, r->area.right,
2289 r->area.top, r->area.bottom);
2292 /****************************************************************************
2293 ****************************************************************************/
2295 static void display_form_info2(struct spoolss_FormInfo2 *r)
2298 "\tflag: %s (%d)\n" \
2299 "\twidth: %d, length: %d\n" \
2300 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2301 r->form_name, get_form_flag(r->flags), r->flags,
2302 r->size.width, r->size.height,
2303 r->area.left, r->area.right,
2304 r->area.top, r->area.bottom);
2305 printf("\tkeyword: %s\n", r->keyword);
2306 printf("\tstring_type: 0x%08x\n", r->string_type);
2307 printf("\tmui_dll: %s\n", r->mui_dll);
2308 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2309 printf("\tdisplay_name: %s\n", r->display_name);
2310 printf("\tlang_id: %d\n", r->lang_id);
2314 /****************************************************************************
2315 ****************************************************************************/
2317 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2318 int argc, const char **argv)
2320 struct policy_handle handle;
2323 const char *printername;
2325 uint32_t offered = 0;
2326 union spoolss_FormInfo info;
2329 struct dcerpc_binding_handle *b = cli->binding_handle;
2331 /* Parse the command arguments */
2333 if (argc < 3 || argc > 5) {
2334 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2338 /* Get a printer handle */
2340 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2342 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2344 SEC_FLAG_MAXIMUM_ALLOWED,
2346 if (!W_ERROR_IS_OK(werror))
2350 level = atoi(argv[3]);
2355 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2364 if (!NT_STATUS_IS_OK(status)) {
2365 werror = ntstatus_to_werror(status);
2368 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2369 buffer = data_blob_talloc_zero(mem_ctx, needed);
2371 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2380 if (!NT_STATUS_IS_OK(status)) {
2381 werror = ntstatus_to_werror(status);
2386 if (!W_ERROR_IS_OK(werror)) {
2392 display_form_info1(&info.info1);
2395 display_form_info2(&info.info2);
2400 if (is_valid_policy_hnd(&handle)) {
2402 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2408 /****************************************************************************
2409 ****************************************************************************/
2411 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2412 TALLOC_CTX *mem_ctx, int argc,
2415 struct policy_handle handle;
2418 const char *printername;
2419 struct dcerpc_binding_handle *b = cli->binding_handle;
2421 /* Parse the command arguments */
2424 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2428 /* Get a printer handle */
2430 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2432 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2434 SEC_FLAG_MAXIMUM_ALLOWED,
2436 if (!W_ERROR_IS_OK(werror))
2439 /* Delete the form */
2441 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2445 if (!NT_STATUS_IS_OK(status)) {
2446 werror = ntstatus_to_werror(status);
2451 if (is_valid_policy_hnd(&handle)) {
2453 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2459 /****************************************************************************
2460 ****************************************************************************/
2462 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2463 TALLOC_CTX *mem_ctx, int argc,
2466 struct policy_handle handle;
2468 const char *printername;
2469 uint32_t num_forms, level = 1, i;
2470 union spoolss_FormInfo *forms;
2471 struct dcerpc_binding_handle *b = cli->binding_handle;
2473 /* Parse the command arguments */
2475 if (argc < 2 || argc > 4) {
2476 printf ("Usage: %s <printer> [level]\n", argv[0]);
2480 /* Get a printer handle */
2482 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2484 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2486 SEC_FLAG_MAXIMUM_ALLOWED,
2488 if (!W_ERROR_IS_OK(werror))
2492 level = atoi(argv[2]);
2495 /* Enumerate forms */
2497 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2504 if (!W_ERROR_IS_OK(werror))
2507 /* Display output */
2509 for (i = 0; i < num_forms; i++) {
2512 display_form_info1(&forms[i].info1);
2515 display_form_info2(&forms[i].info2);
2521 if (is_valid_policy_hnd(&handle)) {
2523 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2529 /****************************************************************************
2530 ****************************************************************************/
2532 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2533 TALLOC_CTX *mem_ctx,
2534 int argc, const char **argv)
2538 const char *printername;
2539 struct policy_handle pol;
2540 union spoolss_PrinterInfo info;
2541 enum winreg_Type type;
2542 union spoolss_PrinterData data;
2544 struct dcerpc_binding_handle *b = cli->binding_handle;
2546 /* parse the command arguments */
2548 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2549 " <value> <data>\n",
2554 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2558 if (strequal(argv[2], "string")) {
2562 if (strequal(argv[2], "binary")) {
2566 if (strequal(argv[2], "dword")) {
2570 if (strequal(argv[2], "multistring")) {
2571 type = REG_MULTI_SZ;
2574 if (type == REG_NONE) {
2575 printf("Unknown data type: %s\n", argv[2]);
2576 result = WERR_INVALID_PARAM;
2580 /* get a printer handle */
2582 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2584 SEC_FLAG_MAXIMUM_ALLOWED,
2586 if (!W_ERROR_IS_OK(result)) {
2590 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2595 if (!W_ERROR_IS_OK(result)) {
2599 printf("%s\n", current_timestring(mem_ctx, true));
2600 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2602 /* Set the printer data */
2606 data.string = talloc_strdup(mem_ctx, argv[4]);
2607 W_ERROR_HAVE_NO_MEMORY(data.string);
2610 data.value = strtoul(argv[4], NULL, 10);
2613 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2615 case REG_MULTI_SZ: {
2617 const char **strings = NULL;
2619 for (i=4; i<argc; i++) {
2620 if (strcmp(argv[i], "NULL") == 0) {
2623 if (!add_string_to_array(mem_ctx, argv[i],
2626 result = WERR_NOMEM;
2630 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2631 if (!data.string_array) {
2632 result = WERR_NOMEM;
2635 for (i=0; i < num_strings; i++) {
2636 data.string_array[i] = strings[i];
2641 printf("Unknown data type: %s\n", argv[2]);
2642 result = WERR_INVALID_PARAM;
2646 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2647 if (!W_ERROR_IS_OK(result)) {
2651 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2653 argv[3], /* value_name */
2658 if (!NT_STATUS_IS_OK(status)) {
2659 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2660 result = ntstatus_to_werror(status);
2663 if (!W_ERROR_IS_OK(result)) {
2664 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2667 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2669 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2674 if (!W_ERROR_IS_OK(result)) {
2678 printf("%s\n", current_timestring(mem_ctx, true));
2679 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2683 if (is_valid_policy_hnd(&pol)) {
2685 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2691 /****************************************************************************
2692 ****************************************************************************/
2694 static void display_job_info1(struct spoolss_JobInfo1 *r)
2696 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2697 r->user_name, r->document_name, r->text_status, r->pages_printed,
2701 /****************************************************************************
2702 ****************************************************************************/
2704 static void display_job_info2(struct spoolss_JobInfo2 *r)
2706 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2707 r->position, r->job_id,
2708 r->user_name, r->document_name, r->text_status, r->pages_printed,
2709 r->total_pages, r->size);
2712 /****************************************************************************
2713 ****************************************************************************/
2715 static void display_job_info3(struct spoolss_JobInfo3 *r)
2717 printf("jobid[%d], next_jobid[%d]\n",
2718 r->job_id, r->next_job_id);
2721 /****************************************************************************
2722 ****************************************************************************/
2724 static void display_job_info4(struct spoolss_JobInfo4 *r)
2726 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2727 r->position, r->job_id,
2728 r->user_name, r->document_name, r->text_status, r->pages_printed,
2729 r->total_pages, r->size, r->size_high);
2732 /****************************************************************************
2733 ****************************************************************************/
2735 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2736 TALLOC_CTX *mem_ctx, int argc,
2740 uint32_t level = 1, count, i;
2741 const char *printername;
2742 struct policy_handle hnd;
2743 union spoolss_JobInfo *info;
2744 struct dcerpc_binding_handle *b = cli->binding_handle;
2746 if (argc < 2 || argc > 3) {
2747 printf("Usage: %s printername [level]\n", argv[0]);
2752 level = atoi(argv[2]);
2755 /* Open printer handle */
2757 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2759 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2761 SEC_FLAG_MAXIMUM_ALLOWED,
2763 if (!W_ERROR_IS_OK(result))
2766 /* Enumerate ports */
2768 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2776 if (!W_ERROR_IS_OK(result)) {
2780 for (i = 0; i < count; i++) {
2783 display_job_info1(&info[i].info1);
2786 display_job_info2(&info[i].info2);
2789 d_printf("unknown info level %d\n", level);
2795 if (is_valid_policy_hnd(&hnd)) {
2797 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2803 /****************************************************************************
2804 ****************************************************************************/
2806 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2807 TALLOC_CTX *mem_ctx, int argc,
2811 const char *printername;
2812 struct policy_handle hnd;
2815 union spoolss_JobInfo info;
2816 struct dcerpc_binding_handle *b = cli->binding_handle;
2818 if (argc < 3 || argc > 4) {
2819 printf("Usage: %s printername job_id [level]\n", argv[0]);
2823 job_id = atoi(argv[2]);
2826 level = atoi(argv[3]);
2829 /* Open printer handle */
2831 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2833 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2835 SEC_FLAG_MAXIMUM_ALLOWED,
2837 if (!W_ERROR_IS_OK(result)) {
2841 /* Enumerate ports */
2843 result = rpccli_spoolss_getjob(cli, mem_ctx,
2850 if (!W_ERROR_IS_OK(result)) {
2856 display_job_info1(&info.info1);
2859 display_job_info2(&info.info2);
2862 display_job_info3(&info.info3);
2865 display_job_info4(&info.info4);
2868 d_printf("unknown info level %d\n", level);
2873 if (is_valid_policy_hnd(&hnd)) {
2875 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2881 /****************************************************************************
2882 ****************************************************************************/
2886 enum spoolss_JobControl val;
2888 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2889 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2890 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2891 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2892 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2893 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2894 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2895 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2896 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2899 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2903 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2904 if (strequal(cmdvals[i].name, cmd)) {
2905 return cmdvals[i].val;
2908 return (enum spoolss_JobControl)atoi(cmd);
2911 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2912 TALLOC_CTX *mem_ctx, int argc,
2917 const char *printername;
2918 struct policy_handle hnd;
2920 enum spoolss_JobControl command;
2921 struct dcerpc_binding_handle *b = cli->binding_handle;
2924 printf("Usage: %s printername job_id command\n", argv[0]);
2925 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2926 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2930 job_id = atoi(argv[2]);
2931 command = parse_setjob_command(argv[3]);
2933 /* Open printer handle */
2935 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2937 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2939 SEC_FLAG_MAXIMUM_ALLOWED,
2941 if (!W_ERROR_IS_OK(result)) {
2947 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2953 if (!NT_STATUS_IS_OK(status)) {
2954 result = ntstatus_to_werror(status);
2957 if (!W_ERROR_IS_OK(result)) {
2962 if (is_valid_policy_hnd(&hnd)) {
2964 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2970 /****************************************************************************
2971 ****************************************************************************/
2973 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2974 TALLOC_CTX *mem_ctx, int argc,
2979 const char *printername;
2980 struct policy_handle hnd;
2981 uint32_t value_needed;
2982 enum winreg_Type type;
2983 uint32_t data_needed;
2984 struct dcerpc_binding_handle *b = cli->binding_handle;
2985 struct spoolss_EnumPrinterData r;
2988 printf("Usage: %s printername\n", argv[0]);
2992 /* Open printer handle */
2994 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2996 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2998 SEC_FLAG_MAXIMUM_ALLOWED,
3000 if (!W_ERROR_IS_OK(result)) {
3004 /* Enumerate data */
3007 r.in.enum_index = 0;
3008 r.in.value_offered = 0;
3009 r.in.data_offered = 0;
3010 r.out.value_name = NULL;
3011 r.out.value_needed = &value_needed;
3014 r.out.data_needed = &data_needed;
3016 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3017 if (!NT_STATUS_IS_OK(status)) {
3018 result = ntstatus_to_werror(status);
3022 if (!W_ERROR_IS_OK(r.out.result)) {
3023 result = r.out.result;
3027 r.in.data_offered = *r.out.data_needed;
3028 r.in.value_offered = *r.out.value_needed;
3029 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3030 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3034 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 result = ntstatus_to_werror(status);
3040 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3048 struct regval_blob *v;
3050 v = regval_compose(talloc_tos(),
3056 result = WERR_NOMEM;
3060 display_reg_value(v);
3064 } while (W_ERROR_IS_OK(r.out.result));
3067 if (is_valid_policy_hnd(&hnd)) {
3069 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3075 /****************************************************************************
3076 ****************************************************************************/
3078 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3079 TALLOC_CTX *mem_ctx, int argc,
3084 const char *printername;
3085 struct policy_handle hnd;
3087 struct spoolss_PrinterEnumValues *info;
3088 struct dcerpc_binding_handle *b = cli->binding_handle;
3091 printf("Usage: %s printername <keyname>\n", argv[0]);
3095 /* Open printer handle */
3097 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3099 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3101 SEC_FLAG_MAXIMUM_ALLOWED,
3103 if (!W_ERROR_IS_OK(result)) {
3107 /* Enumerate subkeys */
3109 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3115 if (!W_ERROR_IS_OK(result)) {
3119 for (i=0; i < count; i++) {
3120 display_printer_data(info[i].value_name,
3123 info[i].data->length);
3127 if (is_valid_policy_hnd(&hnd)) {
3129 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3135 /****************************************************************************
3136 ****************************************************************************/
3138 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3139 TALLOC_CTX *mem_ctx, int argc,
3143 const char *printername;
3144 const char *keyname = NULL;
3145 struct policy_handle hnd;
3146 const char **key_buffer = NULL;
3148 uint32_t offered = 0;
3149 struct dcerpc_binding_handle *b = cli->binding_handle;
3151 if (argc < 2 || argc > 4) {
3152 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3163 offered = atoi(argv[3]);
3166 /* Open printer handle */
3168 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3170 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3172 SEC_FLAG_MAXIMUM_ALLOWED,
3174 if (!W_ERROR_IS_OK(result)) {
3178 /* Enumerate subkeys */
3180 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3186 if (!W_ERROR_IS_OK(result)) {
3190 for (i=0; key_buffer && key_buffer[i]; i++) {
3191 printf("%s\n", key_buffer[i]);
3196 if (is_valid_policy_hnd(&hnd)) {
3198 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3204 /****************************************************************************
3205 ****************************************************************************/
3207 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3208 TALLOC_CTX *mem_ctx, int argc,
3211 const char *printername;
3212 const char *clientname;
3213 struct policy_handle hnd;
3216 struct spoolss_NotifyOption option;
3217 struct dcerpc_binding_handle *b = cli->binding_handle;
3220 printf("Usage: %s printername\n", argv[0]);
3227 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3229 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3231 SEC_FLAG_MAXIMUM_ALLOWED,
3233 if (!W_ERROR_IS_OK(result)) {
3234 printf("Error opening %s\n", argv[1]);
3238 /* Create spool options */
3243 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3244 if (option.types == NULL) {
3245 result = WERR_NOMEM;
3249 option.types[0].type = PRINTER_NOTIFY_TYPE;
3250 option.types[0].count = 1;
3251 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3252 if (option.types[0].fields == NULL) {
3253 result = WERR_NOMEM;
3256 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3258 option.types[1].type = JOB_NOTIFY_TYPE;
3259 option.types[1].count = 1;
3260 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3261 if (option.types[1].fields == NULL) {
3262 result = WERR_NOMEM;
3265 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3267 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3269 result = WERR_NOMEM;
3275 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3283 if (!NT_STATUS_IS_OK(status)) {
3284 result = ntstatus_to_werror(status);
3287 if (!W_ERROR_IS_OK(result)) {
3288 printf("Error rffpcnex %s\n", argv[1]);
3293 if (is_valid_policy_hnd(&hnd)) {
3295 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3301 /****************************************************************************
3302 ****************************************************************************/
3304 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3305 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3307 union spoolss_PrinterInfo info1, info2;
3309 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3311 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3312 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3317 if ( !W_ERROR_IS_OK(werror) ) {
3318 printf("failed (%s)\n", win_errstr(werror));
3319 talloc_destroy(mem_ctx);
3324 printf("Retrieving printer properties for %s...", cli2->desthost);
3325 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3330 if ( !W_ERROR_IS_OK(werror) ) {
3331 printf("failed (%s)\n", win_errstr(werror));
3332 talloc_destroy(mem_ctx);
3337 talloc_destroy(mem_ctx);
3342 /****************************************************************************
3343 ****************************************************************************/
3345 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3346 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3348 union spoolss_PrinterInfo info1, info2;
3350 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3351 struct security_descriptor *sd1, *sd2;
3355 printf("Retrieving printer security for %s...", cli1->desthost);
3356 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3361 if ( !W_ERROR_IS_OK(werror) ) {
3362 printf("failed (%s)\n", win_errstr(werror));
3368 printf("Retrieving printer security for %s...", cli2->desthost);
3369 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3374 if ( !W_ERROR_IS_OK(werror) ) {
3375 printf("failed (%s)\n", win_errstr(werror));
3384 sd1 = info1.info3.secdesc;
3385 sd2 = info2.info3.secdesc;
3387 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3388 printf("NULL secdesc!\n");
3393 if (!security_descriptor_equal( sd1, sd2 ) ) {
3394 printf("Security Descriptors *not* equal!\n");
3399 printf("Security descriptors match\n");
3402 talloc_destroy(mem_ctx);
3407 /****************************************************************************
3408 ****************************************************************************/
3410 extern struct user_auth_info *rpcclient_auth_info;
3412 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3413 TALLOC_CTX *mem_ctx, int argc,
3416 const char *printername;
3417 char *printername_path = NULL;
3418 struct cli_state *cli_server2 = NULL;
3419 struct rpc_pipe_client *cli2 = NULL;
3420 struct policy_handle hPrinter1, hPrinter2;
3425 printf("Usage: %s <printer> <server>\n", argv[0]);
3429 printername = argv[1];
3431 /* first get the connection to the remote server */
3433 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3436 get_cmdline_auth_info_username(rpcclient_auth_info),
3438 get_cmdline_auth_info_password(rpcclient_auth_info),
3439 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3440 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3442 if ( !NT_STATUS_IS_OK(nt_status) )
3443 return WERR_GENERAL_FAILURE;
3445 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3447 if (!NT_STATUS_IS_OK(nt_status)) {
3448 printf("failed to open spoolss pipe on server %s (%s)\n",
3449 argv[2], nt_errstr(nt_status));
3450 return WERR_GENERAL_FAILURE;
3453 /* now open up both printers */
3455 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3457 printf("Opening %s...", printername_path);
3459 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3463 if ( !W_ERROR_IS_OK(werror) ) {
3464 printf("failed (%s)\n", win_errstr(werror));
3469 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3471 printf("Opening %s...", printername_path);
3472 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3476 if ( !W_ERROR_IS_OK(werror) ) {
3477 printf("failed (%s)\n", win_errstr(werror));
3482 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3483 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3485 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3492 printf("Closing printers...");
3495 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3496 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3500 /* close the second remote connection */
3502 cli_shutdown( cli_server2 );
3506 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3508 printf("print_processor_name: %s\n", r->print_processor_name);
3511 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3512 TALLOC_CTX *mem_ctx, int argc,
3516 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3517 uint32_t num_procs, level = 1, i;
3518 union spoolss_PrintProcessorInfo *procs;
3520 /* Parse the command arguments */
3522 if (argc < 1 || argc > 4) {
3523 printf ("Usage: %s [environment] [level]\n", argv[0]);
3528 environment = argv[1];
3532 level = atoi(argv[2]);
3535 /* Enumerate Print Processors */
3537 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3538 cli->srv_name_slash,
3544 if (!W_ERROR_IS_OK(werror))
3547 /* Display output */
3549 for (i = 0; i < num_procs; i++) {
3552 display_proc_info1(&procs[i].info1);
3561 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3563 printf("name_array: %s\n", r->name_array);
3566 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3567 TALLOC_CTX *mem_ctx, int argc,
3571 const char *print_processor_name = "winprint";
3572 uint32_t num_procs, level = 1, i;
3573 union spoolss_PrintProcDataTypesInfo *procs;
3575 /* Parse the command arguments */
3577 if (argc < 1 || argc > 4) {
3578 printf ("Usage: %s [environment] [level]\n", argv[0]);
3583 print_processor_name = argv[1];
3587 level = atoi(argv[2]);
3590 /* Enumerate Print Processor Data Types */
3592 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3593 cli->srv_name_slash,
3594 print_processor_name,
3599 if (!W_ERROR_IS_OK(werror))
3602 /* Display output */
3604 for (i = 0; i < num_procs; i++) {
3607 display_proc_data_types_info1(&procs[i].info1);
3616 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3618 printf("monitor_name: %s\n", r->monitor_name);
3621 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3623 printf("monitor_name: %s\n", r->monitor_name);
3624 printf("environment: %s\n", r->environment);
3625 printf("dll_name: %s\n", r->dll_name);
3628 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3629 TALLOC_CTX *mem_ctx, int argc,
3633 uint32_t count, level = 1, i;
3634 union spoolss_MonitorInfo *info;
3636 /* Parse the command arguments */
3639 printf("Usage: %s [level]\n", argv[0]);
3644 level = atoi(argv[1]);
3647 /* Enumerate Print Monitors */
3649 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3650 cli->srv_name_slash,
3655 if (!W_ERROR_IS_OK(werror)) {
3659 /* Display output */
3661 for (i = 0; i < count; i++) {
3664 display_monitor1(&info[i].info1);
3667 display_monitor2(&info[i].info2);
3676 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3677 TALLOC_CTX *mem_ctx, int argc,
3682 struct policy_handle handle, gdi_handle;
3683 const char *printername;
3684 struct spoolss_DevmodeContainer devmode_ctr;
3685 struct dcerpc_binding_handle *b = cli->binding_handle;
3687 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3689 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3691 SEC_FLAG_MAXIMUM_ALLOWED,
3693 if (!W_ERROR_IS_OK(result)) {
3697 ZERO_STRUCT(devmode_ctr);
3699 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3704 if (!NT_STATUS_IS_OK(status)) {
3705 result = ntstatus_to_werror(status);
3708 if (!W_ERROR_IS_OK(result)) {
3713 if (is_valid_policy_hnd(&gdi_handle)) {
3715 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3717 if (is_valid_policy_hnd(&handle)) {
3719 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3725 /* List of commands exported by this module */
3726 struct cmd_set spoolss_commands[] = {
3730 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3731 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3732 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3733 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3734 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3735 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3736 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3737 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3738 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3739 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3740 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3741 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3742 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3743 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3744 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3745 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3746 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3747 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3748 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3749 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3750 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3751 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3752 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3753 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3754 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3755 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3756 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3757 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3758 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3759 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3760 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3761 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3762 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3763 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3764 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3765 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },