2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/cli_spoolss.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
31 #include "registry/reg_objects.h"
33 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
35 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
36 _cli->srv_name_slash, _arg); \
37 W_ERROR_HAVE_NO_MEMORY(_printername); \
40 /* The version int is used by getdrivers. Note that
41 all architecture strings that support mutliple
42 versions must be grouped together since enumdrivers
43 uses this property to prevent issuing multiple
44 enumdriver calls for the same arch */
47 static const struct print_architecture_table_node archi_table[]= {
49 {"Windows 4.0", "WIN40", 0 },
50 {"Windows NT x86", "W32X86", 2 },
51 {"Windows NT x86", "W32X86", 3 },
52 {"Windows NT R4000", "W32MIPS", 2 },
53 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
54 {"Windows NT PowerPC", "W32PPC", 2 },
55 {"Windows IA64", "IA64", 3 },
56 {"Windows x64", "x64", 3 },
63 * rpcclient module for SPOOLSS rpc pipe.
65 * This generally just parses and checks command lines, and then calls
66 * a cli_spoolss function.
69 /****************************************************************************
70 function to do the mapping between the long architecture name and
72 ****************************************************************************/
74 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
78 DEBUG(107,("Getting architecture dependant directory\n"));
81 } while ( (archi_table[i].long_archi!=NULL ) &&
82 StrCaseCmp(long_archi, archi_table[i].long_archi) );
84 if (archi_table[i].long_archi==NULL) {
85 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
89 /* this might be client code - but shouldn't this be an fstrcpy etc? */
92 DEBUGADD(108,("index: [%d]\n", i));
93 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
94 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
96 return archi_table[i].short_archi;
99 /****************************************************************************
100 ****************************************************************************/
102 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
104 int argc, const char **argv)
107 struct policy_handle hnd;
108 uint32_t access_mask = PRINTER_ALL_ACCESS;
111 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
116 sscanf(argv[2], "%x", &access_mask);
119 /* Open the printer handle */
121 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
125 if (W_ERROR_IS_OK(werror)) {
126 printf("Printer %s opened successfully\n", argv[1]);
127 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
129 if (!W_ERROR_IS_OK(werror)) {
130 printf("Error closing printer handle! (%s)\n",
131 get_dos_error_msg(werror));
139 /****************************************************************************
140 ****************************************************************************/
142 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
147 printf("\tprintername:[%s]\n", r->printername);
148 printf("\tservername:[%s]\n", r->servername);
149 printf("\tcjobs:[0x%x]\n", r->cjobs);
150 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
151 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
152 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
153 r->time.day, r->time.day_of_week);
154 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
155 r->time.second, r->time.millisecond);
157 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
158 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
160 printf("\tversion:[0x%x]\n", r->version);
161 printf("\tfree_build:[0x%x]\n", r->free_build);
162 printf("\tspooling:[0x%x]\n", r->spooling);
163 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
164 printf("\tsession_counter:[0x%x]\n", r->session_counter);
165 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
166 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
167 printf("\tjob_error:[0x%x]\n", r->job_error);
168 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
169 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
170 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
171 printf("\tchange_id:[0x%x]\n", r->change_id);
172 printf("\tlast_error: %s\n", win_errstr(r->last_error));
173 printf("\tstatus:[0x%x]\n", r->status);
174 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
175 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
176 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
177 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
178 printf("\tref_ic:[0x%x]\n", r->ref_ic);
179 printf("\treserved2:[0x%x]\n", r->reserved2);
180 printf("\treserved3:[0x%x]\n", r->reserved3);
185 /****************************************************************************
186 ****************************************************************************/
188 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
190 printf("\tflags:[0x%x]\n", r->flags);
191 printf("\tname:[%s]\n", r->name);
192 printf("\tdescription:[%s]\n", r->description);
193 printf("\tcomment:[%s]\n", r->comment);
198 /****************************************************************************
199 ****************************************************************************/
201 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
203 printf("\tservername:[%s]\n", r->servername);
204 printf("\tprintername:[%s]\n", r->printername);
205 printf("\tsharename:[%s]\n", r->sharename);
206 printf("\tportname:[%s]\n", r->portname);
207 printf("\tdrivername:[%s]\n", r->drivername);
208 printf("\tcomment:[%s]\n", r->comment);
209 printf("\tlocation:[%s]\n", r->location);
210 printf("\tsepfile:[%s]\n", r->sepfile);
211 printf("\tprintprocessor:[%s]\n", r->printprocessor);
212 printf("\tdatatype:[%s]\n", r->datatype);
213 printf("\tparameters:[%s]\n", r->parameters);
214 printf("\tattributes:[0x%x]\n", r->attributes);
215 printf("\tpriority:[0x%x]\n", r->priority);
216 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
217 printf("\tstarttime:[0x%x]\n", r->starttime);
218 printf("\tuntiltime:[0x%x]\n", r->untiltime);
219 printf("\tstatus:[0x%x]\n", r->status);
220 printf("\tcjobs:[0x%x]\n", r->cjobs);
221 printf("\taverageppm:[0x%x]\n", r->averageppm);
224 display_sec_desc(r->secdesc);
229 /****************************************************************************
230 ****************************************************************************/
232 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
234 display_sec_desc(r->secdesc);
239 /****************************************************************************
240 ****************************************************************************/
242 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
244 printf("\tservername:[%s]\n", r->servername);
245 printf("\tprintername:[%s]\n", r->printername);
246 printf("\tattributes:[0x%x]\n", r->attributes);
250 /****************************************************************************
251 ****************************************************************************/
253 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
255 printf("\tprintername:[%s]\n", r->printername);
256 printf("\tportname:[%s]\n", r->portname);
257 printf("\tattributes:[0x%x]\n", r->attributes);
258 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
259 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
263 /****************************************************************************
264 ****************************************************************************/
266 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
268 printf("\tstatus:[0x%x]\n", r->status);
272 /****************************************************************************
273 ****************************************************************************/
275 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
277 printf("\tguid:[%s]\n", r->guid);
278 printf("\taction:[0x%x]\n", r->action);
282 /****************************************************************************
283 ****************************************************************************/
285 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
287 int argc, const char **argv)
291 union spoolss_PrinterInfo *info;
294 uint32_t flags = PRINTER_ENUM_LOCAL;
297 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
302 level = atoi(argv[1]);
308 name = cli->srv_name_slash;
312 flags = atoi(argv[3]);
315 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
322 if (W_ERROR_IS_OK(result)) {
325 printf ("No printers returned.\n");
329 for (i = 0; i < count; i++) {
332 display_print_info0(&info[i].info0);
335 display_print_info1(&info[i].info1);
338 display_print_info2(&info[i].info2);
341 display_print_info3(&info[i].info3);
344 display_print_info4(&info[i].info4);
347 display_print_info5(&info[i].info5);
350 display_print_info6(&info[i].info6);
353 printf("unknown info level %d\n", level);
363 /****************************************************************************
364 ****************************************************************************/
366 static void display_port_info_1(struct spoolss_PortInfo1 *r)
368 printf("\tPort Name:\t[%s]\n", r->port_name);
371 /****************************************************************************
372 ****************************************************************************/
374 static void display_port_info_2(struct spoolss_PortInfo2 *r)
376 printf("\tPort Name:\t[%s]\n", r->port_name);
377 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
378 printf("\tDescription:\t[%s]\n", r->description);
379 printf("\tPort Type:\t" );
381 int comma = 0; /* hack */
383 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
387 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
388 printf( "%sWrite", comma ? ", " : "" );
391 /* These two have slightly different interpretations
392 on 95/98/ME but I'm disregarding that for now */
393 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
394 printf( "%sRedirected", comma ? ", " : "" );
397 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
398 printf( "%sNet-Attached", comma ? ", " : "" );
402 printf( "[Unset]\n" );
404 printf("\tReserved:\t[%d]\n", r->reserved);
408 /****************************************************************************
409 ****************************************************************************/
411 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
412 TALLOC_CTX *mem_ctx, int argc,
418 union spoolss_PortInfo *info;
421 printf("Usage: %s [level]\n", argv[0]);
426 level = atoi(argv[1]);
429 /* Enumerate ports */
431 result = rpccli_spoolss_enumports(cli, mem_ctx,
437 if (W_ERROR_IS_OK(result)) {
440 for (i = 0; i < count; i++) {
443 display_port_info_1(&info[i].info1);
446 display_port_info_2(&info[i].info2);
449 printf("unknown info level %d\n", level);
458 /****************************************************************************
459 ****************************************************************************/
461 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
463 int argc, const char **argv)
465 struct policy_handle pol;
468 uint32_t info_level = 2;
469 union spoolss_PrinterInfo info;
470 struct spoolss_SetPrinterInfoCtr info_ctr;
471 struct spoolss_SetPrinterInfo2 info2;
472 const char *printername, *comment = NULL;
473 struct spoolss_DevmodeContainer devmode_ctr;
474 struct sec_desc_buf secdesc_ctr;
476 if (argc == 1 || argc > 3) {
477 printf("Usage: %s printername comment\n", argv[0]);
482 /* Open a printer handle */
487 ZERO_STRUCT(devmode_ctr);
488 ZERO_STRUCT(secdesc_ctr);
490 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
492 /* get a printer handle */
493 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
497 if (!W_ERROR_IS_OK(result))
500 /* Get printer info */
501 result = rpccli_spoolss_getprinter(cli, mem_ctx,
506 if (!W_ERROR_IS_OK(result))
510 /* Modify the comment. */
511 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
512 info2.comment = comment;
515 info_ctr.info.info2 = &info2;
517 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
524 if (W_ERROR_IS_OK(result))
525 printf("Success in setting comment.\n");
528 if (is_valid_policy_hnd(&pol))
529 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
534 /****************************************************************************
535 ****************************************************************************/
537 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
539 int argc, const char **argv)
541 struct policy_handle pol;
544 uint32_t info_level = 2;
545 union spoolss_PrinterInfo info;
546 const char *printername,
547 *new_printername = NULL;
548 struct spoolss_SetPrinterInfoCtr info_ctr;
549 struct spoolss_SetPrinterInfo2 info2;
550 struct spoolss_DevmodeContainer devmode_ctr;
551 struct sec_desc_buf secdesc_ctr;
553 ZERO_STRUCT(devmode_ctr);
554 ZERO_STRUCT(secdesc_ctr);
556 if (argc == 1 || argc > 3) {
557 printf("Usage: %s printername new_printername\n", argv[0]);
562 /* Open a printer handle */
564 new_printername = argv[2];
567 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
569 /* get a printer handle */
570 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
574 if (!W_ERROR_IS_OK(result))
577 /* Get printer info */
578 result = rpccli_spoolss_getprinter(cli, mem_ctx,
583 if (!W_ERROR_IS_OK(result))
586 /* Modify the printername. */
587 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
588 info2.printername = new_printername;
591 info_ctr.info.info2 = &info2;
593 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
600 if (W_ERROR_IS_OK(result))
601 printf("Success in setting printername.\n");
604 if (is_valid_policy_hnd(&pol))
605 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
610 /****************************************************************************
611 ****************************************************************************/
613 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
615 int argc, const char **argv)
617 struct policy_handle pol;
620 const char *printername;
621 union spoolss_PrinterInfo info;
623 if (argc == 1 || argc > 3) {
624 printf("Usage: %s <printername> [level]\n", argv[0]);
628 /* Open a printer handle */
630 level = atoi(argv[2]);
633 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
635 /* get a printer handle */
637 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
639 SEC_FLAG_MAXIMUM_ALLOWED,
641 if (!W_ERROR_IS_OK(result)) {
645 /* Get printer info */
647 result = rpccli_spoolss_getprinter(cli, mem_ctx,
652 if (!W_ERROR_IS_OK(result)) {
656 /* Display printer info */
659 display_print_info0(&info.info0);
662 display_print_info1(&info.info1);
665 display_print_info2(&info.info2);
668 display_print_info3(&info.info3);
671 display_print_info4(&info.info4);
674 display_print_info5(&info.info5);
677 display_print_info6(&info.info6);
680 display_print_info7(&info.info7);
683 printf("unknown info level %d\n", level);
687 if (is_valid_policy_hnd(&pol)) {
688 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
694 /****************************************************************************
695 ****************************************************************************/
697 static void display_reg_value(struct regval_blob *value)
699 const char *text = NULL;
702 switch(regval_type(value)) {
704 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
705 *((uint32_t *) regval_data_p(value)));
708 blob = data_blob_const(regval_data_p(value), regval_size(value));
709 pull_reg_sz(talloc_tos(), &blob, &text);
710 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
713 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
715 printf("%s: REG_BINARY:", regval_name(value));
717 for (i=0; i<len; i++) {
718 if (hex[i] == '\0') {
733 blob = data_blob_const(regval_data_p(value), regval_size(value));
735 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
736 d_printf("pull_reg_multi_sz failed\n");
740 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
741 for (i=0; values[i] != NULL; i++) {
742 d_printf("%s\n", values[i]);
748 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
753 /****************************************************************************
754 ****************************************************************************/
756 static void display_printer_data(const char *v,
757 enum winreg_Type type,
762 union spoolss_PrinterData r;
763 DATA_BLOB blob = data_blob_const(data, length);
766 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
767 if (!W_ERROR_IS_OK(result)) {
773 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
776 printf("%s: REG_SZ: %s\n", v, r.string);
779 char *hex = hex_encode_talloc(NULL,
780 r.binary.data, r.binary.length);
782 printf("%s: REG_BINARY:", v);
784 for (i=0; i<len; i++) {
785 if (hex[i] == '\0') {
798 printf("%s: REG_MULTI_SZ: ", v);
799 for (i=0; r.string_array[i] != NULL; i++) {
800 printf("%s ", r.string_array[i]);
805 printf("%s: unknown type 0x%02x:\n", v, type);
810 /****************************************************************************
811 ****************************************************************************/
813 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
815 int argc, const char **argv)
817 struct policy_handle pol;
820 const char *valuename;
821 enum winreg_Type type;
826 printf("Usage: %s <printername> <valuename>\n", argv[0]);
827 printf("<printername> of . queries print server\n");
832 /* Open a printer handle */
834 if (strncmp(argv[1], ".", sizeof(".")) == 0)
835 fstrcpy(printername, cli->srv_name_slash);
837 slprintf(printername, sizeof(printername)-1, "%s\\%s",
838 cli->srv_name_slash, argv[1]);
840 /* get a printer handle */
842 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
844 SEC_FLAG_MAXIMUM_ALLOWED,
846 if (!W_ERROR_IS_OK(result))
849 /* Get printer info */
851 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
858 if (!W_ERROR_IS_OK(result))
861 /* Display printer data */
863 display_printer_data(valuename, type, data, needed);
866 if (is_valid_policy_hnd(&pol))
867 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
872 /****************************************************************************
873 ****************************************************************************/
875 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
877 int argc, const char **argv)
879 struct policy_handle pol;
883 const char *valuename, *keyname;
885 enum winreg_Type type;
886 uint8_t *data = NULL;
887 uint32_t offered = 0;
891 printf("Usage: %s <printername> <keyname> <valuename>\n",
893 printf("<printername> of . queries print server\n");
899 /* Open a printer handle */
901 if (strncmp(argv[1], ".", sizeof(".")) == 0)
902 fstrcpy(printername, cli->srv_name_slash);
904 slprintf(printername, sizeof(printername)-1, "%s\\%s",
905 cli->srv_name_slash, argv[1]);
907 /* get a printer handle */
909 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
911 SEC_FLAG_MAXIMUM_ALLOWED,
913 if (!W_ERROR_IS_OK(result))
916 /* Get printer info */
918 data = talloc_zero_array(mem_ctx, uint8_t, offered);
923 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
932 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
934 data = talloc_zero_array(mem_ctx, uint8_t, offered);
938 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
949 if (!NT_STATUS_IS_OK(status)) {
953 if (!W_ERROR_IS_OK(result))
956 /* Display printer data */
958 display_printer_data(valuename, type, data, needed);
962 if (is_valid_policy_hnd(&pol))
963 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
968 /****************************************************************************
969 ****************************************************************************/
971 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
977 printf("Printer Driver Info 1:\n");
978 printf("\tDriver Name: [%s]\n", r->driver_name);
982 /****************************************************************************
983 ****************************************************************************/
985 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
991 printf("Printer Driver Info 2:\n");
992 printf("\tVersion: [%x]\n", r->version);
993 printf("\tDriver Name: [%s]\n", r->driver_name);
994 printf("\tArchitecture: [%s]\n", r->architecture);
995 printf("\tDriver Path: [%s]\n", r->driver_path);
996 printf("\tDatafile: [%s]\n", r->data_file);
997 printf("\tConfigfile: [%s]\n", r->config_file);
1001 /****************************************************************************
1002 ****************************************************************************/
1004 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1012 printf("Printer Driver Info 3:\n");
1013 printf("\tVersion: [%x]\n", r->version);
1014 printf("\tDriver Name: [%s]\n", r->driver_name);
1015 printf("\tArchitecture: [%s]\n", r->architecture);
1016 printf("\tDriver Path: [%s]\n", r->driver_path);
1017 printf("\tDatafile: [%s]\n", r->data_file);
1018 printf("\tConfigfile: [%s]\n", r->config_file);
1019 printf("\tHelpfile: [%s]\n", r->help_file);
1021 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1022 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1025 printf("\tMonitorname: [%s]\n", r->monitor_name);
1026 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1030 /****************************************************************************
1031 ****************************************************************************/
1033 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1041 printf("Printer Driver Info 4:\n");
1042 printf("\tVersion: [%x]\n", r->version);
1043 printf("\tDriver Name: [%s]\n", r->driver_name);
1044 printf("\tArchitecture: [%s]\n", r->architecture);
1045 printf("\tDriver Path: [%s]\n", r->driver_path);
1046 printf("\tDatafile: [%s]\n", r->data_file);
1047 printf("\tConfigfile: [%s]\n", r->config_file);
1048 printf("\tHelpfile: [%s]\n", r->help_file);
1050 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1051 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1054 printf("\tMonitorname: [%s]\n", r->monitor_name);
1055 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1057 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1058 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1063 /****************************************************************************
1064 ****************************************************************************/
1066 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1072 printf("Printer Driver Info 5:\n");
1073 printf("\tVersion: [%x]\n", r->version);
1074 printf("\tDriver Name: [%s]\n", r->driver_name);
1075 printf("\tArchitecture: [%s]\n", r->architecture);
1076 printf("\tDriver Path: [%s]\n", r->driver_path);
1077 printf("\tDatafile: [%s]\n", r->data_file);
1078 printf("\tConfigfile: [%s]\n", r->config_file);
1079 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1080 printf("\tConfig Version: [0x%x]\n", r->config_version);
1081 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1085 /****************************************************************************
1086 ****************************************************************************/
1088 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1096 printf("Printer Driver Info 6:\n");
1097 printf("\tVersion: [%x]\n", r->version);
1098 printf("\tDriver Name: [%s]\n", r->driver_name);
1099 printf("\tArchitecture: [%s]\n", r->architecture);
1100 printf("\tDriver Path: [%s]\n", r->driver_path);
1101 printf("\tDatafile: [%s]\n", r->data_file);
1102 printf("\tConfigfile: [%s]\n", r->config_file);
1103 printf("\tHelpfile: [%s]\n", r->help_file);
1105 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1106 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1109 printf("\tMonitorname: [%s]\n", r->monitor_name);
1110 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1112 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1113 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1116 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1117 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1118 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1119 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1120 printf("\tHardware ID: [%s]\n", r->hardware_id);
1121 printf("\tProvider: [%s]\n", r->provider);
1126 /****************************************************************************
1127 ****************************************************************************/
1129 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1137 printf("Printer Driver Info 8:\n");
1138 printf("\tVersion: [%x]\n", r->version);
1139 printf("\tDriver Name: [%s]\n", r->driver_name);
1140 printf("\tArchitecture: [%s]\n", r->architecture);
1141 printf("\tDriver Path: [%s]\n", r->driver_path);
1142 printf("\tDatafile: [%s]\n", r->data_file);
1143 printf("\tConfigfile: [%s]\n", r->config_file);
1144 printf("\tHelpfile: [%s]\n", r->help_file);
1145 printf("\tMonitorname: [%s]\n", r->monitor_name);
1146 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1148 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1149 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1152 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1153 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1156 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1157 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1158 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1159 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1160 printf("\tHardware ID: [%s]\n", r->hardware_id);
1161 printf("\tProvider: [%s]\n", r->provider);
1162 printf("\tPrint Processor: [%s]\n", r->print_processor);
1163 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1164 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1165 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1167 printf("\tInf Path: [%s]\n", r->inf_path);
1168 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1169 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1170 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1172 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1173 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1174 (long long unsigned int)r->min_inbox_driver_ver_version);
1179 /****************************************************************************
1180 ****************************************************************************/
1182 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1183 TALLOC_CTX *mem_ctx,
1184 int argc, const char **argv)
1186 struct policy_handle pol;
1189 const char *printername;
1191 bool success = false;
1192 union spoolss_DriverInfo info;
1193 uint32_t server_major_version;
1194 uint32_t server_minor_version;
1196 if ((argc == 1) || (argc > 3)) {
1197 printf("Usage: %s <printername> [level]\n", argv[0]);
1201 /* get the arguments need to open the printer handle */
1203 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1206 level = atoi(argv[2]);
1209 /* Open a printer handle */
1211 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1215 if (!W_ERROR_IS_OK(werror)) {
1216 printf("Error opening printer handle for %s!\n", printername);
1220 /* loop through and print driver info level for each architecture */
1222 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1224 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1226 archi_table[i].long_archi,
1229 archi_table[i].version,
1232 &server_major_version,
1233 &server_minor_version);
1234 if (!W_ERROR_IS_OK(werror)) {
1238 /* need at least one success */
1242 printf("\n[%s]\n", archi_table[i].long_archi);
1246 display_print_driver1(&info.info1);
1249 display_print_driver2(&info.info2);
1252 display_print_driver3(&info.info3);
1255 display_print_driver4(&info.info4);
1258 display_print_driver5(&info.info5);
1261 display_print_driver6(&info.info6);
1264 display_print_driver8(&info.info8);
1267 printf("unknown info level %d\n", level);
1274 if (is_valid_policy_hnd(&pol)) {
1275 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1285 /****************************************************************************
1286 ****************************************************************************/
1288 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1289 TALLOC_CTX *mem_ctx,
1290 const char *architecture,
1295 union spoolss_DriverInfo *info = NULL;
1298 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1299 cli->srv_name_slash,
1306 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1307 printf("Server does not support environment [%s]\n",
1316 if (!W_ERROR_IS_OK(werror)) {
1317 printf("Error getting driver for environment [%s] - %s\n",
1318 architecture, win_errstr(werror));
1322 printf("\n[%s]\n", architecture);
1326 for (j=0; j < count; j++) {
1327 display_print_driver1(&info[j].info1);
1331 for (j=0; j < count; j++) {
1332 display_print_driver2(&info[j].info2);
1336 for (j=0; j < count; j++) {
1337 display_print_driver3(&info[j].info3);
1341 for (j=0; j < count; j++) {
1342 display_print_driver4(&info[j].info4);
1346 for (j=0; j < count; j++) {
1347 display_print_driver5(&info[j].info5);
1351 for (j=0; j < count; j++) {
1352 display_print_driver6(&info[j].info6);
1356 for (j=0; j < count; j++) {
1357 display_print_driver8(&info[j].info8);
1361 printf("unknown info level %d\n", level);
1362 return WERR_UNKNOWN_LEVEL;
1368 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1369 TALLOC_CTX *mem_ctx,
1370 int argc, const char **argv)
1372 WERROR werror = WERR_OK;
1375 const char *architecture = NULL;
1378 printf("Usage: enumdrivers [level] [architecture]\n");
1383 level = atoi(argv[1]);
1387 architecture = argv[2];
1391 return enum_driver_by_architecture(cli, mem_ctx,
1396 /* loop through and print driver info level for each architecture */
1397 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1398 /* check to see if we already asked for this architecture string */
1400 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1404 werror = enum_driver_by_architecture(cli, mem_ctx,
1405 archi_table[i].long_archi,
1407 if (!W_ERROR_IS_OK(werror)) {
1415 /****************************************************************************
1416 ****************************************************************************/
1418 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1420 printf("\tDirectory Name:[%s]\n", r->directory_name);
1423 /****************************************************************************
1424 ****************************************************************************/
1426 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1427 TALLOC_CTX *mem_ctx,
1428 int argc, const char **argv)
1432 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1435 union spoolss_DriverDirectoryInfo info;
1439 printf("Usage: %s [environment]\n", argv[0]);
1443 /* Get the arguments need to open the printer handle */
1449 /* Get the directory. Only use Info level 1 */
1451 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1452 cli->srv_name_slash,
1460 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1462 buffer = data_blob_talloc_zero(mem_ctx, needed);
1464 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1465 cli->srv_name_slash,
1475 if (W_ERROR_IS_OK(result)) {
1476 display_printdriverdir_1(&info.info1);
1482 /****************************************************************************
1483 ****************************************************************************/
1485 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1486 struct spoolss_AddDriverInfo3 *info,
1492 for (i=0; archi_table[i].long_archi != NULL; i++)
1494 if (strcmp(arch, archi_table[i].short_archi) == 0)
1496 info->version = archi_table[i].version;
1497 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1502 if (archi_table[i].long_archi == NULL)
1504 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1511 /**************************************************************************
1512 wrapper for strtok to get the next parameter from a delimited list.
1513 Needed to handle the empty parameter string denoted by "NULL"
1514 *************************************************************************/
1516 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1517 const char *delim, const char **dest,
1522 /* get the next token */
1523 ptr = strtok_r(str, delim, saveptr);
1525 /* a string of 'NULL' is used to represent an empty
1526 parameter because two consecutive delimiters
1527 will not return an empty string. See man strtok(3)
1529 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1534 *dest = talloc_strdup(mem_ctx, ptr);
1540 /********************************************************************************
1541 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1542 string in the form of
1543 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1544 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1545 <Default Data Type>:<Comma Separated list of Files>
1546 *******************************************************************************/
1548 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1553 char *saveptr = NULL;
1554 struct spoolss_StringArray *deps;
1555 const char **file_array = NULL;
1558 /* fill in the UNISTR fields */
1559 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1560 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1561 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1562 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1563 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1564 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1565 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1567 /* <Comma Separated List of Dependent Files> */
1568 /* save the beginning of the string */
1569 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1572 /* begin to strip out each filename */
1573 str = strtok_r(str, ",", &saveptr);
1575 /* no dependent files, we are done */
1580 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1585 while (str != NULL) {
1586 add_string_to_array(deps, str, &file_array, &count);
1587 str = strtok_r(NULL, ",", &saveptr);
1590 deps->string = talloc_zero_array(deps, const char *, count + 1);
1591 if (!deps->string) {
1595 for (i=0; i < count; i++) {
1596 deps->string[i] = file_array[i];
1599 r->dependent_files = deps;
1604 /****************************************************************************
1605 ****************************************************************************/
1607 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1608 TALLOC_CTX *mem_ctx,
1609 int argc, const char **argv)
1614 struct spoolss_AddDriverInfoCtr info_ctr;
1615 struct spoolss_AddDriverInfo3 info3;
1619 /* parse the command arguments */
1620 if (argc != 3 && argc != 4)
1622 printf ("Usage: %s <Environment> \\\n", argv[0]);
1623 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1624 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1625 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1626 printf ("\t[version]\n");
1631 /* Fill in the spoolss_AddDriverInfo3 struct */
1634 arch = cmd_spoolss_get_short_archi(argv[1]);
1636 printf ("Error Unknown architechture [%s]\n", argv[1]);
1637 return WERR_INVALID_PARAM;
1640 set_drv_info_3_env(mem_ctx, &info3, arch);
1642 driver_args = talloc_strdup( mem_ctx, argv[2] );
1643 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1645 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1646 return WERR_INVALID_PARAM;
1649 /* if printer driver version specified, override the default version
1650 * used by the architecture. This allows installation of Windows
1651 * 2000 (version 3) printer drivers. */
1654 info3.version = atoi(argv[3]);
1658 info_ctr.level = level;
1659 info_ctr.info.info3 = &info3;
1661 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1662 cli->srv_name_slash,
1665 if (!NT_STATUS_IS_OK(status)) {
1666 return ntstatus_to_werror(status);
1668 if (W_ERROR_IS_OK(result)) {
1669 printf ("Printer Driver %s successfully installed.\n",
1677 /****************************************************************************
1678 ****************************************************************************/
1680 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1681 TALLOC_CTX *mem_ctx,
1682 int argc, const char **argv)
1685 struct spoolss_SetPrinterInfoCtr info_ctr;
1686 struct spoolss_SetPrinterInfo2 info2;
1688 /* parse the command arguments */
1691 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1695 /* Fill in the DRIVER_INFO_2 struct */
1698 info2.printername = argv[1];
1699 info2.drivername = argv[3];
1700 info2.sharename = argv[2];
1701 info2.portname = argv[4];
1702 info2.comment = "Created by rpcclient";
1703 info2.printprocessor = "winprint";
1704 info2.datatype = "RAW";
1705 info2.devmode_ptr = 0;
1706 info2.secdesc_ptr = 0;
1707 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1709 info2.defaultpriority = 0;
1710 info2.starttime = 0;
1711 info2.untiltime = 0;
1713 /* These three fields must not be used by AddPrinter()
1714 as defined in the MS Platform SDK documentation..
1718 info2.averageppm = 0;
1722 info_ctr.info.info2 = &info2;
1724 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1726 if (W_ERROR_IS_OK(result))
1727 printf ("Printer %s successfully installed.\n", argv[1]);
1732 /****************************************************************************
1733 ****************************************************************************/
1735 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1736 TALLOC_CTX *mem_ctx,
1737 int argc, const char **argv)
1739 struct policy_handle pol;
1743 const char *printername;
1744 union spoolss_PrinterInfo info;
1745 struct spoolss_SetPrinterInfoCtr info_ctr;
1746 struct spoolss_SetPrinterInfo2 info2;
1747 struct spoolss_DevmodeContainer devmode_ctr;
1748 struct sec_desc_buf secdesc_ctr;
1750 ZERO_STRUCT(devmode_ctr);
1751 ZERO_STRUCT(secdesc_ctr);
1753 /* parse the command arguments */
1756 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1760 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1762 /* Get a printer handle */
1764 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1768 if (!W_ERROR_IS_OK(result))
1771 /* Get printer info */
1773 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1778 if (!W_ERROR_IS_OK(result)) {
1779 printf ("Unable to retrieve printer information!\n");
1783 /* Set the printer driver */
1785 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1786 info2.drivername = argv[2];
1789 info_ctr.info.info2 = &info2;
1791 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1798 if (!W_ERROR_IS_OK(result)) {
1799 printf("SetPrinter call failed!\n");
1803 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1808 if (is_valid_policy_hnd(&pol))
1809 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1815 /****************************************************************************
1816 ****************************************************************************/
1818 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1819 TALLOC_CTX *mem_ctx,
1820 int argc, const char **argv)
1822 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1828 const char *arch = NULL;
1829 uint32_t delete_flags = 0;
1831 /* parse the command arguments */
1832 if (argc < 2 || argc > 4) {
1833 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1840 vers = atoi (argv[3]);
1843 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1846 /* delete the driver for all architectures */
1847 for (i=0; archi_table[i].long_archi; i++) {
1849 if (arch && !strequal( archi_table[i].long_archi, arch))
1852 if (vers >= 0 && archi_table[i].version != vers)
1855 /* make the call to remove the driver */
1856 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1857 cli->srv_name_slash,
1858 archi_table[i].long_archi,
1861 archi_table[i].version,
1864 if ( !W_ERROR_IS_OK(result) )
1866 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1867 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1868 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1873 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1874 archi_table[i].long_archi, archi_table[i].version);
1883 /****************************************************************************
1884 ****************************************************************************/
1886 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1887 TALLOC_CTX *mem_ctx,
1888 int argc, const char **argv)
1890 WERROR result = WERR_OK;
1894 /* parse the command arguments */
1896 printf ("Usage: %s <driver>\n", argv[0]);
1900 /* delete the driver for all architectures */
1901 for (i=0; archi_table[i].long_archi; i++) {
1902 /* make the call to remove the driver */
1903 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1904 cli->srv_name_slash,
1905 archi_table[i].long_archi,
1908 if (!NT_STATUS_IS_OK(status)) {
1911 if ( !W_ERROR_IS_OK(result) ) {
1912 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1913 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1914 argv[1], archi_table[i].long_archi,
1918 printf ("Driver %s removed for arch [%s].\n", argv[1],
1919 archi_table[i].long_archi);
1926 /****************************************************************************
1927 ****************************************************************************/
1929 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1930 TALLOC_CTX *mem_ctx,
1931 int argc, const char **argv)
1935 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1938 union spoolss_PrintProcessorDirectoryInfo info;
1941 /* parse the command arguments */
1943 printf ("Usage: %s [environment]\n", argv[0]);
1948 environment = argv[1];
1951 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1952 cli->srv_name_slash,
1960 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1962 buffer = data_blob_talloc_zero(mem_ctx, needed);
1964 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1965 cli->srv_name_slash,
1975 if (W_ERROR_IS_OK(result)) {
1976 printf("%s\n", info.info1.directory_name);
1982 /****************************************************************************
1983 ****************************************************************************/
1985 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1986 int argc, const char **argv)
1988 struct policy_handle handle;
1991 const char *printername;
1992 union spoolss_AddFormInfo info;
1993 struct spoolss_AddFormInfo1 info1;
1994 struct spoolss_AddFormInfo2 info2;
1997 /* Parse the command arguments */
1999 if (argc < 3 || argc > 5) {
2000 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2004 /* Get a printer handle */
2006 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2008 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2012 if (!W_ERROR_IS_OK(werror))
2015 /* Dummy up some values for the form data */
2018 level = atoi(argv[3]);
2023 info1.flags = SPOOLSS_FORM_USER;
2024 info1.form_name = argv[2];
2025 info1.size.width = 100;
2026 info1.size.height = 100;
2027 info1.area.left = 0;
2028 info1.area.top = 10;
2029 info1.area.right = 20;
2030 info1.area.bottom = 30;
2032 info.info1 = &info1;
2036 info2.flags = SPOOLSS_FORM_USER;
2037 info2.form_name = argv[2];
2038 info2.size.width = 100;
2039 info2.size.height = 100;
2040 info2.area.left = 0;
2041 info2.area.top = 10;
2042 info2.area.right = 20;
2043 info2.area.bottom = 30;
2044 info2.keyword = argv[2];
2045 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2046 info2.mui_dll = NULL;
2047 info2.ressource_id = 0;
2048 info2.display_name = argv[2];
2051 info.info2 = &info2;
2059 status = rpccli_spoolss_AddForm(cli, mem_ctx,
2066 if (is_valid_policy_hnd(&handle))
2067 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2072 /****************************************************************************
2073 ****************************************************************************/
2075 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2076 int argc, const char **argv)
2078 struct policy_handle handle;
2081 const char *printername;
2082 union spoolss_AddFormInfo info;
2083 struct spoolss_AddFormInfo1 info1;
2085 /* Parse the command arguments */
2088 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2092 /* Get a printer handle */
2094 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2096 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2098 SEC_FLAG_MAXIMUM_ALLOWED,
2100 if (!W_ERROR_IS_OK(werror))
2103 /* Dummy up some values for the form data */
2105 info1.flags = SPOOLSS_FORM_PRINTER;
2106 info1.size.width = 100;
2107 info1.size.height = 100;
2108 info1.area.left = 0;
2109 info1.area.top = 1000;
2110 info1.area.right = 2000;
2111 info1.area.bottom = 3000;
2112 info1.form_name = argv[2];
2114 info.info1 = &info1;
2118 status = rpccli_spoolss_SetForm(cli, mem_ctx,
2126 if (is_valid_policy_hnd(&handle))
2127 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2132 /****************************************************************************
2133 ****************************************************************************/
2135 static const char *get_form_flag(int form_flag)
2137 switch (form_flag) {
2138 case SPOOLSS_FORM_USER:
2140 case SPOOLSS_FORM_BUILTIN:
2141 return "FORM_BUILTIN";
2142 case SPOOLSS_FORM_PRINTER:
2143 return "FORM_PRINTER";
2149 /****************************************************************************
2150 ****************************************************************************/
2152 static void display_form_info1(struct spoolss_FormInfo1 *r)
2155 "\tflag: %s (%d)\n" \
2156 "\twidth: %d, length: %d\n" \
2157 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2158 r->form_name, get_form_flag(r->flags), r->flags,
2159 r->size.width, r->size.height,
2160 r->area.left, r->area.right,
2161 r->area.top, r->area.bottom);
2164 /****************************************************************************
2165 ****************************************************************************/
2167 static void display_form_info2(struct spoolss_FormInfo2 *r)
2170 "\tflag: %s (%d)\n" \
2171 "\twidth: %d, length: %d\n" \
2172 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2173 r->form_name, get_form_flag(r->flags), r->flags,
2174 r->size.width, r->size.height,
2175 r->area.left, r->area.right,
2176 r->area.top, r->area.bottom);
2177 printf("\tkeyword: %s\n", r->keyword);
2178 printf("\tstring_type: 0x%08x\n", r->string_type);
2179 printf("\tmui_dll: %s\n", r->mui_dll);
2180 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2181 printf("\tdisplay_name: %s\n", r->display_name);
2182 printf("\tlang_id: %d\n", r->lang_id);
2186 /****************************************************************************
2187 ****************************************************************************/
2189 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2190 int argc, const char **argv)
2192 struct policy_handle handle;
2195 const char *printername;
2197 uint32_t offered = 0;
2198 union spoolss_FormInfo info;
2202 /* Parse the command arguments */
2204 if (argc < 3 || argc > 5) {
2205 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2209 /* Get a printer handle */
2211 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2213 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2215 SEC_FLAG_MAXIMUM_ALLOWED,
2217 if (!W_ERROR_IS_OK(werror))
2221 level = atoi(argv[3]);
2226 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2235 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2236 buffer = data_blob_talloc_zero(mem_ctx, needed);
2238 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2249 if (!NT_STATUS_IS_OK(status)) {
2255 display_form_info1(&info.info1);
2258 display_form_info2(&info.info2);
2263 if (is_valid_policy_hnd(&handle))
2264 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2269 /****************************************************************************
2270 ****************************************************************************/
2272 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2273 TALLOC_CTX *mem_ctx, int argc,
2276 struct policy_handle handle;
2279 const char *printername;
2281 /* Parse the command arguments */
2284 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2288 /* Get a printer handle */
2290 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2292 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2294 SEC_FLAG_MAXIMUM_ALLOWED,
2296 if (!W_ERROR_IS_OK(werror))
2299 /* Delete the form */
2301 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2305 if (!NT_STATUS_IS_OK(status)) {
2306 return ntstatus_to_werror(status);
2310 if (is_valid_policy_hnd(&handle))
2311 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2316 /****************************************************************************
2317 ****************************************************************************/
2319 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2320 TALLOC_CTX *mem_ctx, int argc,
2323 struct policy_handle handle;
2325 const char *printername;
2326 uint32_t num_forms, level = 1, i;
2327 union spoolss_FormInfo *forms;
2329 /* Parse the command arguments */
2331 if (argc < 2 || argc > 4) {
2332 printf ("Usage: %s <printer> [level]\n", argv[0]);
2336 /* Get a printer handle */
2338 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2340 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2342 SEC_FLAG_MAXIMUM_ALLOWED,
2344 if (!W_ERROR_IS_OK(werror))
2348 level = atoi(argv[2]);
2351 /* Enumerate forms */
2353 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2360 if (!W_ERROR_IS_OK(werror))
2363 /* Display output */
2365 for (i = 0; i < num_forms; i++) {
2368 display_form_info1(&forms[i].info1);
2371 display_form_info2(&forms[i].info2);
2377 if (is_valid_policy_hnd(&handle))
2378 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2383 /****************************************************************************
2384 ****************************************************************************/
2386 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2387 TALLOC_CTX *mem_ctx,
2388 int argc, const char **argv)
2392 const char *printername;
2393 struct policy_handle pol;
2394 union spoolss_PrinterInfo info;
2395 enum winreg_Type type;
2396 union spoolss_PrinterData data;
2399 /* parse the command arguments */
2401 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2402 " <value> <data>\n",
2407 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2411 if (strequal(argv[2], "string")) {
2415 if (strequal(argv[2], "binary")) {
2419 if (strequal(argv[2], "dword")) {
2423 if (strequal(argv[2], "multistring")) {
2424 type = REG_MULTI_SZ;
2427 if (type == REG_NONE) {
2428 printf("Unknown data type: %s\n", argv[2]);
2429 result = WERR_INVALID_PARAM;
2433 /* get a printer handle */
2435 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2437 SEC_FLAG_MAXIMUM_ALLOWED,
2439 if (!W_ERROR_IS_OK(result)) {
2443 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2448 if (!W_ERROR_IS_OK(result)) {
2452 printf("%s\n", current_timestring(mem_ctx, true));
2453 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2455 /* Set the printer data */
2459 data.string = talloc_strdup(mem_ctx, argv[4]);
2460 W_ERROR_HAVE_NO_MEMORY(data.string);
2463 data.value = strtoul(argv[4], NULL, 10);
2466 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2468 case REG_MULTI_SZ: {
2470 const char **strings = NULL;
2472 for (i=4; i<argc; i++) {
2473 if (strcmp(argv[i], "NULL") == 0) {
2476 if (!add_string_to_array(mem_ctx, argv[i],
2479 result = WERR_NOMEM;
2483 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2484 if (!data.string_array) {
2485 result = WERR_NOMEM;
2488 for (i=0; i < num_strings; i++) {
2489 data.string_array[i] = strings[i];
2494 printf("Unknown data type: %s\n", argv[2]);
2495 result = WERR_INVALID_PARAM;
2499 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2500 if (!W_ERROR_IS_OK(result)) {
2504 status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
2506 argv[3], /* value_name */
2511 if (!W_ERROR_IS_OK(result)) {
2512 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2515 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2517 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2522 if (!W_ERROR_IS_OK(result)) {
2526 printf("%s\n", current_timestring(mem_ctx, true));
2527 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2531 if (is_valid_policy_hnd(&pol)) {
2532 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2538 /****************************************************************************
2539 ****************************************************************************/
2541 static void display_job_info1(struct spoolss_JobInfo1 *r)
2543 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2544 r->user_name, r->document_name, r->text_status, r->pages_printed,
2548 /****************************************************************************
2549 ****************************************************************************/
2551 static void display_job_info2(struct spoolss_JobInfo2 *r)
2553 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2554 r->position, r->job_id,
2555 r->user_name, r->document_name, r->text_status, r->pages_printed,
2556 r->total_pages, r->size);
2559 /****************************************************************************
2560 ****************************************************************************/
2562 static void display_job_info3(struct spoolss_JobInfo3 *r)
2564 printf("jobid[%d], next_jobid[%d]\n",
2565 r->job_id, r->next_job_id);
2568 /****************************************************************************
2569 ****************************************************************************/
2571 static void display_job_info4(struct spoolss_JobInfo4 *r)
2573 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2574 r->position, r->job_id,
2575 r->user_name, r->document_name, r->text_status, r->pages_printed,
2576 r->total_pages, r->size, r->size_high);
2579 /****************************************************************************
2580 ****************************************************************************/
2582 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2583 TALLOC_CTX *mem_ctx, int argc,
2587 uint32_t level = 1, count, i;
2588 const char *printername;
2589 struct policy_handle hnd;
2590 union spoolss_JobInfo *info;
2592 if (argc < 2 || argc > 3) {
2593 printf("Usage: %s printername [level]\n", argv[0]);
2598 level = atoi(argv[2]);
2601 /* Open printer handle */
2603 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2605 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2607 SEC_FLAG_MAXIMUM_ALLOWED,
2609 if (!W_ERROR_IS_OK(result))
2612 /* Enumerate ports */
2614 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2622 if (!W_ERROR_IS_OK(result)) {
2626 for (i = 0; i < count; i++) {
2629 display_job_info1(&info[i].info1);
2632 display_job_info2(&info[i].info2);
2635 d_printf("unknown info level %d\n", level);
2641 if (is_valid_policy_hnd(&hnd)) {
2642 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2648 /****************************************************************************
2649 ****************************************************************************/
2651 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2652 TALLOC_CTX *mem_ctx, int argc,
2656 const char *printername;
2657 struct policy_handle hnd;
2660 union spoolss_JobInfo info;
2662 if (argc < 3 || argc > 4) {
2663 printf("Usage: %s printername job_id [level]\n", argv[0]);
2667 job_id = atoi(argv[2]);
2670 level = atoi(argv[3]);
2673 /* Open printer handle */
2675 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2677 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2679 SEC_FLAG_MAXIMUM_ALLOWED,
2681 if (!W_ERROR_IS_OK(result)) {
2685 /* Enumerate ports */
2687 result = rpccli_spoolss_getjob(cli, mem_ctx,
2694 if (!W_ERROR_IS_OK(result)) {
2700 display_job_info1(&info.info1);
2703 display_job_info2(&info.info2);
2706 display_job_info3(&info.info3);
2709 display_job_info4(&info.info4);
2712 d_printf("unknown info level %d\n", level);
2717 if (is_valid_policy_hnd(&hnd)) {
2718 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2724 /****************************************************************************
2725 ****************************************************************************/
2729 enum spoolss_JobControl val;
2731 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2732 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2733 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2734 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2735 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2736 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2737 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2738 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2739 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2742 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2746 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2747 if (strequal(cmdvals[i].name, cmd)) {
2748 return cmdvals[i].val;
2751 return (enum spoolss_JobControl)atoi(cmd);
2754 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2755 TALLOC_CTX *mem_ctx, int argc,
2760 const char *printername;
2761 struct policy_handle hnd;
2763 enum spoolss_JobControl command;
2766 printf("Usage: %s printername job_id command\n", argv[0]);
2767 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2768 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2772 job_id = atoi(argv[2]);
2773 command = parse_setjob_command(argv[3]);
2775 /* Open printer handle */
2777 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2779 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2781 SEC_FLAG_MAXIMUM_ALLOWED,
2783 if (!W_ERROR_IS_OK(result)) {
2789 status = rpccli_spoolss_SetJob(cli, mem_ctx,
2796 if (!W_ERROR_IS_OK(result)) {
2801 if (is_valid_policy_hnd(&hnd)) {
2802 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2808 /****************************************************************************
2809 ****************************************************************************/
2811 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2812 TALLOC_CTX *mem_ctx, int argc,
2818 const char *printername;
2819 struct policy_handle hnd;
2820 uint32_t value_offered = 0;
2821 const char *value_name = NULL;
2822 uint32_t value_needed;
2823 enum winreg_Type type;
2824 uint8_t *data = NULL;
2825 uint32_t data_offered = 0;
2826 uint32_t data_needed;
2829 printf("Usage: %s printername\n", argv[0]);
2833 /* Open printer handle */
2835 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2837 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2839 SEC_FLAG_MAXIMUM_ALLOWED,
2841 if (!W_ERROR_IS_OK(result)) {
2845 /* Enumerate data */
2847 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2859 data_offered = data_needed;
2860 value_offered = value_needed;
2861 data = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2862 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2864 while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2866 status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
2877 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
2878 struct regval_blob *v;
2880 v = regval_compose(talloc_tos(),
2886 result = WERR_NOMEM;
2890 display_reg_value(v);
2895 if (W_ERROR_V(result) == ERRnomoreitems) {
2896 result = W_ERROR(ERRsuccess);
2900 if (is_valid_policy_hnd(&hnd)) {
2901 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2907 /****************************************************************************
2908 ****************************************************************************/
2910 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2911 TALLOC_CTX *mem_ctx, int argc,
2916 const char *printername;
2917 struct policy_handle hnd;
2919 struct spoolss_PrinterEnumValues *info;
2922 printf("Usage: %s printername <keyname>\n", argv[0]);
2926 /* Open printer handle */
2928 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2930 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2932 SEC_FLAG_MAXIMUM_ALLOWED,
2934 if (!W_ERROR_IS_OK(result)) {
2938 /* Enumerate subkeys */
2940 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
2946 if (!W_ERROR_IS_OK(result)) {
2950 for (i=0; i < count; i++) {
2951 display_printer_data(info[i].value_name,
2954 info[i].data->length);
2958 if (is_valid_policy_hnd(&hnd)) {
2959 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2965 /****************************************************************************
2966 ****************************************************************************/
2968 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
2969 TALLOC_CTX *mem_ctx, int argc,
2973 const char *printername;
2974 const char *keyname = NULL;
2975 struct policy_handle hnd;
2976 const char **key_buffer = NULL;
2978 uint32_t offered = 0;
2980 if (argc < 2 || argc > 4) {
2981 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
2992 offered = atoi(argv[3]);
2995 /* Open printer handle */
2997 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2999 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3001 SEC_FLAG_MAXIMUM_ALLOWED,
3003 if (!W_ERROR_IS_OK(result)) {
3007 /* Enumerate subkeys */
3009 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3015 if (!W_ERROR_IS_OK(result)) {
3019 for (i=0; key_buffer && key_buffer[i]; i++) {
3020 printf("%s\n", key_buffer[i]);
3025 if (is_valid_policy_hnd(&hnd)) {
3026 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3032 /****************************************************************************
3033 ****************************************************************************/
3035 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3036 TALLOC_CTX *mem_ctx, int argc,
3039 const char *printername;
3040 const char *clientname;
3041 struct policy_handle hnd;
3044 struct spoolss_NotifyOption option;
3047 printf("Usage: %s printername\n", argv[0]);
3054 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3056 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3058 SEC_FLAG_MAXIMUM_ALLOWED,
3060 if (!W_ERROR_IS_OK(result)) {
3061 printf("Error opening %s\n", argv[1]);
3065 /* Create spool options */
3070 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3071 if (option.types == NULL) {
3072 result = WERR_NOMEM;
3076 option.types[0].type = PRINTER_NOTIFY_TYPE;
3077 option.types[0].count = 1;
3078 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3079 if (option.types[0].fields == NULL) {
3080 result = WERR_NOMEM;
3083 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3085 option.types[1].type = JOB_NOTIFY_TYPE;
3086 option.types[1].count = 1;
3087 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3088 if (option.types[1].fields == NULL) {
3089 result = WERR_NOMEM;
3092 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3094 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3096 result = WERR_NOMEM;
3102 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
3110 if (!W_ERROR_IS_OK(result)) {
3111 printf("Error rffpcnex %s\n", argv[1]);
3116 if (is_valid_policy_hnd(&hnd))
3117 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
3122 /****************************************************************************
3123 ****************************************************************************/
3125 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3126 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3128 union spoolss_PrinterInfo info1, info2;
3130 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3132 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3133 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3138 if ( !W_ERROR_IS_OK(werror) ) {
3139 printf("failed (%s)\n", win_errstr(werror));
3140 talloc_destroy(mem_ctx);
3145 printf("Retrieving printer properties for %s...", cli2->desthost);
3146 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3151 if ( !W_ERROR_IS_OK(werror) ) {
3152 printf("failed (%s)\n", win_errstr(werror));
3153 talloc_destroy(mem_ctx);
3158 talloc_destroy(mem_ctx);
3163 /****************************************************************************
3164 ****************************************************************************/
3166 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3167 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3169 union spoolss_PrinterInfo info1, info2;
3171 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3172 struct security_descriptor *sd1, *sd2;
3176 printf("Retrieving printer security for %s...", cli1->desthost);
3177 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3182 if ( !W_ERROR_IS_OK(werror) ) {
3183 printf("failed (%s)\n", win_errstr(werror));
3189 printf("Retrieving printer security for %s...", cli2->desthost);
3190 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3195 if ( !W_ERROR_IS_OK(werror) ) {
3196 printf("failed (%s)\n", win_errstr(werror));
3205 sd1 = info1.info3.secdesc;
3206 sd2 = info2.info3.secdesc;
3208 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3209 printf("NULL secdesc!\n");
3214 if (!security_descriptor_equal( sd1, sd2 ) ) {
3215 printf("Security Descriptors *not* equal!\n");
3220 printf("Security descriptors match\n");
3223 talloc_destroy(mem_ctx);
3228 /****************************************************************************
3229 ****************************************************************************/
3231 extern struct user_auth_info *rpcclient_auth_info;
3233 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3234 TALLOC_CTX *mem_ctx, int argc,
3237 const char *printername;
3238 char *printername_path = NULL;
3239 struct cli_state *cli_server2 = NULL;
3240 struct rpc_pipe_client *cli2 = NULL;
3241 struct policy_handle hPrinter1, hPrinter2;
3246 printf("Usage: %s <printer> <server>\n", argv[0]);
3250 printername = argv[1];
3252 /* first get the connection to the remote server */
3254 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3257 get_cmdline_auth_info_username(rpcclient_auth_info),
3259 get_cmdline_auth_info_password(rpcclient_auth_info),
3260 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3261 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
3263 if ( !NT_STATUS_IS_OK(nt_status) )
3264 return WERR_GENERAL_FAILURE;
3266 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3268 if (!NT_STATUS_IS_OK(nt_status)) {
3269 printf("failed to open spoolss pipe on server %s (%s)\n",
3270 argv[2], nt_errstr(nt_status));
3271 return WERR_GENERAL_FAILURE;
3274 /* now open up both printers */
3276 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3278 printf("Opening %s...", printername_path);
3280 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3284 if ( !W_ERROR_IS_OK(werror) ) {
3285 printf("failed (%s)\n", win_errstr(werror));
3290 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3292 printf("Opening %s...", printername_path);
3293 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3297 if ( !W_ERROR_IS_OK(werror) ) {
3298 printf("failed (%s)\n", win_errstr(werror));
3303 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3304 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3306 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3313 printf("Closing printers...");
3314 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3315 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3318 /* close the second remote connection */
3320 cli_shutdown( cli_server2 );
3324 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3326 printf("print_processor_name: %s\n", r->print_processor_name);
3329 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3330 TALLOC_CTX *mem_ctx, int argc,
3334 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3335 uint32_t num_procs, level = 1, i;
3336 union spoolss_PrintProcessorInfo *procs;
3338 /* Parse the command arguments */
3340 if (argc < 1 || argc > 4) {
3341 printf ("Usage: %s [environment] [level]\n", argv[0]);
3346 environment = argv[1];
3350 level = atoi(argv[2]);
3353 /* Enumerate Print Processors */
3355 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3356 cli->srv_name_slash,
3362 if (!W_ERROR_IS_OK(werror))
3365 /* Display output */
3367 for (i = 0; i < num_procs; i++) {
3370 display_proc_info1(&procs[i].info1);
3379 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3381 printf("name_array: %s\n", r->name_array);
3384 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3385 TALLOC_CTX *mem_ctx, int argc,
3389 const char *print_processor_name = "winprint";
3390 uint32_t num_procs, level = 1, i;
3391 union spoolss_PrintProcDataTypesInfo *procs;
3393 /* Parse the command arguments */
3395 if (argc < 1 || argc > 4) {
3396 printf ("Usage: %s [environment] [level]\n", argv[0]);
3401 print_processor_name = argv[1];
3405 level = atoi(argv[2]);
3408 /* Enumerate Print Processor Data Types */
3410 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3411 cli->srv_name_slash,
3412 print_processor_name,
3417 if (!W_ERROR_IS_OK(werror))
3420 /* Display output */
3422 for (i = 0; i < num_procs; i++) {
3425 display_proc_data_types_info1(&procs[i].info1);
3434 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3436 printf("monitor_name: %s\n", r->monitor_name);
3439 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3441 printf("monitor_name: %s\n", r->monitor_name);
3442 printf("environment: %s\n", r->environment);
3443 printf("dll_name: %s\n", r->dll_name);
3446 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3447 TALLOC_CTX *mem_ctx, int argc,
3451 uint32_t count, level = 1, i;
3452 union spoolss_MonitorInfo *info;
3454 /* Parse the command arguments */
3457 printf("Usage: %s [level]\n", argv[0]);
3462 level = atoi(argv[1]);
3465 /* Enumerate Print Monitors */
3467 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3468 cli->srv_name_slash,
3473 if (!W_ERROR_IS_OK(werror)) {
3477 /* Display output */
3479 for (i = 0; i < count; i++) {
3482 display_monitor1(&info[i].info1);
3485 display_monitor2(&info[i].info2);
3494 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3495 TALLOC_CTX *mem_ctx, int argc,
3500 struct policy_handle handle, gdi_handle;
3501 const char *printername;
3502 struct spoolss_DevmodeContainer devmode_ctr;
3504 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3506 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3508 SEC_FLAG_MAXIMUM_ALLOWED,
3510 if (!W_ERROR_IS_OK(result)) {
3514 ZERO_STRUCT(devmode_ctr);
3516 status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
3521 if (!W_ERROR_IS_OK(result)) {
3526 if (is_valid_policy_hnd(&gdi_handle)) {
3527 rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
3529 if (is_valid_policy_hnd(&handle)) {
3530 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3536 /* List of commands exported by this module */
3537 struct cmd_set spoolss_commands[] = {
3541 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3542 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3543 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3544 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3545 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3546 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3547 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3548 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3549 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3550 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3551 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3552 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3553 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3554 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3555 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3556 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3557 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3558 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3559 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3560 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3561 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3562 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3563 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3564 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3565 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3566 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3567 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3568 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3569 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3570 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3571 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3572 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3573 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3574 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3575 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },