s3-rpcclient: add enummonitors command to enumerate print monitors.
[Samba/fernandojvsilva.git] / source3 / rpcclient / cmd_spoolss.c
blob6cbdf89583fc9e1b4e12837955cdab9ebf5fa818
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpcclient.h"
27 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
28 { \
29 _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
30 _cli->srv_name_slash, _arg); \
31 W_ERROR_HAVE_NO_MEMORY(_printername); \
34 struct table_node {
35 const char *long_archi;
36 const char *short_archi;
37 int version;
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 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 },
57 {NULL, "", -1 }
60 /**
61 * @file
63 * rpcclient module for SPOOLSS rpc pipe.
65 * This generally just parses and checks command lines, and then calls
66 * a cli_spoolss function.
67 **/
69 /****************************************************************************
70 function to do the mapping between the long architecture name and
71 the short one.
72 ****************************************************************************/
74 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
76 int i=-1;
78 DEBUG(107,("Getting architecture dependant directory\n"));
79 do {
80 i++;
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));
86 return NULL;
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,
103 TALLOC_CTX *mem_ctx,
104 int argc, const char **argv)
106 WERROR werror;
107 POLICY_HND hnd;
109 if (argc != 2) {
110 printf("Usage: %s <printername>\n", argv[0]);
111 return WERR_OK;
114 if (!cli)
115 return WERR_GENERAL_FAILURE;
117 /* Open the printer handle */
119 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
120 argv[1],
121 PRINTER_ALL_ACCESS,
122 &hnd);
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", argv[1]);
125 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
127 if (!W_ERROR_IS_OK(werror)) {
128 printf("Error closing printer handle! (%s)\n",
129 get_dos_error_msg(werror));
133 return werror;
137 /****************************************************************************
138 ****************************************************************************/
140 static void display_print_info_0(PRINTER_INFO_0 *i0)
142 fstring name = "";
143 fstring servername = "";
145 if (!i0)
146 return;
148 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
150 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
152 printf("\tprintername:[%s]\n", name);
153 printf("\tservername:[%s]\n", servername);
154 printf("\tcjobs:[0x%x]\n", i0->cjobs);
155 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
157 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
158 i0->day, i0->dayofweek);
159 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
160 i0->second, i0->milliseconds);
162 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
163 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
165 printf("\tmajorversion:[0x%x]\n", i0->major_version);
166 printf("\tbuildversion:[0x%x]\n", i0->build_version);
168 printf("\tunknown7:[0x%x]\n", i0->unknown7);
169 printf("\tunknown8:[0x%x]\n", i0->unknown8);
170 printf("\tunknown9:[0x%x]\n", i0->unknown9);
171 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
172 printf("\tunknown11:[0x%x]\n", i0->unknown11);
173 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
174 printf("\tunknown13:[0x%x]\n", i0->unknown13);
175 printf("\tunknown14:[0x%x]\n", i0->unknown14);
176 printf("\tunknown15:[0x%x]\n", i0->unknown15);
177 printf("\tunknown16:[0x%x]\n", i0->unknown16);
178 printf("\tchange_id:[0x%x]\n", i0->change_id);
179 printf("\tunknown18:[0x%x]\n", i0->unknown18);
180 printf("\tstatus:[0x%x]\n", i0->status);
181 printf("\tunknown20:[0x%x]\n", i0->unknown20);
182 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
183 printf("\tunknown22:[0x%x]\n", i0->unknown22);
184 printf("\tunknown23:[0x%x]\n", i0->unknown23);
185 printf("\tunknown24:[0x%x]\n", i0->unknown24);
186 printf("\tunknown25:[0x%x]\n", i0->unknown25);
187 printf("\tunknown26:[0x%x]\n", i0->unknown26);
188 printf("\tunknown27:[0x%x]\n", i0->unknown27);
189 printf("\tunknown28:[0x%x]\n", i0->unknown28);
190 printf("\tunknown29:[0x%x]\n", i0->unknown29);
192 printf("\n");
195 /****************************************************************************
196 ****************************************************************************/
198 static void display_print_info_1(PRINTER_INFO_1 *i1)
200 fstring desc = "";
201 fstring name = "";
202 fstring comm = "";
204 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
205 STR_TERMINATE);
207 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
208 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
210 printf("\tflags:[0x%x]\n", i1->flags);
211 printf("\tname:[%s]\n", name);
212 printf("\tdescription:[%s]\n", desc);
213 printf("\tcomment:[%s]\n", comm);
215 printf("\n");
218 /****************************************************************************
219 ****************************************************************************/
221 static void display_print_info_2(PRINTER_INFO_2 *i2)
223 fstring servername = "";
224 fstring printername = "";
225 fstring sharename = "";
226 fstring portname = "";
227 fstring drivername = "";
228 fstring comment = "";
229 fstring location = "";
230 fstring sepfile = "";
231 fstring printprocessor = "";
232 fstring datatype = "";
233 fstring parameters = "";
235 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
236 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
237 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
238 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
239 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
240 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
241 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
242 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
243 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
244 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
245 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
247 printf("\tservername:[%s]\n", servername);
248 printf("\tprintername:[%s]\n", printername);
249 printf("\tsharename:[%s]\n", sharename);
250 printf("\tportname:[%s]\n", portname);
251 printf("\tdrivername:[%s]\n", drivername);
252 printf("\tcomment:[%s]\n", comment);
253 printf("\tlocation:[%s]\n", location);
254 printf("\tsepfile:[%s]\n", sepfile);
255 printf("\tprintprocessor:[%s]\n", printprocessor);
256 printf("\tdatatype:[%s]\n", datatype);
257 printf("\tparameters:[%s]\n", parameters);
258 printf("\tattributes:[0x%x]\n", i2->attributes);
259 printf("\tpriority:[0x%x]\n", i2->priority);
260 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
261 printf("\tstarttime:[0x%x]\n", i2->starttime);
262 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
263 printf("\tstatus:[0x%x]\n", i2->status);
264 printf("\tcjobs:[0x%x]\n", i2->cjobs);
265 printf("\taverageppm:[0x%x]\n", i2->averageppm);
267 if (i2->secdesc)
268 display_sec_desc(i2->secdesc);
270 printf("\n");
273 /****************************************************************************
274 ****************************************************************************/
276 static void display_print_info_3(PRINTER_INFO_3 *i3)
278 display_sec_desc(i3->secdesc);
280 printf("\n");
283 /****************************************************************************
284 ****************************************************************************/
286 static void display_print_info7(struct spoolss_PrinterInfo7 *r)
288 printf("\tguid:[%s]\n", r->guid);
289 printf("\taction:[0x%x]\n", r->action);
293 /****************************************************************************
294 ****************************************************************************/
296 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
297 TALLOC_CTX *mem_ctx,
298 int argc, const char **argv)
300 WERROR result;
301 uint32 info_level = 1;
302 PRINTER_INFO_CTR ctr;
303 uint32 i = 0, num_printers;
304 fstring name;
306 if (argc > 3)
308 printf("Usage: %s [level] [name]\n", argv[0]);
309 return WERR_OK;
312 if (argc >= 2)
313 info_level = atoi(argv[1]);
315 if (argc == 3)
316 fstrcpy(name, argv[2]);
317 else {
318 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
319 strupper_m(name);
322 ZERO_STRUCT(ctr);
324 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
325 info_level, &num_printers, &ctr);
327 if (W_ERROR_IS_OK(result)) {
329 if (!num_printers) {
330 printf ("No printers returned.\n");
331 goto done;
334 for (i = 0; i < num_printers; i++) {
335 switch(info_level) {
336 case 0:
337 display_print_info_0(&ctr.printers_0[i]);
338 break;
339 case 1:
340 display_print_info_1(&ctr.printers_1[i]);
341 break;
342 case 2:
343 display_print_info_2(&ctr.printers_2[i]);
344 break;
345 case 3:
346 display_print_info_3(&ctr.printers_3[i]);
347 break;
348 default:
349 printf("unknown info level %d\n", info_level);
350 goto done;
354 done:
356 return result;
359 /****************************************************************************
360 ****************************************************************************/
362 static void display_port_info_1(struct spoolss_PortInfo1 *r)
364 printf("\tPort Name:\t[%s]\n", r->port_name);
367 /****************************************************************************
368 ****************************************************************************/
370 static void display_port_info_2(struct spoolss_PortInfo2 *r)
372 printf("\tPort Name:\t[%s]\n", r->port_name);
373 printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
374 printf("\tDescription:\t[%s]\n", r->description);
375 printf("\tPort Type:\t" );
376 if (r->port_type) {
377 int comma = 0; /* hack */
378 printf( "[" );
379 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
380 printf( "Read" );
381 comma = 1;
383 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
384 printf( "%sWrite", comma ? ", " : "" );
385 comma = 1;
387 /* These two have slightly different interpretations
388 on 95/98/ME but I'm disregarding that for now */
389 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
390 printf( "%sRedirected", comma ? ", " : "" );
391 comma = 1;
393 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
394 printf( "%sNet-Attached", comma ? ", " : "" );
396 printf( "]\n" );
397 } else {
398 printf( "[Unset]\n" );
400 printf("\tReserved:\t[%d]\n", r->reserved);
401 printf("\n");
404 /****************************************************************************
405 ****************************************************************************/
407 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
408 TALLOC_CTX *mem_ctx, int argc,
409 const char **argv)
411 WERROR result;
412 uint32 info_level = 1;
413 uint32 returned;
414 union spoolss_PortInfo *info;
416 if (argc > 2) {
417 printf("Usage: %s [level]\n", argv[0]);
418 return WERR_OK;
421 if (argc == 2)
422 info_level = atoi(argv[1]);
424 /* Enumerate ports */
426 result = rpccli_spoolss_enumports(cli, mem_ctx,
427 cli->srv_name_slash,
428 info_level,
430 &returned,
431 &info);
432 if (W_ERROR_IS_OK(result)) {
433 int i;
435 for (i = 0; i < returned; i++) {
436 switch (info_level) {
437 case 1:
438 display_port_info_1(&info[i].info1);
439 break;
440 case 2:
441 display_port_info_2(&info[i].info2);
442 break;
443 default:
444 printf("unknown info level %d\n", info_level);
445 break;
450 return result;
453 /****************************************************************************
454 ****************************************************************************/
456 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
457 TALLOC_CTX *mem_ctx,
458 int argc, const char **argv)
460 POLICY_HND pol;
461 WERROR result;
462 NTSTATUS status;
463 uint32 info_level = 2;
464 union spoolss_PrinterInfo info;
465 struct spoolss_SetPrinterInfoCtr info_ctr;
466 const char *printername, *comment = NULL;
467 struct spoolss_DevmodeContainer devmode_ctr;
468 struct sec_desc_buf secdesc_ctr;
470 if (argc == 1 || argc > 3) {
471 printf("Usage: %s printername comment\n", argv[0]);
473 return WERR_OK;
476 /* Open a printer handle */
477 if (argc == 3) {
478 comment = argv[2];
481 ZERO_STRUCT(devmode_ctr);
482 ZERO_STRUCT(secdesc_ctr);
484 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
486 /* get a printer handle */
487 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
488 printername,
489 PRINTER_ALL_ACCESS,
490 &pol);
491 if (!W_ERROR_IS_OK(result))
492 goto done;
494 /* Get printer info */
495 result = rpccli_spoolss_getprinter(cli, mem_ctx,
496 &pol,
497 info_level,
499 &info);
500 if (!W_ERROR_IS_OK(result))
501 goto done;
504 /* Modify the comment. */
505 info.info2.comment = comment;
506 info.info2.secdesc = NULL;
507 info.info2.devmode = NULL;
509 info_ctr.level = 2;
510 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
512 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
513 &pol,
514 &info_ctr,
515 &devmode_ctr,
516 &secdesc_ctr,
517 0, /* command */
518 &result);
519 if (W_ERROR_IS_OK(result))
520 printf("Success in setting comment.\n");
522 done:
523 if (is_valid_policy_hnd(&pol))
524 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
526 return result;
529 /****************************************************************************
530 ****************************************************************************/
532 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
533 TALLOC_CTX *mem_ctx,
534 int argc, const char **argv)
536 POLICY_HND pol;
537 WERROR result;
538 NTSTATUS status;
539 uint32 info_level = 2;
540 union spoolss_PrinterInfo info;
541 const char *printername,
542 *new_printername = NULL;
543 struct spoolss_SetPrinterInfoCtr info_ctr;
544 struct spoolss_DevmodeContainer devmode_ctr;
545 struct sec_desc_buf secdesc_ctr;
547 ZERO_STRUCT(devmode_ctr);
548 ZERO_STRUCT(secdesc_ctr);
550 if (argc == 1 || argc > 3) {
551 printf("Usage: %s printername new_printername\n", argv[0]);
553 return WERR_OK;
556 /* Open a printer handle */
557 if (argc == 3) {
558 new_printername = argv[2];
561 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
563 /* get a printer handle */
564 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
565 printername,
566 PRINTER_ALL_ACCESS,
567 &pol);
568 if (!W_ERROR_IS_OK(result))
569 goto done;
571 /* Get printer info */
572 result = rpccli_spoolss_getprinter(cli, mem_ctx,
573 &pol,
574 info_level,
576 &info);
577 if (!W_ERROR_IS_OK(result))
578 goto done;
580 /* Modify the printername. */
581 info.info2.printername = new_printername;
582 info.info2.devmode = NULL;
583 info.info2.secdesc = NULL;
585 info_ctr.level = info_level;
586 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
588 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
589 &pol,
590 &info_ctr,
591 &devmode_ctr,
592 &secdesc_ctr,
593 0, /* command */
594 &result);
595 if (W_ERROR_IS_OK(result))
596 printf("Success in setting printername.\n");
598 done:
599 if (is_valid_policy_hnd(&pol))
600 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
602 return result;
605 /****************************************************************************
606 ****************************************************************************/
608 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
609 TALLOC_CTX *mem_ctx,
610 int argc, const char **argv)
612 POLICY_HND pol;
613 WERROR result;
614 uint32 info_level = 1;
615 const char *printername;
616 union spoolss_PrinterInfo info;
618 if (argc == 1 || argc > 3) {
619 printf("Usage: %s <printername> [level]\n", argv[0]);
620 return WERR_OK;
623 /* Open a printer handle */
624 if (argc == 3) {
625 info_level = atoi(argv[2]);
628 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
630 /* get a printer handle */
632 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
633 printername,
634 SEC_FLAG_MAXIMUM_ALLOWED,
635 &pol);
636 if (!W_ERROR_IS_OK(result))
637 goto done;
639 /* Get printer info */
641 result = rpccli_spoolss_getprinter(cli, mem_ctx,
642 &pol,
643 info_level,
645 &info);
646 if (!W_ERROR_IS_OK(result))
647 goto done;
649 /* Display printer info */
650 switch (info_level) {
651 #if 0 /* FIXME GD */
652 case 0:
653 display_print_info_0(ctr.printers_0);
654 break;
655 case 1:
656 display_print_info_1(ctr.printers_1);
657 break;
658 case 2:
659 display_print_info_2(ctr.printers_2);
660 break;
661 case 3:
662 display_print_info_3(ctr.printers_3);
663 break;
664 #endif
665 case 7:
666 display_print_info7(&info.info7);
667 break;
668 default:
669 printf("unknown info level %d\n", info_level);
670 break;
672 done:
673 if (is_valid_policy_hnd(&pol))
674 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
676 return result;
679 /****************************************************************************
680 ****************************************************************************/
682 static void display_reg_value(REGISTRY_VALUE value)
684 char *text = NULL;
686 switch(value.type) {
687 case REG_DWORD:
688 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
689 *((uint32 *) value.data_p));
690 break;
691 case REG_SZ:
692 rpcstr_pull_talloc(talloc_tos(),
693 &text,
694 value.data_p,
695 value.size,
696 STR_TERMINATE);
697 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
698 break;
699 case REG_BINARY: {
700 char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
701 size_t i, len;
702 printf("%s: REG_BINARY:", value.valuename);
703 len = strlen(hex);
704 for (i=0; i<len; i++) {
705 if (hex[i] == '\0') {
706 break;
708 if (i%40 == 0) {
709 putchar('\n');
711 putchar(hex[i]);
713 TALLOC_FREE(hex);
714 putchar('\n');
715 break;
717 case REG_MULTI_SZ: {
718 uint32 i, num_values;
719 char **values;
721 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
722 value.size, &num_values,
723 &values))) {
724 d_printf("reg_pull_multi_sz failed\n");
725 break;
728 for (i=0; i<num_values; i++) {
729 d_printf("%s\n", values[i]);
731 TALLOC_FREE(values);
732 break;
734 default:
735 printf("%s: unknown type %d\n", value.valuename, value.type);
740 /****************************************************************************
741 ****************************************************************************/
743 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
744 TALLOC_CTX *mem_ctx,
745 int argc, const char **argv)
747 POLICY_HND pol;
748 WERROR result;
749 fstring printername;
750 const char *valuename;
751 REGISTRY_VALUE value;
753 if (argc != 3) {
754 printf("Usage: %s <printername> <valuename>\n", argv[0]);
755 printf("<printername> of . queries print server\n");
756 return WERR_OK;
758 valuename = argv[2];
760 /* Open a printer handle */
762 if (strncmp(argv[1], ".", sizeof(".")) == 0)
763 fstrcpy(printername, cli->srv_name_slash);
764 else
765 slprintf(printername, sizeof(printername)-1, "%s\\%s",
766 cli->srv_name_slash, argv[1]);
768 /* get a printer handle */
770 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
771 printername,
772 SEC_FLAG_MAXIMUM_ALLOWED,
773 &pol);
774 if (!W_ERROR_IS_OK(result))
775 goto done;
777 /* Get printer info */
779 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
781 if (!W_ERROR_IS_OK(result))
782 goto done;
784 /* Display printer data */
786 fstrcpy(value.valuename, valuename);
787 display_reg_value(value);
790 done:
791 if (is_valid_policy_hnd(&pol))
792 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
794 return result;
797 /****************************************************************************
798 ****************************************************************************/
800 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
801 TALLOC_CTX *mem_ctx,
802 int argc, const char **argv)
804 POLICY_HND pol;
805 WERROR result;
806 NTSTATUS status;
807 fstring printername;
808 const char *valuename, *keyname;
809 REGISTRY_VALUE value;
811 uint32_t type;
812 uint8_t *buffer = NULL;
813 uint32_t offered = 0;
814 uint32_t needed;
816 if (argc != 4) {
817 printf("Usage: %s <printername> <keyname> <valuename>\n",
818 argv[0]);
819 printf("<printername> of . queries print server\n");
820 return WERR_OK;
822 valuename = argv[3];
823 keyname = argv[2];
825 /* Open a printer handle */
827 if (strncmp(argv[1], ".", sizeof(".")) == 0)
828 fstrcpy(printername, cli->srv_name_slash);
829 else
830 slprintf(printername, sizeof(printername)-1, "%s\\%s",
831 cli->srv_name_slash, argv[1]);
833 /* get a printer handle */
835 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
836 printername,
837 SEC_FLAG_MAXIMUM_ALLOWED,
838 &pol);
839 if (!W_ERROR_IS_OK(result))
840 goto done;
842 /* Get printer info */
844 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
845 &pol,
846 keyname,
847 valuename,
848 &type,
849 buffer,
850 offered,
851 &needed,
852 &result);
853 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
854 offered = needed;
855 buffer = talloc_array(mem_ctx, uint8_t, needed);
856 status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
857 &pol,
858 keyname,
859 valuename,
860 &type,
861 buffer,
862 offered,
863 &needed,
864 &result);
867 if (!NT_STATUS_IS_OK(status)) {
868 goto done;
871 if (!W_ERROR_IS_OK(result)) {
872 goto done;
876 if (!W_ERROR_IS_OK(result))
877 goto done;
879 /* Display printer data */
881 fstrcpy(value.valuename, valuename);
882 value.type = type;
883 value.size = needed;
884 value.data_p = buffer;
886 display_reg_value(value);
888 done:
889 if (is_valid_policy_hnd(&pol))
890 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
892 return result;
895 /****************************************************************************
896 ****************************************************************************/
898 static void display_print_driver_1(DRIVER_INFO_1 *i1)
900 fstring name;
901 if (i1 == NULL)
902 return;
904 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
906 printf ("Printer Driver Info 1:\n");
907 printf ("\tDriver Name: [%s]\n\n", name);
909 return;
912 /****************************************************************************
913 ****************************************************************************/
915 static void display_print_driver_2(DRIVER_INFO_2 *i1)
917 fstring name;
918 fstring architecture;
919 fstring driverpath;
920 fstring datafile;
921 fstring configfile;
922 if (i1 == NULL)
923 return;
925 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
926 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
927 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
928 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
929 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
931 printf ("Printer Driver Info 2:\n");
932 printf ("\tVersion: [%x]\n", i1->version);
933 printf ("\tDriver Name: [%s]\n", name);
934 printf ("\tArchitecture: [%s]\n", architecture);
935 printf ("\tDriver Path: [%s]\n", driverpath);
936 printf ("\tDatafile: [%s]\n", datafile);
937 printf ("\tConfigfile: [%s]\n\n", configfile);
939 return;
942 /****************************************************************************
943 ****************************************************************************/
945 static void display_print_driver_3(DRIVER_INFO_3 *i1)
947 fstring name = "";
948 fstring architecture = "";
949 fstring driverpath = "";
950 fstring datafile = "";
951 fstring configfile = "";
952 fstring helpfile = "";
953 fstring dependentfiles = "";
954 fstring monitorname = "";
955 fstring defaultdatatype = "";
957 int length=0;
958 bool valid = True;
960 if (i1 == NULL)
961 return;
963 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
964 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
965 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
966 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
967 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
968 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
969 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
970 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
972 printf ("Printer Driver Info 3:\n");
973 printf ("\tVersion: [%x]\n", i1->version);
974 printf ("\tDriver Name: [%s]\n",name);
975 printf ("\tArchitecture: [%s]\n", architecture);
976 printf ("\tDriver Path: [%s]\n", driverpath);
977 printf ("\tDatafile: [%s]\n", datafile);
978 printf ("\tConfigfile: [%s]\n", configfile);
979 printf ("\tHelpfile: [%s]\n\n", helpfile);
981 while (valid)
983 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
985 length+=strlen(dependentfiles)+1;
987 if (strlen(dependentfiles) > 0)
989 printf ("\tDependentfiles: [%s]\n", dependentfiles);
991 else
993 valid = False;
997 printf ("\n");
999 printf ("\tMonitorname: [%s]\n", monitorname);
1000 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
1002 return;
1005 /****************************************************************************
1006 ****************************************************************************/
1008 static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1010 if (!r) {
1011 return;
1014 printf("Printer Driver Info 1:\n");
1015 printf("\tDriver Name: [%s]\n\n", r->driver_name);
1018 /****************************************************************************
1019 ****************************************************************************/
1021 static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1023 if (!r) {
1024 return;
1027 printf("Printer Driver Info 2:\n");
1028 printf("\tVersion: [%x]\n", r->version);
1029 printf("\tDriver Name: [%s]\n", r->driver_name);
1030 printf("\tArchitecture: [%s]\n", r->architecture);
1031 printf("\tDriver Path: [%s]\n", r->driver_path);
1032 printf("\tDatafile: [%s]\n", r->data_file);
1033 printf("\tConfigfile: [%s]\n\n", r->config_file);
1036 /****************************************************************************
1037 ****************************************************************************/
1039 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1041 int i;
1043 if (!r) {
1044 return;
1047 printf("Printer Driver Info 3:\n");
1048 printf("\tVersion: [%x]\n", r->version);
1049 printf("\tDriver Name: [%s]\n", r->driver_name);
1050 printf("\tArchitecture: [%s]\n", r->architecture);
1051 printf("\tDriver Path: [%s]\n", r->driver_path);
1052 printf("\tDatafile: [%s]\n", r->data_file);
1053 printf("\tConfigfile: [%s]\n\n", r->config_file);
1054 printf("\tHelpfile: [%s]\n\n", r->help_file);
1056 for (i=0; r->dependent_files[i] != NULL; i++) {
1057 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1060 printf("\n");
1062 printf("\tMonitorname: [%s]\n", r->monitor_name);
1063 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
1067 /****************************************************************************
1068 ****************************************************************************/
1070 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1071 TALLOC_CTX *mem_ctx,
1072 int argc, const char **argv)
1074 POLICY_HND pol;
1075 WERROR werror;
1076 uint32 info_level = 3;
1077 const char *printername;
1078 uint32 i;
1079 bool success = False;
1080 union spoolss_DriverInfo info;
1081 uint32_t server_major_version;
1082 uint32_t server_minor_version;
1084 if ((argc == 1) || (argc > 3))
1086 printf("Usage: %s <printername> [level]\n", argv[0]);
1087 return WERR_OK;
1090 /* get the arguments need to open the printer handle */
1092 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1094 if (argc == 3)
1095 info_level = atoi(argv[2]);
1097 /* Open a printer handle */
1099 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1100 printername,
1101 PRINTER_ACCESS_USE,
1102 &pol);
1103 if (!W_ERROR_IS_OK(werror)) {
1104 printf("Error opening printer handle for %s!\n", printername);
1105 return werror;
1108 /* loop through and print driver info level for each architecture */
1110 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1112 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1113 &pol,
1114 archi_table[i].long_archi,
1115 info_level,
1116 0, /* offered */
1117 archi_table[i].version,
1119 &info,
1120 &server_major_version,
1121 &server_minor_version);
1122 if (!W_ERROR_IS_OK(werror))
1123 continue;
1125 /* need at least one success */
1127 success = True;
1129 printf ("\n[%s]\n", archi_table[i].long_archi);
1131 switch (info_level) {
1132 case 1:
1133 display_print_driver1(&info.info1);
1134 break;
1135 case 2:
1136 display_print_driver2(&info.info2);
1137 break;
1138 case 3:
1139 display_print_driver3(&info.info3);
1140 break;
1141 default:
1142 printf("unknown info level %d\n", info_level);
1143 break;
1147 /* Cleanup */
1149 if (is_valid_policy_hnd(&pol))
1150 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1152 if ( success )
1153 werror = WERR_OK;
1155 return werror;
1158 /****************************************************************************
1159 ****************************************************************************/
1161 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1162 TALLOC_CTX *mem_ctx,
1163 int argc, const char **argv)
1165 WERROR werror = WERR_OK;
1166 uint32 info_level = 1;
1167 PRINTER_DRIVER_CTR ctr;
1168 uint32 i, j,
1169 returned;
1171 if (argc > 2) {
1172 printf("Usage: enumdrivers [level]\n");
1173 return WERR_OK;
1176 if (argc == 2)
1177 info_level = atoi(argv[1]);
1180 /* loop through and print driver info level for each architecture */
1181 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1182 /* check to see if we already asked for this architecture string */
1184 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1185 continue;
1187 werror = rpccli_spoolss_enumprinterdrivers(
1188 cli, mem_ctx, info_level,
1189 archi_table[i].long_archi, &returned, &ctr);
1191 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1192 printf ("Server does not support environment [%s]\n",
1193 archi_table[i].long_archi);
1194 werror = WERR_OK;
1195 continue;
1198 if (returned == 0)
1199 continue;
1201 if (!W_ERROR_IS_OK(werror)) {
1202 printf ("Error getting driver for environment [%s] - %d\n",
1203 archi_table[i].long_archi, W_ERROR_V(werror));
1204 continue;
1207 printf ("\n[%s]\n", archi_table[i].long_archi);
1208 switch (info_level)
1211 case 1:
1212 for (j=0; j < returned; j++) {
1213 display_print_driver_1 (&ctr.info1[j]);
1215 break;
1216 case 2:
1217 for (j=0; j < returned; j++) {
1218 display_print_driver_2 (&ctr.info2[j]);
1220 break;
1221 case 3:
1222 for (j=0; j < returned; j++) {
1223 display_print_driver_3 (&ctr.info3[j]);
1225 break;
1226 default:
1227 printf("unknown info level %d\n", info_level);
1228 return WERR_UNKNOWN_LEVEL;
1232 return werror;
1235 /****************************************************************************
1236 ****************************************************************************/
1238 static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1240 printf("\tDirectory Name:[%s]\n", r->directory_name);
1243 /****************************************************************************
1244 ****************************************************************************/
1246 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1247 TALLOC_CTX *mem_ctx,
1248 int argc, const char **argv)
1250 WERROR result;
1251 NTSTATUS status;
1252 const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1253 DATA_BLOB buffer;
1254 uint32_t offered;
1255 union spoolss_DriverDirectoryInfo info;
1256 uint32_t needed;
1258 if (argc > 2) {
1259 printf("Usage: %s [environment]\n", argv[0]);
1260 return WERR_OK;
1263 /* Get the arguments need to open the printer handle */
1265 if (argc == 2) {
1266 env = argv[1];
1269 /* Get the directory. Only use Info level 1 */
1271 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1272 cli->srv_name_slash,
1273 env,
1275 NULL, /* buffer */
1276 0, /* offered */
1277 NULL, /* info */
1278 &needed,
1279 &result);
1280 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1281 offered = needed;
1282 buffer = data_blob_talloc_zero(mem_ctx, needed);
1284 status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
1285 cli->srv_name_slash,
1286 env,
1288 &buffer,
1289 offered,
1290 &info,
1291 &needed,
1292 &result);
1295 if (W_ERROR_IS_OK(result)) {
1296 display_printdriverdir_1(&info.info1);
1299 return result;
1302 /****************************************************************************
1303 ****************************************************************************/
1305 static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1306 struct spoolss_AddDriverInfo3 *info,
1307 const char *arch)
1310 int i;
1312 for (i=0; archi_table[i].long_archi != NULL; i++)
1314 if (strcmp(arch, archi_table[i].short_archi) == 0)
1316 info->version = archi_table[i].version;
1317 info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1318 break;
1322 if (archi_table[i].long_archi == NULL)
1324 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1327 return;
1331 /**************************************************************************
1332 wrapper for strtok to get the next parameter from a delimited list.
1333 Needed to handle the empty parameter string denoted by "NULL"
1334 *************************************************************************/
1336 static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1337 const char *delim, const char **dest,
1338 char **saveptr)
1340 char *ptr;
1342 /* get the next token */
1343 ptr = strtok_r(str, delim, saveptr);
1345 /* a string of 'NULL' is used to represent an empty
1346 parameter because two consecutive delimiters
1347 will not return an empty string. See man strtok(3)
1348 for details */
1349 if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
1350 ptr = NULL;
1353 if (dest != NULL) {
1354 *dest = talloc_strdup(mem_ctx, ptr);
1357 return ptr;
1360 /********************************************************************************
1361 fill in the members of a spoolss_AddDriverInfo3 struct using a character
1362 string in the form of
1363 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1364 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1365 <Default Data Type>:<Comma Separated list of Files>
1366 *******************************************************************************/
1368 static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1369 char *args)
1371 char *str, *str2;
1372 int count = 0;
1373 char *saveptr = NULL;
1374 struct spoolss_StringArray *deps;
1375 const char **file_array = NULL;
1376 int i;
1378 /* fill in the UNISTR fields */
1379 str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1380 str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1381 str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1382 str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1383 str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1384 str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1385 str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1387 /* <Comma Separated List of Dependent Files> */
1388 /* save the beginning of the string */
1389 str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1390 str = str2;
1392 /* begin to strip out each filename */
1393 str = strtok_r(str, ",", &saveptr);
1395 /* no dependent files, we are done */
1396 if (!str) {
1397 return true;
1400 deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1401 if (!deps) {
1402 return false;
1405 while (str != NULL) {
1406 add_string_to_array(deps, str, &file_array, &count);
1407 str = strtok_r(NULL, ",", &saveptr);
1410 deps->string = talloc_zero_array(deps, const char *, count + 1);
1411 if (!deps->string) {
1412 return false;
1415 for (i=0; i < count; i++) {
1416 deps->string[i] = file_array[i];
1419 r->dependent_files = deps;
1421 return true;
1424 /****************************************************************************
1425 ****************************************************************************/
1427 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1428 TALLOC_CTX *mem_ctx,
1429 int argc, const char **argv)
1431 WERROR result;
1432 NTSTATUS status;
1433 uint32 level = 3;
1434 struct spoolss_AddDriverInfoCtr info_ctr;
1435 struct spoolss_AddDriverInfo3 info3;
1436 const char *arch;
1437 char *driver_args;
1439 /* parse the command arguments */
1440 if (argc != 3 && argc != 4)
1442 printf ("Usage: %s <Environment> \\\n", argv[0]);
1443 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1444 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1445 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1446 printf ("\t[version]\n");
1448 return WERR_OK;
1451 /* Fill in the spoolss_AddDriverInfo3 struct */
1452 ZERO_STRUCT(info3);
1454 arch = cmd_spoolss_get_short_archi(argv[1]);
1455 if (!arch) {
1456 printf ("Error Unknown architechture [%s]\n", argv[1]);
1457 return WERR_INVALID_PARAM;
1460 set_drv_info_3_env(mem_ctx, &info3, arch);
1462 driver_args = talloc_strdup( mem_ctx, argv[2] );
1463 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1465 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1466 return WERR_INVALID_PARAM;
1469 /* if printer driver version specified, override the default version
1470 * used by the architecture. This allows installation of Windows
1471 * 2000 (version 3) printer drivers. */
1472 if (argc == 4)
1474 info3.version = atoi(argv[3]);
1478 info_ctr.level = level;
1479 info_ctr.info.info3 = &info3;
1481 status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
1482 cli->srv_name_slash,
1483 &info_ctr,
1484 &result);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 return ntstatus_to_werror(status);
1488 if (W_ERROR_IS_OK(result)) {
1489 printf ("Printer Driver %s successfully installed.\n",
1490 info3.driver_name);
1493 return result;
1497 /****************************************************************************
1498 ****************************************************************************/
1500 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1501 TALLOC_CTX *mem_ctx,
1502 int argc, const char **argv)
1504 WERROR result;
1505 struct spoolss_SetPrinterInfoCtr info_ctr;
1506 struct spoolss_SetPrinterInfo2 info2;
1508 /* parse the command arguments */
1509 if (argc != 5)
1511 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1512 return WERR_OK;
1515 /* Fill in the DRIVER_INFO_2 struct */
1516 ZERO_STRUCT(info2);
1518 info2.printername = argv[1];
1519 info2.drivername = argv[3];
1520 info2.sharename = argv[2];
1521 info2.portname = argv[4];
1522 info2.comment = "Created by rpcclient";
1523 info2.printprocessor = "winprint";
1524 info2.datatype = "RAW";
1525 info2.devmode = NULL;
1526 info2.secdesc = NULL;
1527 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1528 info2.priority = 0;
1529 info2.defaultpriority = 0;
1530 info2.starttime = 0;
1531 info2.untiltime = 0;
1533 /* These three fields must not be used by AddPrinter()
1534 as defined in the MS Platform SDK documentation..
1535 --jerry
1536 info2.status = 0;
1537 info2.cjobs = 0;
1538 info2.averageppm = 0;
1541 info_ctr.level = 2;
1542 info_ctr.info.info2 = &info2;
1544 result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1545 &info_ctr);
1546 if (W_ERROR_IS_OK(result))
1547 printf ("Printer %s successfully installed.\n", argv[1]);
1549 return result;
1552 /****************************************************************************
1553 ****************************************************************************/
1555 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1556 TALLOC_CTX *mem_ctx,
1557 int argc, const char **argv)
1559 POLICY_HND pol;
1560 WERROR result;
1561 NTSTATUS status;
1562 uint32 level = 2;
1563 const char *printername;
1564 union spoolss_PrinterInfo info;
1565 struct spoolss_SetPrinterInfoCtr info_ctr;
1566 struct spoolss_DevmodeContainer devmode_ctr;
1567 struct sec_desc_buf secdesc_ctr;
1569 ZERO_STRUCT(devmode_ctr);
1570 ZERO_STRUCT(secdesc_ctr);
1572 /* parse the command arguments */
1573 if (argc != 3)
1575 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1576 return WERR_OK;
1579 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1581 /* Get a printer handle */
1583 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1584 printername,
1585 PRINTER_ALL_ACCESS,
1586 &pol);
1587 if (!W_ERROR_IS_OK(result))
1588 goto done;
1590 /* Get printer info */
1592 result = rpccli_spoolss_getprinter(cli, mem_ctx,
1593 &pol,
1594 level,
1596 &info);
1597 if (!W_ERROR_IS_OK(result)) {
1598 printf ("Unable to retrieve printer information!\n");
1599 goto done;
1602 /* Set the printer driver */
1604 info.info2.drivername = argv[2];
1605 info.info2.devmode = NULL;
1606 info.info2.secdesc = NULL;
1608 info_ctr.level = 2;
1609 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
1611 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
1612 &pol,
1613 &info_ctr,
1614 &devmode_ctr,
1615 &secdesc_ctr,
1616 0, /* command */
1617 &result);
1618 if (!W_ERROR_IS_OK(result)) {
1619 printf("SetPrinter call failed!\n");
1620 goto done;;
1623 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1625 done:
1626 /* Cleanup */
1628 if (is_valid_policy_hnd(&pol))
1629 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
1631 return result;
1635 /****************************************************************************
1636 ****************************************************************************/
1638 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1639 TALLOC_CTX *mem_ctx,
1640 int argc, const char **argv)
1642 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1643 NTSTATUS status;
1645 int i;
1646 int vers = -1;
1648 const char *arch = NULL;
1649 uint32_t delete_flags = 0;
1651 /* parse the command arguments */
1652 if (argc < 2 || argc > 4) {
1653 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1654 return WERR_OK;
1657 if (argc >= 3)
1658 arch = argv[2];
1659 if (argc == 4)
1660 vers = atoi (argv[3]);
1662 if (vers >= 0) {
1663 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
1666 /* delete the driver for all architectures */
1667 for (i=0; archi_table[i].long_archi; i++) {
1669 if (arch && !strequal( archi_table[i].long_archi, arch))
1670 continue;
1672 if (vers >= 0 && archi_table[i].version != vers)
1673 continue;
1675 /* make the call to remove the driver */
1676 status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
1677 cli->srv_name_slash,
1678 archi_table[i].long_archi,
1679 argv[1],
1680 delete_flags,
1681 archi_table[i].version,
1682 &result);
1684 if ( !W_ERROR_IS_OK(result) )
1686 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1687 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1688 argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
1691 else
1693 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1694 archi_table[i].long_archi, archi_table[i].version);
1695 ret = WERR_OK;
1699 return ret;
1703 /****************************************************************************
1704 ****************************************************************************/
1706 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1707 TALLOC_CTX *mem_ctx,
1708 int argc, const char **argv)
1710 WERROR result = WERR_OK;
1711 NTSTATUS status;
1712 int i;
1714 /* parse the command arguments */
1715 if (argc != 2) {
1716 printf ("Usage: %s <driver>\n", argv[0]);
1717 return WERR_OK;
1720 /* delete the driver for all architectures */
1721 for (i=0; archi_table[i].long_archi; i++) {
1722 /* make the call to remove the driver */
1723 status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
1724 cli->srv_name_slash,
1725 archi_table[i].long_archi,
1726 argv[1],
1727 &result);
1728 if (!NT_STATUS_IS_OK(status)) {
1729 return result;
1731 if ( !W_ERROR_IS_OK(result) ) {
1732 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1733 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1734 argv[1], archi_table[i].long_archi,
1735 W_ERROR_V(result));
1737 } else {
1738 printf ("Driver %s removed for arch [%s].\n", argv[1],
1739 archi_table[i].long_archi);
1743 return result;
1746 /****************************************************************************
1747 ****************************************************************************/
1749 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1750 TALLOC_CTX *mem_ctx,
1751 int argc, const char **argv)
1753 WERROR result;
1754 NTSTATUS status;
1755 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
1756 DATA_BLOB buffer;
1757 uint32_t offered;
1758 union spoolss_PrintProcessorDirectoryInfo info;
1759 uint32_t needed;
1761 /* parse the command arguments */
1762 if (argc > 2) {
1763 printf ("Usage: %s [environment]\n", argv[0]);
1764 return WERR_OK;
1767 if (argc == 2) {
1768 environment = argv[1];
1771 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1772 cli->srv_name_slash,
1773 environment,
1775 NULL, /* buffer */
1776 0, /* offered */
1777 NULL, /* info */
1778 &needed,
1779 &result);
1780 if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1781 offered = needed;
1782 buffer = data_blob_talloc_zero(mem_ctx, needed);
1784 status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
1785 cli->srv_name_slash,
1786 environment,
1788 &buffer,
1789 offered,
1790 &info,
1791 &needed,
1792 &result);
1795 if (W_ERROR_IS_OK(result)) {
1796 printf("%s\n", info.info1.directory_name);
1799 return result;
1802 /****************************************************************************
1803 ****************************************************************************/
1805 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1806 int argc, const char **argv)
1808 POLICY_HND handle;
1809 WERROR werror;
1810 NTSTATUS status;
1811 const char *printername;
1812 union spoolss_AddFormInfo info;
1813 struct spoolss_AddFormInfo1 info1;
1814 struct spoolss_AddFormInfo2 info2;
1815 uint32_t level = 1;
1817 /* Parse the command arguments */
1819 if (argc < 3 || argc > 5) {
1820 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
1821 return WERR_OK;
1824 /* Get a printer handle */
1826 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1828 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1829 printername,
1830 PRINTER_ALL_ACCESS,
1831 &handle);
1832 if (!W_ERROR_IS_OK(werror))
1833 goto done;
1835 /* Dummy up some values for the form data */
1837 if (argc == 4) {
1838 level = atoi(argv[3]);
1841 switch (level) {
1842 case 1:
1843 info1.flags = SPOOLSS_FORM_USER;
1844 info1.form_name = argv[2];
1845 info1.size.width = 100;
1846 info1.size.height = 100;
1847 info1.area.left = 0;
1848 info1.area.top = 10;
1849 info1.area.right = 20;
1850 info1.area.bottom = 30;
1852 info.info1 = &info1;
1854 break;
1855 case 2:
1856 info2.flags = SPOOLSS_FORM_USER;
1857 info2.form_name = argv[2];
1858 info2.size.width = 100;
1859 info2.size.height = 100;
1860 info2.area.left = 0;
1861 info2.area.top = 10;
1862 info2.area.right = 20;
1863 info2.area.bottom = 30;
1864 info2.keyword = argv[2];
1865 info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
1866 info2.mui_dll = NULL;
1867 info2.ressource_id = 0;
1868 info2.display_name = argv[2];
1869 info2.lang_id = 0;
1871 info.info2 = &info2;
1873 break;
1876 /* Add the form */
1879 status = rpccli_spoolss_AddForm(cli, mem_ctx,
1880 &handle,
1881 level,
1882 info,
1883 &werror);
1885 done:
1886 if (is_valid_policy_hnd(&handle))
1887 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1889 return werror;
1892 /****************************************************************************
1893 ****************************************************************************/
1895 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1896 int argc, const char **argv)
1898 POLICY_HND handle;
1899 WERROR werror;
1900 NTSTATUS status;
1901 const char *printername;
1902 union spoolss_AddFormInfo info;
1903 struct spoolss_AddFormInfo1 info1;
1905 /* Parse the command arguments */
1907 if (argc != 3) {
1908 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1909 return WERR_OK;
1912 /* Get a printer handle */
1914 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1916 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1917 printername,
1918 SEC_FLAG_MAXIMUM_ALLOWED,
1919 &handle);
1920 if (!W_ERROR_IS_OK(werror))
1921 goto done;
1923 /* Dummy up some values for the form data */
1925 info1.flags = SPOOLSS_FORM_PRINTER;
1926 info1.size.width = 100;
1927 info1.size.height = 100;
1928 info1.area.left = 0;
1929 info1.area.top = 1000;
1930 info1.area.right = 2000;
1931 info1.area.bottom = 3000;
1932 info1.form_name = argv[2];
1934 info.info1 = &info1;
1936 /* Set the form */
1938 status = rpccli_spoolss_SetForm(cli, mem_ctx,
1939 &handle,
1940 argv[2],
1942 info,
1943 &werror);
1945 done:
1946 if (is_valid_policy_hnd(&handle))
1947 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1949 return werror;
1952 /****************************************************************************
1953 ****************************************************************************/
1955 static const char *get_form_flag(int form_flag)
1957 switch (form_flag) {
1958 case SPOOLSS_FORM_USER:
1959 return "FORM_USER";
1960 case SPOOLSS_FORM_BUILTIN:
1961 return "FORM_BUILTIN";
1962 case SPOOLSS_FORM_PRINTER:
1963 return "FORM_PRINTER";
1964 default:
1965 return "unknown";
1969 /****************************************************************************
1970 ****************************************************************************/
1972 static void display_form_info1(struct spoolss_FormInfo1 *r)
1974 printf("%s\n" \
1975 "\tflag: %s (%d)\n" \
1976 "\twidth: %d, length: %d\n" \
1977 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1978 r->form_name, get_form_flag(r->flags), r->flags,
1979 r->size.width, r->size.height,
1980 r->area.left, r->area.right,
1981 r->area.top, r->area.bottom);
1984 /****************************************************************************
1985 ****************************************************************************/
1987 static void display_form_info2(struct spoolss_FormInfo2 *r)
1989 printf("%s\n" \
1990 "\tflag: %s (%d)\n" \
1991 "\twidth: %d, length: %d\n" \
1992 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
1993 r->form_name, get_form_flag(r->flags), r->flags,
1994 r->size.width, r->size.height,
1995 r->area.left, r->area.right,
1996 r->area.top, r->area.bottom);
1997 printf("\tkeyword: %s\n", r->keyword);
1998 printf("\tstring_type: 0x%08x\n", r->string_type);
1999 printf("\tmui_dll: %s\n", r->mui_dll);
2000 printf("\tressource_id: 0x%08x\n", r->ressource_id);
2001 printf("\tdisplay_name: %s\n", r->display_name);
2002 printf("\tlang_id: %d\n", r->lang_id);
2003 printf("\n");
2006 /****************************************************************************
2007 ****************************************************************************/
2009 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2010 int argc, const char **argv)
2012 POLICY_HND handle;
2013 WERROR werror;
2014 NTSTATUS status;
2015 const char *printername;
2016 DATA_BLOB buffer;
2017 uint32_t offered = 0;
2018 union spoolss_FormInfo info;
2019 uint32_t needed;
2020 uint32_t level = 1;
2022 /* Parse the command arguments */
2024 if (argc < 3 || argc > 5) {
2025 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2026 return WERR_OK;
2029 /* Get a printer handle */
2031 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2033 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2034 printername,
2035 SEC_FLAG_MAXIMUM_ALLOWED,
2036 &handle);
2037 if (!W_ERROR_IS_OK(werror))
2038 goto done;
2040 if (argc == 4) {
2041 level = atoi(argv[3]);
2044 /* Get the form */
2046 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2047 &handle,
2048 argv[2],
2049 level,
2050 NULL,
2051 offered,
2052 &info,
2053 &needed,
2054 &werror);
2055 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2056 buffer = data_blob_talloc_zero(mem_ctx, needed);
2057 offered = needed;
2058 status = rpccli_spoolss_GetForm(cli, mem_ctx,
2059 &handle,
2060 argv[2],
2061 level,
2062 &buffer,
2063 offered,
2064 &info,
2065 &needed,
2066 &werror);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 return werror;
2073 switch (level) {
2074 case 1:
2075 display_form_info1(&info.info1);
2076 break;
2077 case 2:
2078 display_form_info2(&info.info2);
2079 break;
2082 done:
2083 if (is_valid_policy_hnd(&handle))
2084 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2086 return werror;
2089 /****************************************************************************
2090 ****************************************************************************/
2092 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2093 TALLOC_CTX *mem_ctx, int argc,
2094 const char **argv)
2096 POLICY_HND handle;
2097 WERROR werror;
2098 NTSTATUS status;
2099 const char *printername;
2101 /* Parse the command arguments */
2103 if (argc != 3) {
2104 printf ("Usage: %s <printer> <formname>\n", argv[0]);
2105 return WERR_OK;
2108 /* Get a printer handle */
2110 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2112 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2113 printername,
2114 SEC_FLAG_MAXIMUM_ALLOWED,
2115 &handle);
2116 if (!W_ERROR_IS_OK(werror))
2117 goto done;
2119 /* Delete the form */
2121 status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
2122 &handle,
2123 argv[2],
2124 &werror);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 return ntstatus_to_werror(status);
2129 done:
2130 if (is_valid_policy_hnd(&handle))
2131 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2133 return werror;
2136 /****************************************************************************
2137 ****************************************************************************/
2139 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2140 TALLOC_CTX *mem_ctx, int argc,
2141 const char **argv)
2143 POLICY_HND handle;
2144 WERROR werror;
2145 const char *printername;
2146 uint32 num_forms, level = 1, i;
2147 union spoolss_FormInfo *forms;
2149 /* Parse the command arguments */
2151 if (argc < 2 || argc > 4) {
2152 printf ("Usage: %s <printer> [level]\n", argv[0]);
2153 return WERR_OK;
2156 /* Get a printer handle */
2158 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2160 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2161 printername,
2162 SEC_FLAG_MAXIMUM_ALLOWED,
2163 &handle);
2164 if (!W_ERROR_IS_OK(werror))
2165 goto done;
2167 if (argc == 3) {
2168 level = atoi(argv[2]);
2171 /* Enumerate forms */
2173 werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2174 &handle,
2175 level,
2177 &num_forms,
2178 &forms);
2180 if (!W_ERROR_IS_OK(werror))
2181 goto done;
2183 /* Display output */
2185 for (i = 0; i < num_forms; i++) {
2186 switch (level) {
2187 case 1:
2188 display_form_info1(&forms[i].info1);
2189 break;
2190 case 2:
2191 display_form_info2(&forms[i].info2);
2192 break;
2196 done:
2197 if (is_valid_policy_hnd(&handle))
2198 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
2200 return werror;
2203 /****************************************************************************
2204 ****************************************************************************/
2206 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2207 TALLOC_CTX *mem_ctx,
2208 int argc, const char **argv)
2210 WERROR result;
2211 const char *printername;
2212 POLICY_HND pol;
2213 union spoolss_PrinterInfo info;
2214 REGISTRY_VALUE value;
2215 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2217 /* parse the command arguments */
2218 if (argc < 5) {
2219 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2220 " <value> <data>\n",
2221 argv[0]);
2222 result = WERR_INVALID_PARAM;
2223 goto done;
2226 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2228 value.type = REG_NONE;
2230 if (strequal(argv[2], "string")) {
2231 value.type = REG_SZ;
2234 if (strequal(argv[2], "binary")) {
2235 value.type = REG_BINARY;
2238 if (strequal(argv[2], "dword")) {
2239 value.type = REG_DWORD;
2242 if (strequal(argv[2], "multistring")) {
2243 value.type = REG_MULTI_SZ;
2246 if (value.type == REG_NONE) {
2247 printf("Unknown data type: %s\n", argv[2]);
2248 result = WERR_INVALID_PARAM;
2249 goto done;
2252 /* get a printer handle */
2254 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2255 printername,
2256 SEC_FLAG_MAXIMUM_ALLOWED,
2257 &pol);
2258 if (!W_ERROR_IS_OK(result))
2259 goto done;
2261 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2262 &pol,
2265 &info);
2266 if (!W_ERROR_IS_OK(result))
2267 goto done;
2269 printf("%s\n", current_timestring(tmp_ctx, True));
2270 printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2272 /* Set the printer data */
2274 fstrcpy(value.valuename, argv[3]);
2276 switch (value.type) {
2277 case REG_SZ: {
2278 UNISTR2 data;
2279 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2280 value.size = data.uni_str_len * 2;
2281 if (value.size) {
2282 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2283 value.size);
2284 } else {
2285 value.data_p = NULL;
2287 break;
2289 case REG_DWORD: {
2290 uint32 data = strtoul(argv[4], NULL, 10);
2291 value.size = sizeof(data);
2292 if (sizeof(data)) {
2293 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2294 sizeof(data));
2295 } else {
2296 value.data_p = NULL;
2298 break;
2300 case REG_BINARY: {
2301 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2302 value.data_p = data.data;
2303 value.size = data.length;
2304 break;
2306 case REG_MULTI_SZ: {
2307 int i;
2308 size_t len = 0;
2309 char *p;
2311 for (i=4; i<argc; i++) {
2312 if (strcmp(argv[i], "NULL") == 0) {
2313 argv[i] = "";
2315 len += strlen(argv[i])+1;
2318 value.size = len*2;
2319 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2320 if (value.data_p == NULL) {
2321 result = WERR_NOMEM;
2322 goto done;
2325 p = (char *)value.data_p;
2326 len = value.size;
2327 for (i=4; i<argc; i++) {
2328 size_t l = (strlen(argv[i])+1)*2;
2329 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2330 p += l;
2331 len -= l;
2333 SMB_ASSERT(len == 0);
2334 break;
2336 default:
2337 printf("Unknown data type: %s\n", argv[2]);
2338 result = WERR_INVALID_PARAM;
2339 goto done;
2342 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2344 if (!W_ERROR_IS_OK(result)) {
2345 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2346 goto done;
2348 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2350 result = rpccli_spoolss_getprinter(cli, mem_ctx,
2351 &pol,
2354 &info);
2355 if (!W_ERROR_IS_OK(result))
2356 goto done;
2358 printf("%s\n", current_timestring(tmp_ctx, True));
2359 printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2361 done:
2362 /* cleanup */
2363 TALLOC_FREE(tmp_ctx);
2364 if (is_valid_policy_hnd(&pol))
2365 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
2367 return result;
2370 /****************************************************************************
2371 ****************************************************************************/
2373 static void display_job_info_1(JOB_INFO_1 *job)
2375 fstring username = "", document = "", text_status = "";
2377 rpcstr_pull(username, job->username.buffer,
2378 sizeof(username), -1, STR_TERMINATE);
2380 rpcstr_pull(document, job->document.buffer,
2381 sizeof(document), -1, STR_TERMINATE);
2383 rpcstr_pull(text_status, job->text_status.buffer,
2384 sizeof(text_status), -1, STR_TERMINATE);
2386 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2387 username, document, text_status, job->pagesprinted,
2388 job->totalpages);
2391 /****************************************************************************
2392 ****************************************************************************/
2394 static void display_job_info_2(JOB_INFO_2 *job)
2396 fstring username = "", document = "", text_status = "";
2398 rpcstr_pull(username, job->username.buffer,
2399 sizeof(username), -1, STR_TERMINATE);
2401 rpcstr_pull(document, job->document.buffer,
2402 sizeof(document), -1, STR_TERMINATE);
2404 rpcstr_pull(text_status, job->text_status.buffer,
2405 sizeof(text_status), -1, STR_TERMINATE);
2407 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2408 username, document, text_status, job->pagesprinted,
2409 job->totalpages, job->size);
2412 /****************************************************************************
2413 ****************************************************************************/
2415 static void display_job_info1(struct spoolss_JobInfo1 *r)
2417 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2418 r->user_name, r->document_name, r->text_status, r->pages_printed,
2419 r->total_pages);
2422 /****************************************************************************
2423 ****************************************************************************/
2425 static void display_job_info2(struct spoolss_JobInfo2 *r)
2427 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2428 r->position, r->job_id,
2429 r->user_name, r->document_name, r->text_status, r->pages_printed,
2430 r->total_pages, r->size);
2433 /****************************************************************************
2434 ****************************************************************************/
2436 static void display_job_info3(struct spoolss_JobInfo3 *r)
2438 printf("jobid[%d], next_jobid[%d]\n",
2439 r->job_id, r->next_job_id);
2442 /****************************************************************************
2443 ****************************************************************************/
2445 static void display_job_info4(struct spoolss_JobInfo4 *r)
2447 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2448 r->position, r->job_id,
2449 r->user_name, r->document_name, r->text_status, r->pages_printed,
2450 r->total_pages, r->size, r->size_high);
2453 /****************************************************************************
2454 ****************************************************************************/
2456 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2457 TALLOC_CTX *mem_ctx, int argc,
2458 const char **argv)
2460 WERROR result;
2461 uint32 level = 1, num_jobs, i;
2462 const char *printername;
2463 POLICY_HND hnd;
2464 JOB_INFO_CTR ctr;
2466 if (argc < 2 || argc > 3) {
2467 printf("Usage: %s printername [level]\n", argv[0]);
2468 return WERR_OK;
2471 if (argc == 3)
2472 level = atoi(argv[2]);
2474 /* Open printer handle */
2476 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2478 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2479 printername,
2480 SEC_FLAG_MAXIMUM_ALLOWED,
2481 &hnd);
2482 if (!W_ERROR_IS_OK(result))
2483 goto done;
2485 /* Enumerate ports */
2487 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2488 &num_jobs, &ctr);
2490 if (!W_ERROR_IS_OK(result))
2491 goto done;
2493 for (i = 0; i < num_jobs; i++) {
2494 switch(level) {
2495 case 1:
2496 display_job_info_1(&ctr.job.job_info_1[i]);
2497 break;
2498 case 2:
2499 display_job_info_2(&ctr.job.job_info_2[i]);
2500 break;
2501 default:
2502 d_printf("unknown info level %d\n", level);
2503 break;
2507 done:
2508 if (is_valid_policy_hnd(&hnd))
2509 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2511 return result;
2514 /****************************************************************************
2515 ****************************************************************************/
2517 static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2518 TALLOC_CTX *mem_ctx, int argc,
2519 const char **argv)
2521 WERROR result;
2522 const char *printername;
2523 struct policy_handle hnd;
2524 uint32_t job_id;
2525 uint32_t level = 1;
2526 union spoolss_JobInfo info;
2528 if (argc < 3 || argc > 4) {
2529 printf("Usage: %s printername job_id [level]\n", argv[0]);
2530 return WERR_OK;
2533 job_id = atoi(argv[2]);
2535 if (argc == 4) {
2536 level = atoi(argv[3]);
2539 /* Open printer handle */
2541 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2543 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2544 printername,
2545 SEC_FLAG_MAXIMUM_ALLOWED,
2546 &hnd);
2547 if (!W_ERROR_IS_OK(result)) {
2548 goto done;
2551 /* Enumerate ports */
2553 result = rpccli_spoolss_getjob(cli, mem_ctx,
2554 &hnd,
2555 job_id,
2556 level,
2558 &info);
2560 if (!W_ERROR_IS_OK(result)) {
2561 goto done;
2564 switch (level) {
2565 case 1:
2566 display_job_info1(&info.info1);
2567 break;
2568 case 2:
2569 display_job_info2(&info.info2);
2570 break;
2571 case 3:
2572 display_job_info3(&info.info3);
2573 break;
2574 case 4:
2575 display_job_info4(&info.info4);
2576 break;
2577 default:
2578 d_printf("unknown info level %d\n", level);
2579 break;
2582 done:
2583 if (is_valid_policy_hnd(&hnd)) {
2584 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2587 return result;
2591 /****************************************************************************
2592 ****************************************************************************/
2594 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2595 TALLOC_CTX *mem_ctx, int argc,
2596 const char **argv)
2598 WERROR result;
2599 uint32 i=0, val_needed, data_needed;
2600 const char *printername;
2601 POLICY_HND hnd;
2603 if (argc != 2) {
2604 printf("Usage: %s printername\n", argv[0]);
2605 return WERR_OK;
2608 /* Open printer handle */
2610 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2612 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2613 printername,
2614 SEC_FLAG_MAXIMUM_ALLOWED,
2615 &hnd);
2616 if (!W_ERROR_IS_OK(result))
2617 goto done;
2619 /* Enumerate data */
2621 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2622 &val_needed, &data_needed,
2623 NULL);
2624 while (W_ERROR_IS_OK(result)) {
2625 REGISTRY_VALUE value;
2626 result = rpccli_spoolss_enumprinterdata(
2627 cli, mem_ctx, &hnd, i++, val_needed,
2628 data_needed, 0, 0, &value);
2629 if (W_ERROR_IS_OK(result))
2630 display_reg_value(value);
2632 if (W_ERROR_V(result) == ERRnomoreitems)
2633 result = W_ERROR(ERRsuccess);
2635 done:
2636 if (is_valid_policy_hnd(&hnd))
2637 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2639 return result;
2642 /****************************************************************************
2643 ****************************************************************************/
2645 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2646 TALLOC_CTX *mem_ctx, int argc,
2647 const char **argv)
2649 WERROR result;
2650 uint32 i;
2651 const char *printername;
2652 const char *keyname = NULL;
2653 POLICY_HND hnd;
2654 REGVAL_CTR *ctr = NULL;
2656 if (argc != 3) {
2657 printf("Usage: %s printername <keyname>\n", argv[0]);
2658 return WERR_OK;
2661 keyname = argv[2];
2663 /* Open printer handle */
2665 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2667 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2668 printername,
2669 SEC_FLAG_MAXIMUM_ALLOWED,
2670 &hnd);
2671 if (!W_ERROR_IS_OK(result))
2672 goto done;
2674 /* Enumerate subkeys */
2676 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2677 return WERR_NOMEM;
2679 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2681 if (!W_ERROR_IS_OK(result))
2682 goto done;
2684 for (i=0; i < ctr->num_values; i++) {
2685 display_reg_value(*(ctr->values[i]));
2688 TALLOC_FREE( ctr );
2690 done:
2691 if (is_valid_policy_hnd(&hnd))
2692 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2694 return result;
2697 /****************************************************************************
2698 ****************************************************************************/
2700 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2701 TALLOC_CTX *mem_ctx, int argc,
2702 const char **argv)
2704 WERROR result;
2705 const char *printername;
2706 const char *keyname = NULL;
2707 POLICY_HND hnd;
2708 uint16 *keylist = NULL, *curkey;
2710 if (argc < 2 || argc > 3) {
2711 printf("Usage: %s printername [keyname]\n", argv[0]);
2712 return WERR_OK;
2715 if (argc == 3)
2716 keyname = argv[2];
2717 else
2718 keyname = "";
2720 /* Open printer handle */
2722 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2724 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2725 printername,
2726 SEC_FLAG_MAXIMUM_ALLOWED,
2727 &hnd);
2728 if (!W_ERROR_IS_OK(result))
2729 goto done;
2731 /* Enumerate subkeys */
2733 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2735 if (!W_ERROR_IS_OK(result))
2736 goto done;
2738 curkey = keylist;
2739 while (*curkey != 0) {
2740 char *subkey = NULL;
2741 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2742 STR_TERMINATE);
2743 if (!subkey) {
2744 break;
2746 printf("%s\n", subkey);
2747 curkey += strlen(subkey) + 1;
2750 done:
2752 SAFE_FREE(keylist);
2754 if (is_valid_policy_hnd(&hnd))
2755 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2757 return result;
2760 /****************************************************************************
2761 ****************************************************************************/
2763 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2764 TALLOC_CTX *mem_ctx, int argc,
2765 const char **argv)
2767 const char *printername;
2768 const char *clientname;
2769 POLICY_HND hnd;
2770 WERROR result;
2771 NTSTATUS status;
2772 struct spoolss_NotifyOption option;
2774 if (argc != 2) {
2775 printf("Usage: %s printername\n", argv[0]);
2776 result = WERR_OK;
2777 goto done;
2780 /* Open printer */
2782 RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2784 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2785 printername,
2786 SEC_FLAG_MAXIMUM_ALLOWED,
2787 &hnd);
2788 if (!W_ERROR_IS_OK(result)) {
2789 printf("Error opening %s\n", argv[1]);
2790 goto done;
2793 /* Create spool options */
2795 option.version = 2;
2796 option.count = 2;
2798 option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
2799 if (option.types == NULL) {
2800 result = WERR_NOMEM;
2801 goto done;
2804 option.types[0].type = PRINTER_NOTIFY_TYPE;
2805 option.types[0].count = 1;
2806 option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2807 if (option.types[0].fields == NULL) {
2808 result = WERR_NOMEM;
2809 goto done;
2811 option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2813 option.types[1].type = JOB_NOTIFY_TYPE;
2814 option.types[1].count = 1;
2815 option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
2816 if (option.types[1].fields == NULL) {
2817 result = WERR_NOMEM;
2818 goto done;
2820 option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2822 clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
2823 if (!clientname) {
2824 result = WERR_NOMEM;
2825 goto done;
2828 /* Send rffpcnex */
2830 status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
2831 &hnd,
2834 clientname,
2835 123,
2836 &option,
2837 &result);
2838 if (!W_ERROR_IS_OK(result)) {
2839 printf("Error rffpcnex %s\n", argv[1]);
2840 goto done;
2843 done:
2844 if (is_valid_policy_hnd(&hnd))
2845 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
2847 return result;
2850 /****************************************************************************
2851 ****************************************************************************/
2853 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2854 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2856 union spoolss_PrinterInfo info1, info2;
2857 WERROR werror;
2858 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2860 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2861 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2862 hnd1,
2865 &info1);
2866 if ( !W_ERROR_IS_OK(werror) ) {
2867 printf("failed (%s)\n", win_errstr(werror));
2868 talloc_destroy(mem_ctx);
2869 return False;
2871 printf("ok\n");
2873 printf("Retrieving printer properties for %s...", cli2->desthost);
2874 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2875 hnd2,
2878 &info2);
2879 if ( !W_ERROR_IS_OK(werror) ) {
2880 printf("failed (%s)\n", win_errstr(werror));
2881 talloc_destroy(mem_ctx);
2882 return False;
2884 printf("ok\n");
2886 talloc_destroy(mem_ctx);
2888 return True;
2891 /****************************************************************************
2892 ****************************************************************************/
2894 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2895 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2897 union spoolss_PrinterInfo info1, info2;
2898 WERROR werror;
2899 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2900 SEC_DESC *sd1, *sd2;
2901 bool result = True;
2904 printf("Retrieving printer security for %s...", cli1->desthost);
2905 werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
2906 hnd1,
2909 &info1);
2910 if ( !W_ERROR_IS_OK(werror) ) {
2911 printf("failed (%s)\n", win_errstr(werror));
2912 result = False;
2913 goto done;
2915 printf("ok\n");
2917 printf("Retrieving printer security for %s...", cli2->desthost);
2918 werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
2919 hnd2,
2922 &info2);
2923 if ( !W_ERROR_IS_OK(werror) ) {
2924 printf("failed (%s)\n", win_errstr(werror));
2925 result = False;
2926 goto done;
2928 printf("ok\n");
2931 printf("++ ");
2933 sd1 = info1.info3.secdesc;
2934 sd2 = info2.info3.secdesc;
2936 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2937 printf("NULL secdesc!\n");
2938 result = False;
2939 goto done;
2942 if (!sec_desc_equal( sd1, sd2 ) ) {
2943 printf("Security Descriptors *not* equal!\n");
2944 result = False;
2945 goto done;
2948 printf("Security descriptors match\n");
2950 done:
2951 talloc_destroy(mem_ctx);
2952 return result;
2956 /****************************************************************************
2957 ****************************************************************************/
2959 extern struct user_auth_info *rpcclient_auth_info;
2961 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2962 TALLOC_CTX *mem_ctx, int argc,
2963 const char **argv)
2965 const char *printername;
2966 char *printername_path = NULL;
2967 struct cli_state *cli_server2 = NULL;
2968 struct rpc_pipe_client *cli2 = NULL;
2969 POLICY_HND hPrinter1, hPrinter2;
2970 NTSTATUS nt_status;
2971 WERROR werror;
2973 if ( argc != 3 ) {
2974 printf("Usage: %s <printer> <server>\n", argv[0]);
2975 return WERR_OK;
2978 printername = argv[1];
2980 /* first get the connection to the remote server */
2982 nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
2983 NULL, 0,
2984 "IPC$", "IPC",
2985 get_cmdline_auth_info_username(rpcclient_auth_info),
2986 lp_workgroup(),
2987 get_cmdline_auth_info_password(rpcclient_auth_info),
2988 get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2989 get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
2991 if ( !NT_STATUS_IS_OK(nt_status) )
2992 return WERR_GENERAL_FAILURE;
2994 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2995 &cli2);
2996 if (!NT_STATUS_IS_OK(nt_status)) {
2997 printf("failed to open spoolss pipe on server %s (%s)\n",
2998 argv[2], nt_errstr(nt_status));
2999 return WERR_GENERAL_FAILURE;
3002 /* now open up both printers */
3004 RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3006 printf("Opening %s...", printername_path);
3008 werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3009 printername_path,
3010 PRINTER_ALL_ACCESS,
3011 &hPrinter1);
3012 if ( !W_ERROR_IS_OK(werror) ) {
3013 printf("failed (%s)\n", win_errstr(werror));
3014 goto done;
3016 printf("ok\n");
3018 RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3020 printf("Opening %s...", printername_path);
3021 werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3022 printername_path,
3023 PRINTER_ALL_ACCESS,
3024 &hPrinter2);
3025 if ( !W_ERROR_IS_OK(werror) ) {
3026 printf("failed (%s)\n", win_errstr(werror));
3027 goto done;
3029 printf("ok\n");
3031 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3032 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3033 #if 0
3034 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3035 #endif
3038 done:
3039 /* cleanup */
3041 printf("Closing printers...");
3042 rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
3043 rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
3044 printf("ok\n");
3046 /* close the second remote connection */
3048 cli_shutdown( cli_server2 );
3049 return WERR_OK;
3052 static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3054 printf("print_processor_name: %s\n", r->print_processor_name);
3057 static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3058 TALLOC_CTX *mem_ctx, int argc,
3059 const char **argv)
3061 WERROR werror;
3062 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3063 uint32_t num_procs, level = 1, i;
3064 union spoolss_PrintProcessorInfo *procs;
3066 /* Parse the command arguments */
3068 if (argc < 1 || argc > 4) {
3069 printf ("Usage: %s [environment] [level]\n", argv[0]);
3070 return WERR_OK;
3073 if (argc >= 2) {
3074 environment = argv[1];
3077 if (argc == 3) {
3078 level = atoi(argv[2]);
3081 /* Enumerate Print Processors */
3083 werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3084 cli->srv_name_slash,
3085 environment,
3086 level,
3088 &num_procs,
3089 &procs);
3090 if (!W_ERROR_IS_OK(werror))
3091 goto done;
3093 /* Display output */
3095 for (i = 0; i < num_procs; i++) {
3096 switch (level) {
3097 case 1:
3098 display_proc_info1(&procs[i].info1);
3099 break;
3103 done:
3104 return werror;
3107 static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3109 printf("name_array: %s\n", r->name_array);
3112 static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3113 TALLOC_CTX *mem_ctx, int argc,
3114 const char **argv)
3116 WERROR werror;
3117 const char *print_processor_name = "winprint";
3118 uint32_t num_procs, level = 1, i;
3119 union spoolss_PrintProcDataTypesInfo *procs;
3121 /* Parse the command arguments */
3123 if (argc < 1 || argc > 4) {
3124 printf ("Usage: %s [environment] [level]\n", argv[0]);
3125 return WERR_OK;
3128 if (argc >= 2) {
3129 print_processor_name = argv[1];
3132 if (argc == 3) {
3133 level = atoi(argv[2]);
3136 /* Enumerate Print Processor Data Types */
3138 werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3139 cli->srv_name_slash,
3140 print_processor_name,
3141 level,
3143 &num_procs,
3144 &procs);
3145 if (!W_ERROR_IS_OK(werror))
3146 goto done;
3148 /* Display output */
3150 for (i = 0; i < num_procs; i++) {
3151 switch (level) {
3152 case 1:
3153 display_proc_data_types_info1(&procs[i].info1);
3154 break;
3158 done:
3159 return werror;
3162 static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3164 printf("monitor_name: %s\n", r->monitor_name);
3167 static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3169 printf("monitor_name: %s\n", r->monitor_name);
3170 printf("environment: %s\n", r->environment);
3171 printf("dll_name: %s\n", r->dll_name);
3174 static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3175 TALLOC_CTX *mem_ctx, int argc,
3176 const char **argv)
3178 WERROR werror;
3179 uint32_t count, level = 1, i;
3180 union spoolss_MonitorInfo *info;
3182 /* Parse the command arguments */
3184 if (argc > 2) {
3185 printf("Usage: %s [level]\n", argv[0]);
3186 return WERR_OK;
3189 if (argc == 2) {
3190 level = atoi(argv[1]);
3193 /* Enumerate Print Monitors */
3195 werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3196 cli->srv_name_slash,
3197 level,
3199 &count,
3200 &info);
3201 if (!W_ERROR_IS_OK(werror)) {
3202 goto done;
3205 /* Display output */
3207 for (i = 0; i < count; i++) {
3208 switch (level) {
3209 case 1:
3210 display_monitor1(&info[i].info1);
3211 break;
3212 case 2:
3213 display_monitor2(&info[i].info2);
3214 break;
3218 done:
3219 return werror;
3222 /* List of commands exported by this module */
3223 struct cmd_set spoolss_commands[] = {
3225 { "SPOOLSS" },
3227 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
3228 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
3229 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
3230 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
3231 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
3232 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
3233 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
3234 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
3235 { "getjob", RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job, &syntax_spoolss, NULL, "Get print job", "" },
3236 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
3237 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
3238 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
3239 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
3240 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
3241 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
3242 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
3243 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
3244 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
3245 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
3246 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
3247 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
3248 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
3249 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
3250 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
3251 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
3252 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
3253 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
3254 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
3255 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
3256 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },
3257 { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &syntax_spoolss, NULL, "Enumerate Print Processors", "" },
3258 { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &syntax_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
3259 { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &syntax_spoolss, NULL, "Enumerate Print Monitors", "" },
3261 { NULL }