2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9 Copyright (C) Guenther Deschner 2009
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "rpcclient.h"
27 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
28 #include "rpc_client/cli_spoolss.h"
29 #include "rpc_client/init_spoolss.h"
31 #include "registry/reg_objects.h"
32 #include "nt_printing.h"
34 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
36 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
37 _cli->srv_name_slash, _arg); \
38 W_ERROR_HAVE_NO_MEMORY(_printername); \
41 /* The version int is used by getdrivers. Note that
42 all architecture strings that support mutliple
43 versions must be grouped together since enumdrivers
44 uses this property to prevent issuing multiple
45 enumdriver calls for the same arch */
48 static const struct print_architecture_table_node archi_table[]= {
50 {"Windows 4.0", "WIN40", 0 },
51 {"Windows NT x86", "W32X86", 2 },
52 {"Windows NT x86", "W32X86", 3 },
53 {"Windows NT R4000", "W32MIPS", 2 },
54 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
55 {"Windows NT PowerPC", "W32PPC", 2 },
56 {"Windows IA64", "IA64", 3 },
57 {"Windows x64", "x64", 3 },
64 * rpcclient module for SPOOLSS rpc pipe.
66 * This generally just parses and checks command lines, and then calls
67 * a cli_spoolss function.
70 /****************************************************************************
71 function to do the mapping between the long architecture name and
73 ****************************************************************************/
75 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
79 DEBUG(107,("Getting architecture dependant directory\n"));
82 } while ( (archi_table[i].long_archi!=NULL ) &&
83 StrCaseCmp(long_archi, archi_table[i].long_archi) );
85 if (archi_table[i].long_archi==NULL) {
86 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
90 /* this might be client code - but shouldn't this be an fstrcpy etc? */
93 DEBUGADD(108,("index: [%d]\n", i));
94 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
95 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
97 return archi_table[i].short_archi;
100 /****************************************************************************
101 ****************************************************************************/
103 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
105 int argc, const char **argv)
108 struct policy_handle hnd;
109 uint32_t access_mask = PRINTER_ALL_ACCESS;
110 struct dcerpc_binding_handle *b = cli->binding_handle;
113 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
118 sscanf(argv[2], "%x", &access_mask);
121 /* Open the printer handle */
123 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
127 if (W_ERROR_IS_OK(werror)) {
128 printf("Printer %s opened successfully\n", argv[1]);
129 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
131 if (!W_ERROR_IS_OK(werror)) {
132 printf("Error closing printer handle! (%s)\n",
133 get_dos_error_msg(werror));
140 /****************************************************************************
141 ****************************************************************************/
143 static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
145 int argc, const char **argv)
148 struct policy_handle hnd;
149 uint32_t access_mask = PRINTER_ALL_ACCESS;
151 struct spoolss_DevmodeContainer devmode_ctr;
152 struct dcerpc_binding_handle *b = cli->binding_handle;
154 ZERO_STRUCT(devmode_ctr);
157 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
162 sscanf(argv[2], "%x", &access_mask);
165 /* Open the printer handle */
167 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
174 if (!NT_STATUS_IS_OK(status)) {
175 return ntstatus_to_werror(status);
177 if (W_ERROR_IS_OK(werror)) {
178 printf("Printer %s opened successfully\n", argv[1]);
179 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
181 if (!W_ERROR_IS_OK(werror)) {
182 printf("Error closing printer handle! (%s)\n",
183 get_dos_error_msg(werror));
190 /****************************************************************************
191 ****************************************************************************/
193 static void display_print_info0(struct spoolss_PrinterInfo0 *r)
198 printf("\tprintername:[%s]\n", r->printername);
199 printf("\tservername:[%s]\n", r->servername);
200 printf("\tcjobs:[0x%x]\n", r->cjobs);
201 printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
202 printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
203 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
204 r->time.day, r->time.day_of_week);
205 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
206 r->time.second, r->time.millisecond);
208 printf("\tglobal_counter:[0x%x]\n", r->global_counter);
209 printf("\ttotal_pages:[0x%x]\n", r->total_pages);
211 printf("\tversion:[0x%x]\n", r->version);
212 printf("\tfree_build:[0x%x]\n", r->free_build);
213 printf("\tspooling:[0x%x]\n", r->spooling);
214 printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
215 printf("\tsession_counter:[0x%x]\n", r->session_counter);
216 printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
217 printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
218 printf("\tjob_error:[0x%x]\n", r->job_error);
219 printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
220 printf("\tprocessor_type:[0x%x]\n", r->processor_type);
221 printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
222 printf("\tchange_id:[0x%x]\n", r->change_id);
223 printf("\tlast_error: %s\n", win_errstr(r->last_error));
224 printf("\tstatus:[0x%x]\n", r->status);
225 printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
226 printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
227 printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
228 printf("\tprocessor_level:[0x%x]\n", r->processor_level);
229 printf("\tref_ic:[0x%x]\n", r->ref_ic);
230 printf("\treserved2:[0x%x]\n", r->reserved2);
231 printf("\treserved3:[0x%x]\n", r->reserved3);
236 /****************************************************************************
237 ****************************************************************************/
239 static void display_print_info1(struct spoolss_PrinterInfo1 *r)
241 printf("\tflags:[0x%x]\n", r->flags);
242 printf("\tname:[%s]\n", r->name);
243 printf("\tdescription:[%s]\n", r->description);
244 printf("\tcomment:[%s]\n", r->comment);
249 /****************************************************************************
250 ****************************************************************************/
252 static void display_print_info2(struct spoolss_PrinterInfo2 *r)
254 printf("\tservername:[%s]\n", r->servername);
255 printf("\tprintername:[%s]\n", r->printername);
256 printf("\tsharename:[%s]\n", r->sharename);
257 printf("\tportname:[%s]\n", r->portname);
258 printf("\tdrivername:[%s]\n", r->drivername);
259 printf("\tcomment:[%s]\n", r->comment);
260 printf("\tlocation:[%s]\n", r->location);
261 printf("\tsepfile:[%s]\n", r->sepfile);
262 printf("\tprintprocessor:[%s]\n", r->printprocessor);
263 printf("\tdatatype:[%s]\n", r->datatype);
264 printf("\tparameters:[%s]\n", r->parameters);
265 printf("\tattributes:[0x%x]\n", r->attributes);
266 printf("\tpriority:[0x%x]\n", r->priority);
267 printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
268 printf("\tstarttime:[0x%x]\n", r->starttime);
269 printf("\tuntiltime:[0x%x]\n", r->untiltime);
270 printf("\tstatus:[0x%x]\n", r->status);
271 printf("\tcjobs:[0x%x]\n", r->cjobs);
272 printf("\taverageppm:[0x%x]\n", r->averageppm);
275 display_sec_desc(r->secdesc);
280 /****************************************************************************
281 ****************************************************************************/
283 static void display_print_info3(struct spoolss_PrinterInfo3 *r)
285 display_sec_desc(r->secdesc);
290 /****************************************************************************
291 ****************************************************************************/
293 static void display_print_info4(struct spoolss_PrinterInfo4 *r)
295 printf("\tservername:[%s]\n", r->servername);
296 printf("\tprintername:[%s]\n", r->printername);
297 printf("\tattributes:[0x%x]\n", r->attributes);
301 /****************************************************************************
302 ****************************************************************************/
304 static void display_print_info5(struct spoolss_PrinterInfo5 *r)
306 printf("\tprintername:[%s]\n", r->printername);
307 printf("\tportname:[%s]\n", r->portname);
308 printf("\tattributes:[0x%x]\n", r->attributes);
309 printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
310 printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
314 /****************************************************************************
315 ****************************************************************************/
317 static void display_print_info6(struct spoolss_PrinterInfo6 *r)
319 printf("\tstatus:[0x%x]\n", r->status);
323 /****************************************************************************
324 ****************************************************************************/
326 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
328 printf("\tguid:[%s]\n", r->guid);
329 printf("\taction:[0x%x]\n", r->action);
333 /****************************************************************************
334 ****************************************************************************/
336 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
338 int argc, const char **argv)
342 union spoolss_PrinterInfo *info;
345 uint32_t flags = PRINTER_ENUM_LOCAL;
348 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
353 level = atoi(argv[1]);
359 name = cli->srv_name_slash;
363 flags = atoi(argv[3]);
366 result = rpccli_spoolss_enumprinters(cli, mem_ctx,
373 if (W_ERROR_IS_OK(result)) {
376 printf ("No printers returned.\n");
380 for (i = 0; i < count; i++) {
383 display_print_info0(&info[i].info0);
386 display_print_info1(&info[i].info1);
389 display_print_info2(&info[i].info2);
392 display_print_info3(&info[i].info3);
395 display_print_info4(&info[i].info4);
398 display_print_info5(&info[i].info5);
401 display_print_info6(&info[i].info6);
404 printf("unknown info level %d\n", level);
414 /****************************************************************************
415 ****************************************************************************/
417 static void display_port_info_1(struct spoolss_PortInfo1 *r)
419 printf("\tPort Name:\t[%s]\n", r->port_name);
422 /****************************************************************************
423 ****************************************************************************/
425 static void display_port_info_2(struct spoolss_PortInfo2 *r)
427 printf("\tPort Name:\t[%s]\n", r->port_name);
428 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
429 printf("\tDescription:\t[%s]\n", r->description);
430 printf("\tPort Type:\t" );
432 int comma = 0; /* hack */
434 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
438 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
439 printf( "%sWrite", comma ? ", " : "" );
442 /* These two have slightly different interpretations
443 on 95/98/ME but I'm disregarding that for now */
444 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
445 printf( "%sRedirected", comma ? ", " : "" );
448 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
449 printf( "%sNet-Attached", comma ? ", " : "" );
453 printf( "[Unset]\n" );
455 printf("\tReserved:\t[%d]\n", r->reserved);
459 /****************************************************************************
460 ****************************************************************************/
462 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
463 TALLOC_CTX *mem_ctx, int argc,
469 union spoolss_PortInfo *info;
472 printf("Usage: %s [level]\n", argv[0]);
477 level = atoi(argv[1]);
480 /* Enumerate ports */
482 result = rpccli_spoolss_enumports(cli, mem_ctx,
488 if (W_ERROR_IS_OK(result)) {
491 for (i = 0; i < count; i++) {
494 display_port_info_1(&info[i].info1);
497 display_port_info_2(&info[i].info2);
500 printf("unknown info level %d\n", level);
509 /****************************************************************************
510 ****************************************************************************/
512 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
514 int argc, const char **argv)
516 struct policy_handle pol;
519 uint32_t info_level = 2;
520 union spoolss_PrinterInfo info;
521 struct spoolss_SetPrinterInfoCtr info_ctr;
522 struct spoolss_SetPrinterInfo2 info2;
523 const char *printername, *comment = NULL;
524 struct spoolss_DevmodeContainer devmode_ctr;
525 struct sec_desc_buf secdesc_ctr;
526 struct dcerpc_binding_handle *b = cli->binding_handle;
528 if (argc == 1 || argc > 3) {
529 printf("Usage: %s printername comment\n", argv[0]);
534 /* Open a printer handle */
539 ZERO_STRUCT(devmode_ctr);
540 ZERO_STRUCT(secdesc_ctr);
542 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
544 /* get a printer handle */
545 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
549 if (!W_ERROR_IS_OK(result))
552 /* Get printer info */
553 result = rpccli_spoolss_getprinter(cli, mem_ctx,
558 if (!W_ERROR_IS_OK(result))
562 /* Modify the comment. */
563 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
564 info2.comment = comment;
567 info_ctr.info.info2 = &info2;
569 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
576 if (!NT_STATUS_IS_OK(status)) {
577 result = ntstatus_to_werror(status);
580 if (W_ERROR_IS_OK(result))
581 printf("Success in setting comment.\n");
584 if (is_valid_policy_hnd(&pol)) {
586 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
592 /****************************************************************************
593 ****************************************************************************/
595 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
597 int argc, const char **argv)
599 struct policy_handle pol;
602 uint32_t info_level = 2;
603 union spoolss_PrinterInfo info;
604 const char *printername,
605 *new_printername = NULL;
606 struct spoolss_SetPrinterInfoCtr info_ctr;
607 struct spoolss_SetPrinterInfo2 info2;
608 struct spoolss_DevmodeContainer devmode_ctr;
609 struct sec_desc_buf secdesc_ctr;
610 struct dcerpc_binding_handle *b = cli->binding_handle;
612 ZERO_STRUCT(devmode_ctr);
613 ZERO_STRUCT(secdesc_ctr);
615 if (argc == 1 || argc > 3) {
616 printf("Usage: %s printername new_printername\n", argv[0]);
621 /* Open a printer handle */
623 new_printername = argv[2];
626 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
628 /* get a printer handle */
629 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
633 if (!W_ERROR_IS_OK(result))
636 /* Get printer info */
637 result = rpccli_spoolss_getprinter(cli, mem_ctx,
642 if (!W_ERROR_IS_OK(result))
645 /* Modify the printername. */
646 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
647 info2.printername = new_printername;
650 info_ctr.info.info2 = &info2;
652 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
659 if (!NT_STATUS_IS_OK(status)) {
660 result = ntstatus_to_werror(status);
663 if (W_ERROR_IS_OK(result))
664 printf("Success in setting printername.\n");
667 if (is_valid_policy_hnd(&pol)) {
669 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
675 /****************************************************************************
676 ****************************************************************************/
678 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
680 int argc, const char **argv)
682 struct policy_handle pol;
685 const char *printername;
686 union spoolss_PrinterInfo info;
687 struct dcerpc_binding_handle *b = cli->binding_handle;
689 if (argc == 1 || argc > 3) {
690 printf("Usage: %s <printername> [level]\n", argv[0]);
694 /* Open a printer handle */
696 level = atoi(argv[2]);
699 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
701 /* get a printer handle */
703 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
705 SEC_FLAG_MAXIMUM_ALLOWED,
707 if (!W_ERROR_IS_OK(result)) {
711 /* Get printer info */
713 result = rpccli_spoolss_getprinter(cli, mem_ctx,
718 if (!W_ERROR_IS_OK(result)) {
722 /* Display printer info */
725 display_print_info0(&info.info0);
728 display_print_info1(&info.info1);
731 display_print_info2(&info.info2);
734 display_print_info3(&info.info3);
737 display_print_info4(&info.info4);
740 display_print_info5(&info.info5);
743 display_print_info6(&info.info6);
746 display_print_info7(&info.info7);
749 printf("unknown info level %d\n", level);
753 if (is_valid_policy_hnd(&pol)) {
755 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
761 /****************************************************************************
762 ****************************************************************************/
764 static void display_reg_value(struct regval_blob *value)
766 const char *text = NULL;
769 switch(regval_type(value)) {
771 printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
772 *((uint32_t *) regval_data_p(value)));
775 blob = data_blob_const(regval_data_p(value), regval_size(value));
776 pull_reg_sz(talloc_tos(), &blob, &text);
777 printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
780 char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
782 printf("%s: REG_BINARY:", regval_name(value));
784 for (i=0; i<len; i++) {
785 if (hex[i] == '\0') {
800 blob = data_blob_const(regval_data_p(value), regval_size(value));
802 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
803 d_printf("pull_reg_multi_sz failed\n");
807 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
808 for (i=0; values[i] != NULL; i++) {
809 d_printf("%s\n", values[i]);
815 printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
820 /****************************************************************************
821 ****************************************************************************/
823 static void display_printer_data(const char *v,
824 enum winreg_Type type,
829 union spoolss_PrinterData r;
830 DATA_BLOB blob = data_blob_const(data, length);
833 result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
834 if (!W_ERROR_IS_OK(result)) {
840 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
843 printf("%s: REG_SZ: %s\n", v, r.string);
846 char *hex = hex_encode_talloc(NULL,
847 r.binary.data, r.binary.length);
849 printf("%s: REG_BINARY:", v);
851 for (i=0; i<len; i++) {
852 if (hex[i] == '\0') {
865 printf("%s: REG_MULTI_SZ: ", v);
866 for (i=0; r.string_array[i] != NULL; i++) {
867 printf("%s ", r.string_array[i]);
872 printf("%s: unknown type 0x%02x:\n", v, type);
877 /****************************************************************************
878 ****************************************************************************/
880 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
882 int argc, const char **argv)
884 struct policy_handle pol;
887 const char *valuename;
888 enum winreg_Type type;
891 struct dcerpc_binding_handle *b = cli->binding_handle;
894 printf("Usage: %s <printername> <valuename>\n", argv[0]);
895 printf("<printername> of . queries print server\n");
900 /* Open a printer handle */
902 if (strncmp(argv[1], ".", sizeof(".")) == 0)
903 fstrcpy(printername, cli->srv_name_slash);
905 slprintf(printername, sizeof(printername)-1, "%s\\%s",
906 cli->srv_name_slash, argv[1]);
908 /* get a printer handle */
910 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
912 SEC_FLAG_MAXIMUM_ALLOWED,
914 if (!W_ERROR_IS_OK(result))
917 /* Get printer info */
919 result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
926 if (!W_ERROR_IS_OK(result))
929 /* Display printer data */
931 display_printer_data(valuename, type, data, needed);
934 if (is_valid_policy_hnd(&pol)) {
936 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
942 /****************************************************************************
943 ****************************************************************************/
945 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
947 int argc, const char **argv)
949 struct policy_handle pol;
953 const char *valuename, *keyname;
955 enum winreg_Type type;
956 uint8_t *data = NULL;
957 uint32_t offered = 0;
959 struct dcerpc_binding_handle *b = cli->binding_handle;
962 printf("Usage: %s <printername> <keyname> <valuename>\n",
964 printf("<printername> of . queries print server\n");
970 /* Open a printer handle */
972 if (strncmp(argv[1], ".", sizeof(".")) == 0)
973 fstrcpy(printername, cli->srv_name_slash);
975 slprintf(printername, sizeof(printername)-1, "%s\\%s",
976 cli->srv_name_slash, argv[1]);
978 /* get a printer handle */
980 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
982 SEC_FLAG_MAXIMUM_ALLOWED,
984 if (!W_ERROR_IS_OK(result))
987 /* Get printer info */
989 data = talloc_zero_array(mem_ctx, uint8_t, offered);
994 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1003 if (!NT_STATUS_IS_OK(status)) {
1004 result = ntstatus_to_werror(status);
1007 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1009 data = talloc_zero_array(mem_ctx, uint8_t, offered);
1013 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1024 if (!NT_STATUS_IS_OK(status)) {
1025 result = ntstatus_to_werror(status);
1029 if (!W_ERROR_IS_OK(result))
1032 /* Display printer data */
1034 display_printer_data(valuename, type, data, needed);
1038 if (is_valid_policy_hnd(&pol)) {
1040 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1046 /****************************************************************************
1047 ****************************************************************************/
1049 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1055 printf("Printer Driver Info 1:\n");
1056 printf("\tDriver Name: [%s]\n", r->driver_name);
1060 /****************************************************************************
1061 ****************************************************************************/
1063 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1069 printf("Printer Driver Info 2:\n");
1070 printf("\tVersion: [%x]\n", r->version);
1071 printf("\tDriver Name: [%s]\n", r->driver_name);
1072 printf("\tArchitecture: [%s]\n", r->architecture);
1073 printf("\tDriver Path: [%s]\n", r->driver_path);
1074 printf("\tDatafile: [%s]\n", r->data_file);
1075 printf("\tConfigfile: [%s]\n", r->config_file);
1079 /****************************************************************************
1080 ****************************************************************************/
1082 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1090 printf("Printer Driver Info 3:\n");
1091 printf("\tVersion: [%x]\n", r->version);
1092 printf("\tDriver Name: [%s]\n", r->driver_name);
1093 printf("\tArchitecture: [%s]\n", r->architecture);
1094 printf("\tDriver Path: [%s]\n", r->driver_path);
1095 printf("\tDatafile: [%s]\n", r->data_file);
1096 printf("\tConfigfile: [%s]\n", r->config_file);
1097 printf("\tHelpfile: [%s]\n", r->help_file);
1099 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1100 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1103 printf("\tMonitorname: [%s]\n", r->monitor_name);
1104 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1108 /****************************************************************************
1109 ****************************************************************************/
1111 static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1119 printf("Printer Driver Info 4:\n");
1120 printf("\tVersion: [%x]\n", r->version);
1121 printf("\tDriver Name: [%s]\n", r->driver_name);
1122 printf("\tArchitecture: [%s]\n", r->architecture);
1123 printf("\tDriver Path: [%s]\n", r->driver_path);
1124 printf("\tDatafile: [%s]\n", r->data_file);
1125 printf("\tConfigfile: [%s]\n", r->config_file);
1126 printf("\tHelpfile: [%s]\n", r->help_file);
1128 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1129 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1132 printf("\tMonitorname: [%s]\n", r->monitor_name);
1133 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1135 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1136 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1141 /****************************************************************************
1142 ****************************************************************************/
1144 static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1150 printf("Printer Driver Info 5:\n");
1151 printf("\tVersion: [%x]\n", r->version);
1152 printf("\tDriver Name: [%s]\n", r->driver_name);
1153 printf("\tArchitecture: [%s]\n", r->architecture);
1154 printf("\tDriver Path: [%s]\n", r->driver_path);
1155 printf("\tDatafile: [%s]\n", r->data_file);
1156 printf("\tConfigfile: [%s]\n", r->config_file);
1157 printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1158 printf("\tConfig Version: [0x%x]\n", r->config_version);
1159 printf("\tDriver Version: [0x%x]\n", r->driver_version);
1163 /****************************************************************************
1164 ****************************************************************************/
1166 static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1174 printf("Printer Driver Info 6:\n");
1175 printf("\tVersion: [%x]\n", r->version);
1176 printf("\tDriver Name: [%s]\n", r->driver_name);
1177 printf("\tArchitecture: [%s]\n", r->architecture);
1178 printf("\tDriver Path: [%s]\n", r->driver_path);
1179 printf("\tDatafile: [%s]\n", r->data_file);
1180 printf("\tConfigfile: [%s]\n", r->config_file);
1181 printf("\tHelpfile: [%s]\n", r->help_file);
1183 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1184 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1187 printf("\tMonitorname: [%s]\n", r->monitor_name);
1188 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1190 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1191 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1194 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1195 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1196 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1197 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1198 printf("\tHardware ID: [%s]\n", r->hardware_id);
1199 printf("\tProvider: [%s]\n", r->provider);
1204 /****************************************************************************
1205 ****************************************************************************/
1207 static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1215 printf("Printer Driver Info 8:\n");
1216 printf("\tVersion: [%x]\n", r->version);
1217 printf("\tDriver Name: [%s]\n", r->driver_name);
1218 printf("\tArchitecture: [%s]\n", r->architecture);
1219 printf("\tDriver Path: [%s]\n", r->driver_path);
1220 printf("\tDatafile: [%s]\n", r->data_file);
1221 printf("\tConfigfile: [%s]\n", r->config_file);
1222 printf("\tHelpfile: [%s]\n", r->help_file);
1223 printf("\tMonitorname: [%s]\n", r->monitor_name);
1224 printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1226 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1227 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1230 for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1231 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1234 printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1235 printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1236 printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1237 printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1238 printf("\tHardware ID: [%s]\n", r->hardware_id);
1239 printf("\tProvider: [%s]\n", r->provider);
1240 printf("\tPrint Processor: [%s]\n", r->print_processor);
1241 printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1242 for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1243 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1245 printf("\tInf Path: [%s]\n", r->inf_path);
1246 printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1247 for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1248 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1250 printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1251 printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1252 (long long unsigned int)r->min_inbox_driver_ver_version);
1257 /****************************************************************************
1258 ****************************************************************************/
1260 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1261 TALLOC_CTX *mem_ctx,
1262 int argc, const char **argv)
1264 struct policy_handle pol;
1267 const char *printername;
1269 bool success = false;
1270 union spoolss_DriverInfo info;
1271 uint32_t server_major_version;
1272 uint32_t server_minor_version;
1273 struct dcerpc_binding_handle *b = cli->binding_handle;
1275 if ((argc == 1) || (argc > 3)) {
1276 printf("Usage: %s <printername> [level]\n", argv[0]);
1280 /* get the arguments need to open the printer handle */
1282 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1285 level = atoi(argv[2]);
1288 /* Open a printer handle */
1290 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1294 if (!W_ERROR_IS_OK(werror)) {
1295 printf("Error opening printer handle for %s!\n", printername);
1299 /* loop through and print driver info level for each architecture */
1301 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1303 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1305 archi_table[i].long_archi,
1308 archi_table[i].version,
1311 &server_major_version,
1312 &server_minor_version);
1313 if (!W_ERROR_IS_OK(werror)) {
1317 /* need at least one success */
1321 printf("\n[%s]\n", archi_table[i].long_archi);
1325 display_print_driver1(&info.info1);
1328 display_print_driver2(&info.info2);
1331 display_print_driver3(&info.info3);
1334 display_print_driver4(&info.info4);
1337 display_print_driver5(&info.info5);
1340 display_print_driver6(&info.info6);
1343 display_print_driver8(&info.info8);
1346 printf("unknown info level %d\n", level);
1353 if (is_valid_policy_hnd(&pol)) {
1355 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1365 /****************************************************************************
1366 ****************************************************************************/
1368 static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1369 TALLOC_CTX *mem_ctx,
1370 const char *architecture,
1375 union spoolss_DriverInfo *info = NULL;
1378 werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1379 cli->srv_name_slash,
1386 if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1387 printf("Server does not support environment [%s]\n",
1396 if (!W_ERROR_IS_OK(werror)) {
1397 printf("Error getting driver for environment [%s] - %s\n",
1398 architecture, win_errstr(werror));
1402 printf("\n[%s]\n", architecture);
1406 for (j=0; j < count; j++) {
1407 display_print_driver1(&info[j].info1);
1411 for (j=0; j < count; j++) {
1412 display_print_driver2(&info[j].info2);
1416 for (j=0; j < count; j++) {
1417 display_print_driver3(&info[j].info3);
1421 for (j=0; j < count; j++) {
1422 display_print_driver4(&info[j].info4);
1426 for (j=0; j < count; j++) {
1427 display_print_driver5(&info[j].info5);
1431 for (j=0; j < count; j++) {
1432 display_print_driver6(&info[j].info6);
1436 for (j=0; j < count; j++) {
1437 display_print_driver8(&info[j].info8);
1441 printf("unknown info level %d\n", level);
1442 return WERR_UNKNOWN_LEVEL;
1448 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1449 TALLOC_CTX *mem_ctx,
1450 int argc, const char **argv)
1452 WERROR werror = WERR_OK;
1455 const char *architecture = NULL;
1458 printf("Usage: enumdrivers [level] [architecture]\n");
1463 level = atoi(argv[1]);
1467 architecture = argv[2];
1471 return enum_driver_by_architecture(cli, mem_ctx,
1476 /* loop through and print driver info level for each architecture */
1477 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1478 /* check to see if we already asked for this architecture string */
1480 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1484 werror = enum_driver_by_architecture(cli, mem_ctx,
1485 archi_table[i].long_archi,
1487 if (!W_ERROR_IS_OK(werror)) {
1495 /****************************************************************************
1496 ****************************************************************************/
1498 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1500 printf("\tDirectory Name:[%s]\n", r->directory_name);
1503 /****************************************************************************
1504 ****************************************************************************/
1506 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1507 TALLOC_CTX *mem_ctx,
1508 int argc, const char **argv)
1512 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1515 union spoolss_DriverDirectoryInfo info;
1517 struct dcerpc_binding_handle *b = cli->binding_handle;
1520 printf("Usage: %s [environment]\n", argv[0]);
1524 /* Get the arguments need to open the printer handle */
1530 /* Get the directory. Only use Info level 1 */
1532 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1533 cli->srv_name_slash,
1541 if (!NT_STATUS_IS_OK(status)) {
1542 return ntstatus_to_werror(status);
1544 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1546 buffer = data_blob_talloc_zero(mem_ctx, needed);
1548 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1549 cli->srv_name_slash,
1557 if (!NT_STATUS_IS_OK(status)) {
1558 return ntstatus_to_werror(status);
1562 if (W_ERROR_IS_OK(result)) {
1563 display_printdriverdir_1(&info.info1);
1569 /****************************************************************************
1570 ****************************************************************************/
1572 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1573 struct spoolss_AddDriverInfo3 *info,
1579 for (i=0; archi_table[i].long_archi != NULL; i++)
1581 if (strcmp(arch, archi_table[i].short_archi) == 0)
1583 info->version = archi_table[i].version;
1584 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1589 if (archi_table[i].long_archi == NULL)
1591 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1598 /**************************************************************************
1599 wrapper for strtok to get the next parameter from a delimited list.
1600 Needed to handle the empty parameter string denoted by "NULL"
1601 *************************************************************************/
1603 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1604 const char *delim, const char **dest,
1609 /* get the next token */
1610 ptr = strtok_r(str, delim, saveptr);
1612 /* a string of 'NULL' is used to represent an empty
1613 parameter because two consecutive delimiters
1614 will not return an empty string. See man strtok(3)
1616 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1621 *dest = talloc_strdup(mem_ctx, ptr);
1627 /********************************************************************************
1628 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1629 string in the form of
1630 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1631 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1632 <Default Data Type>:<Comma Separated list of Files>
1633 *******************************************************************************/
1635 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1640 char *saveptr = NULL;
1641 struct spoolss_StringArray *deps;
1642 const char **file_array = NULL;
1645 /* fill in the UNISTR fields */
1646 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1647 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1648 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1649 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1650 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1651 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1652 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1654 /* <Comma Separated List of Dependent Files> */
1655 /* save the beginning of the string */
1656 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1659 /* begin to strip out each filename */
1660 str = strtok_r(str, ",", &saveptr);
1662 /* no dependent files, we are done */
1667 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1672 while (str != NULL) {
1673 add_string_to_array(deps, str, &file_array, &count);
1674 str = strtok_r(NULL, ",", &saveptr);
1677 deps->string = talloc_zero_array(deps, const char *, count + 1);
1678 if (!deps->string) {
1682 for (i=0; i < count; i++) {
1683 deps->string[i] = file_array[i];
1686 r->dependent_files = deps;
1691 /****************************************************************************
1692 ****************************************************************************/
1694 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1695 TALLOC_CTX *mem_ctx,
1696 int argc, const char **argv)
1701 struct spoolss_AddDriverInfoCtr info_ctr;
1702 struct spoolss_AddDriverInfo3 info3;
1705 struct dcerpc_binding_handle *b = cli->binding_handle;
1707 /* parse the command arguments */
1708 if (argc != 3 && argc != 4)
1710 printf ("Usage: %s <Environment> \\\n", argv[0]);
1711 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1712 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1713 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1714 printf ("\t[version]\n");
1719 /* Fill in the spoolss_AddDriverInfo3 struct */
1722 arch = cmd_spoolss_get_short_archi(argv[1]);
1724 printf ("Error Unknown architechture [%s]\n", argv[1]);
1725 return WERR_INVALID_PARAM;
1728 set_drv_info_3_env(mem_ctx, &info3, arch);
1730 driver_args = talloc_strdup( mem_ctx, argv[2] );
1731 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1733 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1734 return WERR_INVALID_PARAM;
1737 /* if printer driver version specified, override the default version
1738 * used by the architecture. This allows installation of Windows
1739 * 2000 (version 3) printer drivers. */
1742 info3.version = atoi(argv[3]);
1746 info_ctr.level = level;
1747 info_ctr.info.info3 = &info3;
1749 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1750 cli->srv_name_slash,
1753 if (!NT_STATUS_IS_OK(status)) {
1754 return ntstatus_to_werror(status);
1756 if (W_ERROR_IS_OK(result)) {
1757 printf ("Printer Driver %s successfully installed.\n",
1765 /****************************************************************************
1766 ****************************************************************************/
1768 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1769 TALLOC_CTX *mem_ctx,
1770 int argc, const char **argv)
1773 struct spoolss_SetPrinterInfoCtr info_ctr;
1774 struct spoolss_SetPrinterInfo2 info2;
1776 /* parse the command arguments */
1779 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1783 /* Fill in the DRIVER_INFO_2 struct */
1786 info2.printername = argv[1];
1787 info2.drivername = argv[3];
1788 info2.sharename = argv[2];
1789 info2.portname = argv[4];
1790 info2.comment = "Created by rpcclient";
1791 info2.printprocessor = "winprint";
1792 info2.datatype = "RAW";
1793 info2.devmode_ptr = 0;
1794 info2.secdesc_ptr = 0;
1795 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1797 info2.defaultpriority = 0;
1798 info2.starttime = 0;
1799 info2.untiltime = 0;
1801 /* These three fields must not be used by AddPrinter()
1802 as defined in the MS Platform SDK documentation..
1806 info2.averageppm = 0;
1810 info_ctr.info.info2 = &info2;
1812 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1814 if (W_ERROR_IS_OK(result))
1815 printf ("Printer %s successfully installed.\n", argv[1]);
1820 /****************************************************************************
1821 ****************************************************************************/
1823 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1824 TALLOC_CTX *mem_ctx,
1825 int argc, const char **argv)
1827 struct policy_handle pol;
1831 const char *printername;
1832 union spoolss_PrinterInfo info;
1833 struct spoolss_SetPrinterInfoCtr info_ctr;
1834 struct spoolss_SetPrinterInfo2 info2;
1835 struct spoolss_DevmodeContainer devmode_ctr;
1836 struct sec_desc_buf secdesc_ctr;
1837 struct dcerpc_binding_handle *b = cli->binding_handle;
1839 ZERO_STRUCT(devmode_ctr);
1840 ZERO_STRUCT(secdesc_ctr);
1842 /* parse the command arguments */
1845 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1849 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1851 /* Get a printer handle */
1853 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1857 if (!W_ERROR_IS_OK(result))
1860 /* Get printer info */
1862 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1867 if (!W_ERROR_IS_OK(result)) {
1868 printf ("Unable to retrieve printer information!\n");
1872 /* Set the printer driver */
1874 spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1875 info2.drivername = argv[2];
1878 info_ctr.info.info2 = &info2;
1880 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1887 if (!NT_STATUS_IS_OK(status)) {
1888 result = ntstatus_to_werror(status);
1891 if (!W_ERROR_IS_OK(result)) {
1892 printf("SetPrinter call failed!\n");
1896 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1901 if (is_valid_policy_hnd(&pol)) {
1903 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1910 /****************************************************************************
1911 ****************************************************************************/
1913 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1914 TALLOC_CTX *mem_ctx,
1915 int argc, const char **argv)
1917 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1919 struct dcerpc_binding_handle *b = cli->binding_handle;
1924 const char *arch = NULL;
1925 uint32_t delete_flags = 0;
1927 /* parse the command arguments */
1928 if (argc < 2 || argc > 4) {
1929 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1936 vers = atoi (argv[3]);
1939 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1942 /* delete the driver for all architectures */
1943 for (i=0; archi_table[i].long_archi; i++) {
1945 if (arch && !strequal( archi_table[i].long_archi, arch))
1948 if (vers >= 0 && archi_table[i].version != vers)
1951 /* make the call to remove the driver */
1952 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
1953 cli->srv_name_slash,
1954 archi_table[i].long_archi,
1957 archi_table[i].version,
1959 if (!NT_STATUS_IS_OK(status)) {
1960 return ntstatus_to_werror(status);
1962 if ( !W_ERROR_IS_OK(result) )
1964 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1965 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1966 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1971 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1972 archi_table[i].long_archi, archi_table[i].version);
1981 /****************************************************************************
1982 ****************************************************************************/
1984 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1985 TALLOC_CTX *mem_ctx,
1986 int argc, const char **argv)
1988 WERROR result = WERR_OK;
1991 struct dcerpc_binding_handle *b = cli->binding_handle;
1993 /* parse the command arguments */
1995 printf ("Usage: %s <driver>\n", argv[0]);
1999 /* delete the driver for all architectures */
2000 for (i=0; archi_table[i].long_archi; i++) {
2003 /* make the call to remove the driver */
2004 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2005 cli->srv_name_slash,
2006 archi_table[i].long_archi,
2009 if (!NT_STATUS_IS_OK(status)) {
2010 result = ntstatus_to_werror(status);
2013 if ( !W_ERROR_IS_OK(result) ) {
2014 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2015 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2016 argv[1], archi_table[i].long_archi,
2017 win_errstr(result));
2020 printf ("Driver %s removed for arch [%s].\n", argv[1],
2021 archi_table[i].long_archi);
2028 /****************************************************************************
2029 ****************************************************************************/
2031 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2032 TALLOC_CTX *mem_ctx,
2033 int argc, const char **argv)
2037 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2040 union spoolss_PrintProcessorDirectoryInfo info;
2042 struct dcerpc_binding_handle *b = cli->binding_handle;
2044 /* parse the command arguments */
2046 printf ("Usage: %s [environment]\n", argv[0]);
2051 environment = argv[1];
2054 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2055 cli->srv_name_slash,
2063 if (!NT_STATUS_IS_OK(status)) {
2064 return ntstatus_to_werror(status);
2066 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2068 buffer = data_blob_talloc_zero(mem_ctx, needed);
2070 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2071 cli->srv_name_slash,
2079 if (!NT_STATUS_IS_OK(status)) {
2080 return ntstatus_to_werror(status);
2084 if (W_ERROR_IS_OK(result)) {
2085 printf("%s\n", info.info1.directory_name);
2091 /****************************************************************************
2092 ****************************************************************************/
2094 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2095 int argc, const char **argv)
2097 struct policy_handle handle;
2100 const char *printername;
2101 union spoolss_AddFormInfo info;
2102 struct spoolss_AddFormInfo1 info1;
2103 struct spoolss_AddFormInfo2 info2;
2105 struct dcerpc_binding_handle *b = cli->binding_handle;
2107 /* Parse the command arguments */
2109 if (argc < 3 || argc > 5) {
2110 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2114 /* Get a printer handle */
2116 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2118 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2122 if (!W_ERROR_IS_OK(werror))
2125 /* Dummy up some values for the form data */
2128 level = atoi(argv[3]);
2133 info1.flags = SPOOLSS_FORM_USER;
2134 info1.form_name = argv[2];
2135 info1.size.width = 100;
2136 info1.size.height = 100;
2137 info1.area.left = 0;
2138 info1.area.top = 10;
2139 info1.area.right = 20;
2140 info1.area.bottom = 30;
2142 info.info1 = &info1;
2146 info2.flags = SPOOLSS_FORM_USER;
2147 info2.form_name = argv[2];
2148 info2.size.width = 100;
2149 info2.size.height = 100;
2150 info2.area.left = 0;
2151 info2.area.top = 10;
2152 info2.area.right = 20;
2153 info2.area.bottom = 30;
2154 info2.keyword = argv[2];
2155 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2156 info2.mui_dll = NULL;
2157 info2.ressource_id = 0;
2158 info2.display_name = argv[2];
2161 info.info2 = &info2;
2165 werror = WERR_INVALID_PARAM;
2172 status = dcerpc_spoolss_AddForm(b, mem_ctx,
2177 if (!NT_STATUS_IS_OK(status)) {
2178 werror = ntstatus_to_werror(status);
2182 if (is_valid_policy_hnd(&handle)) {
2184 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2190 /****************************************************************************
2191 ****************************************************************************/
2193 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2194 int argc, const char **argv)
2196 struct policy_handle handle;
2199 const char *printername;
2200 union spoolss_AddFormInfo info;
2201 struct spoolss_AddFormInfo1 info1;
2202 struct dcerpc_binding_handle *b = cli->binding_handle;
2204 /* Parse the command arguments */
2207 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2211 /* Get a printer handle */
2213 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2215 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2217 SEC_FLAG_MAXIMUM_ALLOWED,
2219 if (!W_ERROR_IS_OK(werror))
2222 /* Dummy up some values for the form data */
2224 info1.flags = SPOOLSS_FORM_PRINTER;
2225 info1.size.width = 100;
2226 info1.size.height = 100;
2227 info1.area.left = 0;
2228 info1.area.top = 1000;
2229 info1.area.right = 2000;
2230 info1.area.bottom = 3000;
2231 info1.form_name = argv[2];
2233 info.info1 = &info1;
2237 status = dcerpc_spoolss_SetForm(b, mem_ctx,
2243 if (!NT_STATUS_IS_OK(status)) {
2244 werror = ntstatus_to_werror(status);
2248 if (is_valid_policy_hnd(&handle)) {
2250 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2256 /****************************************************************************
2257 ****************************************************************************/
2259 static const char *get_form_flag(int form_flag)
2261 switch (form_flag) {
2262 case SPOOLSS_FORM_USER:
2264 case SPOOLSS_FORM_BUILTIN:
2265 return "FORM_BUILTIN";
2266 case SPOOLSS_FORM_PRINTER:
2267 return "FORM_PRINTER";
2273 /****************************************************************************
2274 ****************************************************************************/
2276 static void display_form_info1(struct spoolss_FormInfo1 *r)
2279 "\tflag: %s (%d)\n" \
2280 "\twidth: %d, length: %d\n" \
2281 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2282 r->form_name, get_form_flag(r->flags), r->flags,
2283 r->size.width, r->size.height,
2284 r->area.left, r->area.right,
2285 r->area.top, r->area.bottom);
2288 /****************************************************************************
2289 ****************************************************************************/
2291 static void display_form_info2(struct spoolss_FormInfo2 *r)
2294 "\tflag: %s (%d)\n" \
2295 "\twidth: %d, length: %d\n" \
2296 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2297 r->form_name, get_form_flag(r->flags), r->flags,
2298 r->size.width, r->size.height,
2299 r->area.left, r->area.right,
2300 r->area.top, r->area.bottom);
2301 printf("\tkeyword: %s\n", r->keyword);
2302 printf("\tstring_type: 0x%08x\n", r->string_type);
2303 printf("\tmui_dll: %s\n", r->mui_dll);
2304 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2305 printf("\tdisplay_name: %s\n", r->display_name);
2306 printf("\tlang_id: %d\n", r->lang_id);
2310 /****************************************************************************
2311 ****************************************************************************/
2313 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2314 int argc, const char **argv)
2316 struct policy_handle handle;
2319 const char *printername;
2321 uint32_t offered = 0;
2322 union spoolss_FormInfo info;
2325 struct dcerpc_binding_handle *b = cli->binding_handle;
2327 /* Parse the command arguments */
2329 if (argc < 3 || argc > 5) {
2330 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2334 /* Get a printer handle */
2336 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2338 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2340 SEC_FLAG_MAXIMUM_ALLOWED,
2342 if (!W_ERROR_IS_OK(werror))
2346 level = atoi(argv[3]);
2351 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2360 if (!NT_STATUS_IS_OK(status)) {
2361 werror = ntstatus_to_werror(status);
2364 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2365 buffer = data_blob_talloc_zero(mem_ctx, needed);
2367 status = dcerpc_spoolss_GetForm(b, mem_ctx,
2376 if (!NT_STATUS_IS_OK(status)) {
2377 werror = ntstatus_to_werror(status);
2382 if (!W_ERROR_IS_OK(werror)) {
2388 display_form_info1(&info.info1);
2391 display_form_info2(&info.info2);
2396 if (is_valid_policy_hnd(&handle)) {
2398 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2404 /****************************************************************************
2405 ****************************************************************************/
2407 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2408 TALLOC_CTX *mem_ctx, int argc,
2411 struct policy_handle handle;
2414 const char *printername;
2415 struct dcerpc_binding_handle *b = cli->binding_handle;
2417 /* Parse the command arguments */
2420 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2424 /* Get a printer handle */
2426 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2428 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2430 SEC_FLAG_MAXIMUM_ALLOWED,
2432 if (!W_ERROR_IS_OK(werror))
2435 /* Delete the form */
2437 status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2441 if (!NT_STATUS_IS_OK(status)) {
2442 werror = ntstatus_to_werror(status);
2447 if (is_valid_policy_hnd(&handle)) {
2449 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2455 /****************************************************************************
2456 ****************************************************************************/
2458 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2459 TALLOC_CTX *mem_ctx, int argc,
2462 struct policy_handle handle;
2464 const char *printername;
2465 uint32_t num_forms, level = 1, i;
2466 union spoolss_FormInfo *forms;
2467 struct dcerpc_binding_handle *b = cli->binding_handle;
2469 /* Parse the command arguments */
2471 if (argc < 2 || argc > 4) {
2472 printf ("Usage: %s <printer> [level]\n", argv[0]);
2476 /* Get a printer handle */
2478 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2480 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2482 SEC_FLAG_MAXIMUM_ALLOWED,
2484 if (!W_ERROR_IS_OK(werror))
2488 level = atoi(argv[2]);
2491 /* Enumerate forms */
2493 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2500 if (!W_ERROR_IS_OK(werror))
2503 /* Display output */
2505 for (i = 0; i < num_forms; i++) {
2508 display_form_info1(&forms[i].info1);
2511 display_form_info2(&forms[i].info2);
2517 if (is_valid_policy_hnd(&handle)) {
2519 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2525 /****************************************************************************
2526 ****************************************************************************/
2528 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2529 TALLOC_CTX *mem_ctx,
2530 int argc, const char **argv)
2534 const char *printername;
2535 struct policy_handle pol;
2536 union spoolss_PrinterInfo info;
2537 enum winreg_Type type;
2538 union spoolss_PrinterData data;
2540 struct dcerpc_binding_handle *b = cli->binding_handle;
2542 /* parse the command arguments */
2544 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2545 " <value> <data>\n",
2550 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2554 if (strequal(argv[2], "string")) {
2558 if (strequal(argv[2], "binary")) {
2562 if (strequal(argv[2], "dword")) {
2566 if (strequal(argv[2], "multistring")) {
2567 type = REG_MULTI_SZ;
2570 if (type == REG_NONE) {
2571 printf("Unknown data type: %s\n", argv[2]);
2572 result = WERR_INVALID_PARAM;
2576 /* get a printer handle */
2578 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2580 SEC_FLAG_MAXIMUM_ALLOWED,
2582 if (!W_ERROR_IS_OK(result)) {
2586 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2591 if (!W_ERROR_IS_OK(result)) {
2595 printf("%s\n", current_timestring(mem_ctx, true));
2596 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2598 /* Set the printer data */
2602 data.string = talloc_strdup(mem_ctx, argv[4]);
2603 W_ERROR_HAVE_NO_MEMORY(data.string);
2606 data.value = strtoul(argv[4], NULL, 10);
2609 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2611 case REG_MULTI_SZ: {
2613 const char **strings = NULL;
2615 for (i=4; i<argc; i++) {
2616 if (strcmp(argv[i], "NULL") == 0) {
2619 if (!add_string_to_array(mem_ctx, argv[i],
2622 result = WERR_NOMEM;
2626 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2627 if (!data.string_array) {
2628 result = WERR_NOMEM;
2631 for (i=0; i < num_strings; i++) {
2632 data.string_array[i] = strings[i];
2637 printf("Unknown data type: %s\n", argv[2]);
2638 result = WERR_INVALID_PARAM;
2642 result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2643 if (!W_ERROR_IS_OK(result)) {
2647 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2649 argv[3], /* value_name */
2654 if (!NT_STATUS_IS_OK(status)) {
2655 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2656 result = ntstatus_to_werror(status);
2659 if (!W_ERROR_IS_OK(result)) {
2660 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2663 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2665 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2670 if (!W_ERROR_IS_OK(result)) {
2674 printf("%s\n", current_timestring(mem_ctx, true));
2675 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2679 if (is_valid_policy_hnd(&pol)) {
2681 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2687 /****************************************************************************
2688 ****************************************************************************/
2690 static void display_job_info1(struct spoolss_JobInfo1 *r)
2692 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2693 r->user_name, r->document_name, r->text_status, r->pages_printed,
2697 /****************************************************************************
2698 ****************************************************************************/
2700 static void display_job_info2(struct spoolss_JobInfo2 *r)
2702 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2703 r->position, r->job_id,
2704 r->user_name, r->document_name, r->text_status, r->pages_printed,
2705 r->total_pages, r->size);
2708 /****************************************************************************
2709 ****************************************************************************/
2711 static void display_job_info3(struct spoolss_JobInfo3 *r)
2713 printf("jobid[%d], next_jobid[%d]\n",
2714 r->job_id, r->next_job_id);
2717 /****************************************************************************
2718 ****************************************************************************/
2720 static void display_job_info4(struct spoolss_JobInfo4 *r)
2722 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2723 r->position, r->job_id,
2724 r->user_name, r->document_name, r->text_status, r->pages_printed,
2725 r->total_pages, r->size, r->size_high);
2728 /****************************************************************************
2729 ****************************************************************************/
2731 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2732 TALLOC_CTX *mem_ctx, int argc,
2736 uint32_t level = 1, count, i;
2737 const char *printername;
2738 struct policy_handle hnd;
2739 union spoolss_JobInfo *info;
2740 struct dcerpc_binding_handle *b = cli->binding_handle;
2742 if (argc < 2 || argc > 3) {
2743 printf("Usage: %s printername [level]\n", argv[0]);
2748 level = atoi(argv[2]);
2751 /* Open printer handle */
2753 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2755 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2757 SEC_FLAG_MAXIMUM_ALLOWED,
2759 if (!W_ERROR_IS_OK(result))
2762 /* Enumerate ports */
2764 result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2772 if (!W_ERROR_IS_OK(result)) {
2776 for (i = 0; i < count; i++) {
2779 display_job_info1(&info[i].info1);
2782 display_job_info2(&info[i].info2);
2785 d_printf("unknown info level %d\n", level);
2791 if (is_valid_policy_hnd(&hnd)) {
2793 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2799 /****************************************************************************
2800 ****************************************************************************/
2802 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2803 TALLOC_CTX *mem_ctx, int argc,
2807 const char *printername;
2808 struct policy_handle hnd;
2811 union spoolss_JobInfo info;
2812 struct dcerpc_binding_handle *b = cli->binding_handle;
2814 if (argc < 3 || argc > 4) {
2815 printf("Usage: %s printername job_id [level]\n", argv[0]);
2819 job_id = atoi(argv[2]);
2822 level = atoi(argv[3]);
2825 /* Open printer handle */
2827 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2829 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2831 SEC_FLAG_MAXIMUM_ALLOWED,
2833 if (!W_ERROR_IS_OK(result)) {
2837 /* Enumerate ports */
2839 result = rpccli_spoolss_getjob(cli, mem_ctx,
2846 if (!W_ERROR_IS_OK(result)) {
2852 display_job_info1(&info.info1);
2855 display_job_info2(&info.info2);
2858 display_job_info3(&info.info3);
2861 display_job_info4(&info.info4);
2864 d_printf("unknown info level %d\n", level);
2869 if (is_valid_policy_hnd(&hnd)) {
2871 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2877 /****************************************************************************
2878 ****************************************************************************/
2882 enum spoolss_JobControl val;
2884 {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2885 {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2886 {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2887 {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2888 {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2889 {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2890 {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2891 {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2892 {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2895 static enum spoolss_JobControl parse_setjob_command(const char *cmd)
2899 for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
2900 if (strequal(cmdvals[i].name, cmd)) {
2901 return cmdvals[i].val;
2904 return (enum spoolss_JobControl)atoi(cmd);
2907 static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
2908 TALLOC_CTX *mem_ctx, int argc,
2913 const char *printername;
2914 struct policy_handle hnd;
2916 enum spoolss_JobControl command;
2917 struct dcerpc_binding_handle *b = cli->binding_handle;
2920 printf("Usage: %s printername job_id command\n", argv[0]);
2921 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
2922 "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
2926 job_id = atoi(argv[2]);
2927 command = parse_setjob_command(argv[3]);
2929 /* Open printer handle */
2931 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2933 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2935 SEC_FLAG_MAXIMUM_ALLOWED,
2937 if (!W_ERROR_IS_OK(result)) {
2943 status = dcerpc_spoolss_SetJob(b, mem_ctx,
2949 if (!NT_STATUS_IS_OK(status)) {
2950 result = ntstatus_to_werror(status);
2953 if (!W_ERROR_IS_OK(result)) {
2958 if (is_valid_policy_hnd(&hnd)) {
2960 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2966 /****************************************************************************
2967 ****************************************************************************/
2969 static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
2970 TALLOC_CTX *mem_ctx, int argc,
2975 const char *printername;
2976 struct policy_handle hnd;
2977 uint32_t value_needed;
2978 enum winreg_Type type;
2979 uint32_t data_needed;
2980 struct dcerpc_binding_handle *b = cli->binding_handle;
2981 struct spoolss_EnumPrinterData r;
2984 printf("Usage: %s printername\n", argv[0]);
2988 /* Open printer handle */
2990 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2992 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2994 SEC_FLAG_MAXIMUM_ALLOWED,
2996 if (!W_ERROR_IS_OK(result)) {
3000 /* Enumerate data */
3003 r.in.enum_index = 0;
3004 r.in.value_offered = 0;
3005 r.in.data_offered = 0;
3006 r.out.value_name = NULL;
3007 r.out.value_needed = &value_needed;
3010 r.out.data_needed = &data_needed;
3012 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3013 if (!NT_STATUS_IS_OK(status)) {
3014 result = ntstatus_to_werror(status);
3018 if (!W_ERROR_IS_OK(r.out.result)) {
3019 result = r.out.result;
3023 r.in.data_offered = *r.out.data_needed;
3024 r.in.value_offered = *r.out.value_needed;
3025 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3026 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3030 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3031 if (!NT_STATUS_IS_OK(status)) {
3032 result = ntstatus_to_werror(status);
3036 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3044 struct regval_blob *v;
3046 v = regval_compose(talloc_tos(),
3052 result = WERR_NOMEM;
3056 display_reg_value(v);
3060 } while (W_ERROR_IS_OK(r.out.result));
3063 if (is_valid_policy_hnd(&hnd)) {
3065 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3071 /****************************************************************************
3072 ****************************************************************************/
3074 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3075 TALLOC_CTX *mem_ctx, int argc,
3080 const char *printername;
3081 struct policy_handle hnd;
3083 struct spoolss_PrinterEnumValues *info;
3084 struct dcerpc_binding_handle *b = cli->binding_handle;
3087 printf("Usage: %s printername <keyname>\n", argv[0]);
3091 /* Open printer handle */
3093 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3095 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3097 SEC_FLAG_MAXIMUM_ALLOWED,
3099 if (!W_ERROR_IS_OK(result)) {
3103 /* Enumerate subkeys */
3105 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3111 if (!W_ERROR_IS_OK(result)) {
3115 for (i=0; i < count; i++) {
3116 display_printer_data(info[i].value_name,
3119 info[i].data->length);
3123 if (is_valid_policy_hnd(&hnd)) {
3125 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3131 /****************************************************************************
3132 ****************************************************************************/
3134 static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3135 TALLOC_CTX *mem_ctx, int argc,
3139 const char *printername;
3140 const char *keyname = NULL;
3141 struct policy_handle hnd;
3142 const char **key_buffer = NULL;
3144 uint32_t offered = 0;
3145 struct dcerpc_binding_handle *b = cli->binding_handle;
3147 if (argc < 2 || argc > 4) {
3148 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3159 offered = atoi(argv[3]);
3162 /* Open printer handle */
3164 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3166 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3168 SEC_FLAG_MAXIMUM_ALLOWED,
3170 if (!W_ERROR_IS_OK(result)) {
3174 /* Enumerate subkeys */
3176 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3182 if (!W_ERROR_IS_OK(result)) {
3186 for (i=0; key_buffer && key_buffer[i]; i++) {
3187 printf("%s\n", key_buffer[i]);
3192 if (is_valid_policy_hnd(&hnd)) {
3194 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3200 /****************************************************************************
3201 ****************************************************************************/
3203 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3204 TALLOC_CTX *mem_ctx, int argc,
3207 const char *printername;
3208 const char *clientname;
3209 struct policy_handle hnd;
3212 struct spoolss_NotifyOption option;
3213 struct dcerpc_binding_handle *b = cli->binding_handle;
3216 printf("Usage: %s printername\n", argv[0]);
3223 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3225 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3227 SEC_FLAG_MAXIMUM_ALLOWED,
3229 if (!W_ERROR_IS_OK(result)) {
3230 printf("Error opening %s\n", argv[1]);
3234 /* Create spool options */
3239 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3240 if (option.types == NULL) {
3241 result = WERR_NOMEM;
3245 option.types[0].type = PRINTER_NOTIFY_TYPE;
3246 option.types[0].count = 1;
3247 option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3248 if (option.types[0].fields == NULL) {
3249 result = WERR_NOMEM;
3252 option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3254 option.types[1].type = JOB_NOTIFY_TYPE;
3255 option.types[1].count = 1;
3256 option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3257 if (option.types[1].fields == NULL) {
3258 result = WERR_NOMEM;
3261 option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3263 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
3265 result = WERR_NOMEM;
3271 status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3279 if (!NT_STATUS_IS_OK(status)) {
3280 result = ntstatus_to_werror(status);
3283 if (!W_ERROR_IS_OK(result)) {
3284 printf("Error rffpcnex %s\n", argv[1]);
3289 if (is_valid_policy_hnd(&hnd)) {
3291 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3297 /****************************************************************************
3298 ****************************************************************************/
3300 static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3301 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3303 union spoolss_PrinterInfo info1, info2;
3305 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3307 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3308 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3313 if ( !W_ERROR_IS_OK(werror) ) {
3314 printf("failed (%s)\n", win_errstr(werror));
3315 talloc_destroy(mem_ctx);
3320 printf("Retrieving printer properties for %s...", cli2->desthost);
3321 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3326 if ( !W_ERROR_IS_OK(werror) ) {
3327 printf("failed (%s)\n", win_errstr(werror));
3328 talloc_destroy(mem_ctx);
3333 talloc_destroy(mem_ctx);
3338 /****************************************************************************
3339 ****************************************************************************/
3341 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3342 struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3344 union spoolss_PrinterInfo info1, info2;
3346 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3347 struct security_descriptor *sd1, *sd2;
3351 printf("Retrieving printer security for %s...", cli1->desthost);
3352 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3357 if ( !W_ERROR_IS_OK(werror) ) {
3358 printf("failed (%s)\n", win_errstr(werror));
3364 printf("Retrieving printer security for %s...", cli2->desthost);
3365 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3370 if ( !W_ERROR_IS_OK(werror) ) {
3371 printf("failed (%s)\n", win_errstr(werror));
3380 sd1 = info1.info3.secdesc;
3381 sd2 = info2.info3.secdesc;
3383 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3384 printf("NULL secdesc!\n");
3389 if (!security_descriptor_equal( sd1, sd2 ) ) {
3390 printf("Security Descriptors *not* equal!\n");
3395 printf("Security descriptors match\n");
3398 talloc_destroy(mem_ctx);
3403 /****************************************************************************
3404 ****************************************************************************/
3406 extern struct user_auth_info *rpcclient_auth_info;
3408 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3409 TALLOC_CTX *mem_ctx, int argc,
3412 const char *printername;
3413 char *printername_path = NULL;
3414 struct cli_state *cli_server2 = NULL;
3415 struct rpc_pipe_client *cli2 = NULL;
3416 struct policy_handle hPrinter1, hPrinter2;
3421 printf("Usage: %s <printer> <server>\n", argv[0]);
3425 printername = argv[1];
3427 /* first get the connection to the remote server */
3429 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
3432 get_cmdline_auth_info_username(rpcclient_auth_info),
3434 get_cmdline_auth_info_password(rpcclient_auth_info),
3435 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
3436 get_cmdline_auth_info_signing_state(rpcclient_auth_info));
3438 if ( !NT_STATUS_IS_OK(nt_status) )
3439 return WERR_GENERAL_FAILURE;
3441 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
3443 if (!NT_STATUS_IS_OK(nt_status)) {
3444 printf("failed to open spoolss pipe on server %s (%s)\n",
3445 argv[2], nt_errstr(nt_status));
3446 return WERR_GENERAL_FAILURE;
3449 /* now open up both printers */
3451 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3453 printf("Opening %s...", printername_path);
3455 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3459 if ( !W_ERROR_IS_OK(werror) ) {
3460 printf("failed (%s)\n", win_errstr(werror));
3465 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3467 printf("Opening %s...", printername_path);
3468 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3472 if ( !W_ERROR_IS_OK(werror) ) {
3473 printf("failed (%s)\n", win_errstr(werror));
3478 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3479 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3481 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3488 printf("Closing printers...");
3491 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3492 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3496 /* close the second remote connection */
3498 cli_shutdown( cli_server2 );
3502 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3504 printf("print_processor_name: %s\n", r->print_processor_name);
3507 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3508 TALLOC_CTX *mem_ctx, int argc,
3512 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3513 uint32_t num_procs, level = 1, i;
3514 union spoolss_PrintProcessorInfo *procs;
3516 /* Parse the command arguments */
3518 if (argc < 1 || argc > 4) {
3519 printf ("Usage: %s [environment] [level]\n", argv[0]);
3524 environment = argv[1];
3528 level = atoi(argv[2]);
3531 /* Enumerate Print Processors */
3533 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3534 cli->srv_name_slash,
3540 if (!W_ERROR_IS_OK(werror))
3543 /* Display output */
3545 for (i = 0; i < num_procs; i++) {
3548 display_proc_info1(&procs[i].info1);
3557 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3559 printf("name_array: %s\n", r->name_array);
3562 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3563 TALLOC_CTX *mem_ctx, int argc,
3567 const char *print_processor_name = "winprint";
3568 uint32_t num_procs, level = 1, i;
3569 union spoolss_PrintProcDataTypesInfo *procs;
3571 /* Parse the command arguments */
3573 if (argc < 1 || argc > 4) {
3574 printf ("Usage: %s [environment] [level]\n", argv[0]);
3579 print_processor_name = argv[1];
3583 level = atoi(argv[2]);
3586 /* Enumerate Print Processor Data Types */
3588 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3589 cli->srv_name_slash,
3590 print_processor_name,
3595 if (!W_ERROR_IS_OK(werror))
3598 /* Display output */
3600 for (i = 0; i < num_procs; i++) {
3603 display_proc_data_types_info1(&procs[i].info1);
3612 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3614 printf("monitor_name: %s\n", r->monitor_name);
3617 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3619 printf("monitor_name: %s\n", r->monitor_name);
3620 printf("environment: %s\n", r->environment);
3621 printf("dll_name: %s\n", r->dll_name);
3624 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3625 TALLOC_CTX *mem_ctx, int argc,
3629 uint32_t count, level = 1, i;
3630 union spoolss_MonitorInfo *info;
3632 /* Parse the command arguments */
3635 printf("Usage: %s [level]\n", argv[0]);
3640 level = atoi(argv[1]);
3643 /* Enumerate Print Monitors */
3645 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3646 cli->srv_name_slash,
3651 if (!W_ERROR_IS_OK(werror)) {
3655 /* Display output */
3657 for (i = 0; i < count; i++) {
3660 display_monitor1(&info[i].info1);
3663 display_monitor2(&info[i].info2);
3672 static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3673 TALLOC_CTX *mem_ctx, int argc,
3678 struct policy_handle handle, gdi_handle;
3679 const char *printername;
3680 struct spoolss_DevmodeContainer devmode_ctr;
3681 struct dcerpc_binding_handle *b = cli->binding_handle;
3683 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3685 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3687 SEC_FLAG_MAXIMUM_ALLOWED,
3689 if (!W_ERROR_IS_OK(result)) {
3693 ZERO_STRUCT(devmode_ctr);
3695 status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3700 if (!NT_STATUS_IS_OK(status)) {
3701 result = ntstatus_to_werror(status);
3704 if (!W_ERROR_IS_OK(result)) {
3709 if (is_valid_policy_hnd(&gdi_handle)) {
3711 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3713 if (is_valid_policy_hnd(&handle)) {
3715 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3721 /* List of commands exported by this module */
3722 struct cmd_set spoolss_commands[] = {
3726 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &ndr_table_spoolss.syntax_id, NULL, "Add a print driver", "" },
3727 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &ndr_table_spoolss.syntax_id, NULL, "Add a printer", "" },
3728 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver", "" },
3729 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files", "" },
3730 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data", "" },
3731 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key", "" },
3732 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys", "" },
3733 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs", "" },
3734 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &ndr_table_spoolss.syntax_id, NULL, "Get print job", "" },
3735 { "setjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job, &ndr_table_spoolss.syntax_id, NULL, "Set print job", "" },
3736 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports", "" },
3737 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
3738 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers", "" },
3739 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Get print driver data", "" },
3740 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
3741 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &ndr_table_spoolss.syntax_id, NULL, "Get print driver information", "" },
3742 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory", "" },
3743 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &ndr_table_spoolss.syntax_id, NULL, "Get printer info", "" },
3744 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3745 { "openprinter_ex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &ndr_table_spoolss.syntax_id, NULL, "Open printer handle", "" },
3746 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &ndr_table_spoolss.syntax_id, NULL, "Set printer driver", "" },
3747 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory", "" },
3748 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &ndr_table_spoolss.syntax_id, NULL, "Add form", "" },
3749 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &ndr_table_spoolss.syntax_id, NULL, "Set form", "" },
3750 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &ndr_table_spoolss.syntax_id, NULL, "Get form", "" },
3751 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &ndr_table_spoolss.syntax_id, NULL, "Delete form", "" },
3752 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms", "" },
3753 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &ndr_table_spoolss.syntax_id, NULL, "Set printer comment", "" },
3754 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &ndr_table_spoolss.syntax_id, NULL, "Set printername", "" },
3755 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data", "" },
3756 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
3757 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
3758 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" },
3759 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
3760 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
3761 { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },