r4970: Fix for bug 2092, allowing fallback after kerberos and allow
[Samba/gebeck_regimport.git] / source / rpcclient / cmd_spoolss.c
blobfa77af4145d18b5e92a4fd21a84bc0769719d522
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gerald Carter 2001
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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "rpcclient.h"
28 struct table_node {
29 const char *long_archi;
30 const char *short_archi;
31 int version;
34 /* The version int is used by getdrivers. Note that
35 all architecture strings that support mutliple
36 versions must be grouped together since enumdrivers
37 uses this property to prevent issuing multiple
38 enumdriver calls for the same arch */
41 static const struct table_node archi_table[]= {
43 {"Windows 4.0", "WIN40", 0 },
44 {"Windows NT x86", "W32X86", 2 },
45 {"Windows NT x86", "W32X86", 3 },
46 {"Windows NT R4000", "W32MIPS", 2 },
47 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
48 {"Windows NT PowerPC", "W32PPC", 2 },
49 {"Windows IA64", "IA64", 3 },
50 {"Windows x64", "x64", 3 },
51 {NULL, "", -1 }
54 /**
55 * @file
57 * rpcclient module for SPOOLSS rpc pipe.
59 * This generally just parses and checks command lines, and then calls
60 * a cli_spoolss function.
61 **/
63 /****************************************************************************
64 function to do the mapping between the long architecture name and
65 the short one.
66 ****************************************************************************/
67 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
69 int i=-1;
71 DEBUG(107,("Getting architecture dependant directory\n"));
72 do {
73 i++;
74 } while ( (archi_table[i].long_archi!=NULL ) &&
75 StrCaseCmp(long_archi, archi_table[i].long_archi) );
77 if (archi_table[i].long_archi==NULL) {
78 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
79 return NULL;
82 /* this might be client code - but shouldn't this be an fstrcpy etc? */
85 DEBUGADD(108,("index: [%d]\n", i));
86 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
87 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
89 return archi_table[i].short_archi;
92 #if 0
93 /**********************************************************************
94 * dummy function -- placeholder
96 static WERROR cmd_spoolss_not_implemented(struct cli_state *cli,
97 TALLOC_CTX *mem_ctx,
98 int argc, const char **argv)
100 printf ("(*) This command is not currently implemented.\n");
101 return WERR_OK;
103 #endif
105 /***********************************************************************
106 * Get printer information
108 static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli,
109 TALLOC_CTX *mem_ctx,
110 int argc, const char **argv)
112 WERROR werror;
113 fstring printername;
114 fstring servername, user;
115 POLICY_HND hnd;
117 if (argc != 2) {
118 printf("Usage: %s <printername>\n", argv[0]);
119 return WERR_OK;
122 if (!cli)
123 return WERR_GENERAL_FAILURE;
125 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
126 strupper_m(servername);
127 fstrcpy(user, cli->user_name);
128 fstrcpy(printername, argv[1]);
130 /* Open the printer handle */
132 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
133 "", PRINTER_ALL_ACCESS,
134 servername, user, &hnd);
136 if (W_ERROR_IS_OK(werror)) {
137 printf("Printer %s opened successfully\n", printername);
138 werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
140 if (!W_ERROR_IS_OK(werror)) {
141 printf("Error closing printer handle! (%s)\n",
142 get_dos_error_msg(werror));
146 return werror;
150 /****************************************************************************
151 printer info level 0 display function
152 ****************************************************************************/
153 static void display_print_info_0(PRINTER_INFO_0 *i0)
155 fstring name = "";
156 fstring servername = "";
158 if (!i0)
159 return;
161 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
163 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
165 printf("\tprintername:[%s]\n", name);
166 printf("\tservername:[%s]\n", servername);
167 printf("\tcjobs:[0x%x]\n", i0->cjobs);
168 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
170 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
171 i0->day, i0->dayofweek);
172 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
173 i0->second, i0->milliseconds);
175 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
176 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
178 printf("\tmajorversion:[0x%x]\n", i0->major_version);
179 printf("\tbuildversion:[0x%x]\n", i0->build_version);
181 printf("\tunknown7:[0x%x]\n", i0->unknown7);
182 printf("\tunknown8:[0x%x]\n", i0->unknown8);
183 printf("\tunknown9:[0x%x]\n", i0->unknown9);
184 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
185 printf("\tunknown11:[0x%x]\n", i0->unknown11);
186 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
187 printf("\tunknown13:[0x%x]\n", i0->unknown13);
188 printf("\tunknown14:[0x%x]\n", i0->unknown14);
189 printf("\tunknown15:[0x%x]\n", i0->unknown15);
190 printf("\tunknown16:[0x%x]\n", i0->unknown16);
191 printf("\tchange_id:[0x%x]\n", i0->change_id);
192 printf("\tunknown18:[0x%x]\n", i0->unknown18);
193 printf("\tstatus:[0x%x]\n", i0->status);
194 printf("\tunknown20:[0x%x]\n", i0->unknown20);
195 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
196 printf("\tunknown22:[0x%x]\n", i0->unknown22);
197 printf("\tunknown23:[0x%x]\n", i0->unknown23);
198 printf("\tunknown24:[0x%x]\n", i0->unknown24);
199 printf("\tunknown25:[0x%x]\n", i0->unknown25);
200 printf("\tunknown26:[0x%x]\n", i0->unknown26);
201 printf("\tunknown27:[0x%x]\n", i0->unknown27);
202 printf("\tunknown28:[0x%x]\n", i0->unknown28);
203 printf("\tunknown29:[0x%x]\n", i0->unknown29);
205 printf("\n");
208 /****************************************************************************
209 printer info level 1 display function
210 ****************************************************************************/
211 static void display_print_info_1(PRINTER_INFO_1 *i1)
213 fstring desc = "";
214 fstring name = "";
215 fstring comm = "";
217 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
218 STR_TERMINATE);
220 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
221 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
223 printf("\tflags:[0x%x]\n", i1->flags);
224 printf("\tname:[%s]\n", name);
225 printf("\tdescription:[%s]\n", desc);
226 printf("\tcomment:[%s]\n", comm);
228 printf("\n");
231 /****************************************************************************
232 printer info level 2 display function
233 ****************************************************************************/
234 static void display_print_info_2(PRINTER_INFO_2 *i2)
236 fstring servername = "";
237 fstring printername = "";
238 fstring sharename = "";
239 fstring portname = "";
240 fstring drivername = "";
241 fstring comment = "";
242 fstring location = "";
243 fstring sepfile = "";
244 fstring printprocessor = "";
245 fstring datatype = "";
246 fstring parameters = "";
248 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
250 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
252 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
254 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
256 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
258 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
260 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
262 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
264 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
266 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
268 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
270 printf("\tservername:[%s]\n", servername);
271 printf("\tprintername:[%s]\n", printername);
272 printf("\tsharename:[%s]\n", sharename);
273 printf("\tportname:[%s]\n", portname);
274 printf("\tdrivername:[%s]\n", drivername);
275 printf("\tcomment:[%s]\n", comment);
276 printf("\tlocation:[%s]\n", location);
277 printf("\tsepfile:[%s]\n", sepfile);
278 printf("\tprintprocessor:[%s]\n", printprocessor);
279 printf("\tdatatype:[%s]\n", datatype);
280 printf("\tparameters:[%s]\n", parameters);
281 printf("\tattributes:[0x%x]\n", i2->attributes);
282 printf("\tpriority:[0x%x]\n", i2->priority);
283 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
284 printf("\tstarttime:[0x%x]\n", i2->starttime);
285 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
286 printf("\tstatus:[0x%x]\n", i2->status);
287 printf("\tcjobs:[0x%x]\n", i2->cjobs);
288 printf("\taverageppm:[0x%x]\n", i2->averageppm);
290 if (i2->secdesc)
291 display_sec_desc(i2->secdesc);
293 printf("\n");
296 /****************************************************************************
297 printer info level 3 display function
298 ****************************************************************************/
299 static void display_print_info_3(PRINTER_INFO_3 *i3)
301 printf("\tflags:[0x%x]\n", i3->flags);
303 display_sec_desc(i3->secdesc);
305 printf("\n");
308 /****************************************************************************
309 printer info level 7 display function
310 ****************************************************************************/
311 static void display_print_info_7(PRINTER_INFO_7 *i7)
313 fstring guid = "";
314 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
315 printf("\tguid:[%s]\n", guid);
316 printf("\taction:[0x%x]\n", i7->action);
320 /* Enumerate printers */
322 static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
323 TALLOC_CTX *mem_ctx,
324 int argc, const char **argv)
326 WERROR result;
327 uint32 info_level = 1;
328 PRINTER_INFO_CTR ctr;
329 uint32 i = 0, num_printers, needed;
330 fstring name;
332 if (argc > 3)
334 printf("Usage: %s [level] [name]\n", argv[0]);
335 return WERR_OK;
338 if (argc >= 2)
339 info_level = atoi(argv[1]);
341 if (argc == 3)
342 fstrcpy(name, argv[2]);
343 else {
344 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
345 strupper_m(name);
348 /* Enumerate printers -- Should we enumerate types other
349 than PRINTER_ENUM_LOCAL? Maybe accept as a parameter? --jerry */
351 ZERO_STRUCT(ctr);
353 result = cli_spoolss_enum_printers(
354 cli, mem_ctx, 0, &needed, name, PRINTER_ENUM_LOCAL,
355 info_level, &num_printers, &ctr);
357 if (W_ERROR_V(result) == ERRinsufficientbuffer)
358 result = cli_spoolss_enum_printers(
359 cli, mem_ctx, needed, NULL, name, PRINTER_ENUM_LOCAL,
360 info_level, &num_printers, &ctr);
362 if (W_ERROR_IS_OK(result)) {
364 if (!num_printers) {
365 printf ("No printers returned.\n");
366 goto done;
369 for (i = 0; i < num_printers; i++) {
370 switch(info_level) {
371 case 0:
372 display_print_info_0(&ctr.printers_0[i]);
373 break;
374 case 1:
375 display_print_info_1(&ctr.printers_1[i]);
376 break;
377 case 2:
378 display_print_info_2(&ctr.printers_2[i]);
379 break;
380 case 3:
381 display_print_info_3(&ctr.printers_3[i]);
382 break;
383 default:
384 printf("unknown info level %d\n", info_level);
385 goto done;
389 done:
391 return result;
394 /****************************************************************************
395 port info level 1 display function
396 ****************************************************************************/
397 static void display_port_info_1(PORT_INFO_1 *i1)
399 fstring buffer;
401 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
402 printf("\tPort Name:\t[%s]\n", buffer);
405 /****************************************************************************
406 port info level 2 display function
407 ****************************************************************************/
408 static void display_port_info_2(PORT_INFO_2 *i2)
410 fstring buffer;
412 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
413 printf("\tPort Name:\t[%s]\n", buffer);
414 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
416 printf("\tMonitor Name:\t[%s]\n", buffer);
417 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
419 printf("\tDescription:\t[%s]\n", buffer);
420 printf("\tPort Type:\t" );
421 if ( i2->port_type ) {
422 int comma = 0; /* hack */
423 printf( "[" );
424 if ( i2->port_type & PORT_TYPE_READ ) {
425 printf( "Read" );
426 comma = 1;
428 if ( i2->port_type & PORT_TYPE_WRITE ) {
429 printf( "%sWrite", comma ? ", " : "" );
430 comma = 1;
432 /* These two have slightly different interpretations
433 on 95/98/ME but I'm disregarding that for now */
434 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
435 printf( "%sRedirected", comma ? ", " : "" );
436 comma = 1;
438 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
439 printf( "%sNet-Attached", comma ? ", " : "" );
441 printf( "]\n" );
442 } else {
443 printf( "[Unset]\n" );
445 printf("\tReserved:\t[%d]\n", i2->reserved);
446 printf("\n");
449 /* Enumerate ports */
451 static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
452 TALLOC_CTX *mem_ctx, int argc,
453 const char **argv)
455 WERROR result;
456 uint32 needed, info_level = 1;
457 PORT_INFO_CTR ctr;
458 uint32 returned;
460 if (argc > 2) {
461 printf("Usage: %s [level]\n", argv[0]);
462 return WERR_OK;
465 if (argc == 2)
466 info_level = atoi(argv[1]);
468 /* Enumerate ports */
470 ZERO_STRUCT(ctr);
472 result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level,
473 &returned, &ctr);
475 if (W_ERROR_V(result) == ERRinsufficientbuffer)
476 result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
477 info_level, &returned, &ctr);
479 if (W_ERROR_IS_OK(result)) {
480 int i;
482 for (i = 0; i < returned; i++) {
483 switch (info_level) {
484 case 1:
485 display_port_info_1(&ctr.port.info_1[i]);
486 break;
487 case 2:
488 display_port_info_2(&ctr.port.info_2[i]);
489 break;
490 default:
491 printf("unknown info level %d\n", info_level);
492 break;
497 return result;
500 /***********************************************************************
501 * Set printer comment - use a level2 set.
503 static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
504 TALLOC_CTX *mem_ctx,
505 int argc, const char **argv)
507 POLICY_HND pol;
508 WERROR result;
509 uint32 needed;
510 uint32 info_level = 2;
511 BOOL opened_hnd = False;
512 PRINTER_INFO_CTR ctr;
513 fstring printername,
514 servername,
515 user,
516 comment;
518 if (argc == 1 || argc > 3) {
519 printf("Usage: %s printername comment\n", argv[0]);
521 return WERR_OK;
524 /* Open a printer handle */
525 if (argc == 3) {
526 fstrcpy(comment, argv[2]);
529 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
530 strupper_m(servername);
531 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
532 fstrcpy(user, cli->user_name);
534 /* get a printer handle */
535 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
536 PRINTER_ALL_ACCESS, servername,
537 user, &pol);
539 if (!W_ERROR_IS_OK(result))
540 goto done;
542 opened_hnd = True;
544 /* Get printer info */
545 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
547 if (W_ERROR_V(result) == ERRinsufficientbuffer)
548 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
550 if (!W_ERROR_IS_OK(result))
551 goto done;
554 /* Modify the comment. */
555 init_unistr(&ctr.printers_2->comment, comment);
556 ctr.printers_2->devmode = NULL;
557 ctr.printers_2->secdesc = NULL;
559 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
560 if (W_ERROR_IS_OK(result))
561 printf("Success in setting comment.\n");
563 done:
564 if (opened_hnd)
565 cli_spoolss_close_printer(cli, mem_ctx, &pol);
567 return result;
570 /***********************************************************************
571 * Set printer name - use a level2 set.
573 static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
574 TALLOC_CTX *mem_ctx,
575 int argc, const char **argv)
577 POLICY_HND pol;
578 WERROR result;
579 uint32 needed;
580 uint32 info_level = 2;
581 BOOL opened_hnd = False;
582 PRINTER_INFO_CTR ctr;
583 fstring printername,
584 servername,
585 user,
586 new_printername;
588 if (argc == 1 || argc > 3) {
589 printf("Usage: %s printername new_printername\n", argv[0]);
591 return WERR_OK;
594 /* Open a printer handle */
595 if (argc == 3) {
596 fstrcpy(new_printername, argv[2]);
599 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
600 strupper_m(servername);
601 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
602 fstrcpy(user, cli->user_name);
604 /* get a printer handle */
605 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
606 PRINTER_ALL_ACCESS, servername,
607 user, &pol);
609 if (!W_ERROR_IS_OK(result))
610 goto done;
612 opened_hnd = True;
614 /* Get printer info */
615 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
617 if (W_ERROR_V(result) == ERRinsufficientbuffer)
618 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
620 if (!W_ERROR_IS_OK(result))
621 goto done;
624 /* Modify the printername. */
625 init_unistr(&ctr.printers_2->printername, new_printername);
626 ctr.printers_2->devmode = NULL;
627 ctr.printers_2->secdesc = NULL;
629 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
630 if (W_ERROR_IS_OK(result))
631 printf("Success in setting printername.\n");
633 done:
634 if (opened_hnd)
635 cli_spoolss_close_printer(cli, mem_ctx, &pol);
637 return result;
640 /***********************************************************************
641 * Get printer information
643 static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
644 TALLOC_CTX *mem_ctx,
645 int argc, const char **argv)
647 POLICY_HND pol;
648 WERROR result;
649 uint32 info_level = 1;
650 BOOL opened_hnd = False;
651 PRINTER_INFO_CTR ctr;
652 fstring printername,
653 servername,
654 user;
655 uint32 needed;
657 if (argc == 1 || argc > 3) {
658 printf("Usage: %s <printername> [level]\n", argv[0]);
659 return WERR_OK;
662 /* Open a printer handle */
663 if (argc == 3) {
664 info_level = atoi(argv[2]);
667 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
668 strupper_m(servername);
669 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
670 fstrcpy(user, cli->user_name);
672 /* get a printer handle */
674 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
675 "", MAXIMUM_ALLOWED_ACCESS,
676 servername, user, &pol);
678 if (!W_ERROR_IS_OK(result))
679 goto done;
681 opened_hnd = True;
683 /* Get printer info */
685 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
686 &pol, info_level, &ctr);
688 if (W_ERROR_V(result) == ERRinsufficientbuffer)
689 result = cli_spoolss_getprinter(
690 cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
692 if (!W_ERROR_IS_OK(result))
693 goto done;
695 /* Display printer info */
697 switch (info_level) {
698 case 0:
699 display_print_info_0(ctr.printers_0);
700 break;
701 case 1:
702 display_print_info_1(ctr.printers_1);
703 break;
704 case 2:
705 display_print_info_2(ctr.printers_2);
706 break;
707 case 3:
708 display_print_info_3(ctr.printers_3);
709 break;
710 case 7:
711 display_print_info_7(ctr.printers_7);
712 break;
713 default:
714 printf("unknown info level %d\n", info_level);
715 break;
718 done:
719 if (opened_hnd)
720 cli_spoolss_close_printer(cli, mem_ctx, &pol);
722 return result;
725 static void display_reg_value(REGISTRY_VALUE value)
727 pstring text;
729 switch(value.type) {
730 case REG_DWORD:
731 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
732 *((uint32 *) value.data_p));
733 break;
734 case REG_SZ:
735 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
736 STR_TERMINATE);
737 printf("%s: REG_SZ: %s\n", value.valuename, text);
738 break;
739 case REG_BINARY:
740 printf("%s: REG_BINARY: unknown length value not displayed\n",
741 value.valuename);
742 break;
743 case REG_MULTI_SZ: {
744 uint16 *curstr = (uint16 *) value.data_p;
745 uint8 *start = value.data_p;
746 printf("%s: REG_MULTI_SZ:\n", value.valuename);
747 while ((*curstr != 0) &&
748 ((uint8 *) curstr < start + value.size)) {
749 rpcstr_pull(text, curstr, sizeof(text), -1,
750 STR_TERMINATE);
751 printf(" %s\n", text);
752 curstr += strlen(text) + 1;
755 break;
756 default:
757 printf("%s: unknown type %d\n", value.valuename, value.type);
762 /***********************************************************************
763 * Get printer data
765 static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
766 TALLOC_CTX *mem_ctx,
767 int argc, const char **argv)
769 POLICY_HND pol;
770 WERROR result;
771 BOOL opened_hnd = False;
772 fstring printername,
773 servername,
774 user;
775 uint32 needed;
776 const char *valuename;
777 REGISTRY_VALUE value;
779 if (argc != 3) {
780 printf("Usage: %s <printername> <valuename>\n", argv[0]);
781 printf("<printername> of . queries print server\n");
782 return WERR_OK;
784 valuename = argv[2];
786 /* Open a printer handle */
788 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
789 strupper_m(servername);
790 if (strncmp(argv[1], ".", sizeof(".")) == 0)
791 fstrcpy(printername, servername);
792 else
793 slprintf(printername, sizeof(servername)-1, "%s\\%s",
794 servername, argv[1]);
795 fstrcpy(user, cli->user_name);
797 /* get a printer handle */
799 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
800 "", MAXIMUM_ALLOWED_ACCESS,
801 servername, user, &pol);
803 if (!W_ERROR_IS_OK(result))
804 goto done;
806 opened_hnd = True;
808 /* Get printer info */
810 result = cli_spoolss_getprinterdata(cli, mem_ctx, 0, &needed,
811 &pol, valuename, &value);
813 if (W_ERROR_V(result) == ERRmoredata)
814 result = cli_spoolss_getprinterdata(
815 cli, mem_ctx, needed, NULL, &pol, valuename, &value);
817 if (!W_ERROR_IS_OK(result))
818 goto done;
820 /* Display printer data */
822 fstrcpy(value.valuename, valuename);
823 display_reg_value(value);
826 done:
827 if (opened_hnd)
828 cli_spoolss_close_printer(cli, mem_ctx, &pol);
830 return result;
833 /***********************************************************************
834 * Get printer data
836 static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
837 TALLOC_CTX *mem_ctx,
838 int argc, const char **argv)
840 POLICY_HND pol;
841 WERROR result;
842 BOOL opened_hnd = False;
843 fstring printername,
844 servername,
845 user;
846 uint32 needed;
847 const char *valuename, *keyname;
848 REGISTRY_VALUE value;
850 if (argc != 4) {
851 printf("Usage: %s <printername> <keyname> <valuename>\n",
852 argv[0]);
853 printf("<printername> of . queries print server\n");
854 return WERR_OK;
856 valuename = argv[3];
857 keyname = argv[2];
859 /* Open a printer handle */
861 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
862 strupper_m(servername);
863 if (strncmp(argv[1], ".", sizeof(".")) == 0)
864 fstrcpy(printername, servername);
865 else
866 slprintf(printername, sizeof(printername)-1, "%s\\%s",
867 servername, argv[1]);
868 fstrcpy(user, cli->user_name);
870 /* get a printer handle */
872 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
873 "", MAXIMUM_ALLOWED_ACCESS,
874 servername, user, &pol);
876 if (!W_ERROR_IS_OK(result))
877 goto done;
879 opened_hnd = True;
881 /* Get printer info */
883 result = cli_spoolss_getprinterdataex(cli, mem_ctx, 0, &needed,
884 &pol, keyname, valuename,
885 &value);
887 if (W_ERROR_V(result) == ERRmoredata)
888 result = cli_spoolss_getprinterdataex(cli, mem_ctx, needed,
889 NULL, &pol, keyname,
890 valuename, &value);
892 if (!W_ERROR_IS_OK(result))
893 goto done;
895 /* Display printer data */
897 fstrcpy(value.valuename, valuename);
898 display_reg_value(value);
901 done:
902 if (opened_hnd)
903 cli_spoolss_close_printer(cli, mem_ctx, &pol);
905 return result;
908 /****************************************************************************
909 printer info level 0 display function
910 ****************************************************************************/
911 static void display_print_driver_1(DRIVER_INFO_1 *i1)
913 fstring name;
914 if (i1 == NULL)
915 return;
917 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
919 printf ("Printer Driver Info 1:\n");
920 printf ("\tDriver Name: [%s]\n\n", name);
922 return;
925 /****************************************************************************
926 printer info level 1 display function
927 ****************************************************************************/
928 static void display_print_driver_2(DRIVER_INFO_2 *i1)
930 fstring name;
931 fstring architecture;
932 fstring driverpath;
933 fstring datafile;
934 fstring configfile;
935 if (i1 == NULL)
936 return;
938 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
939 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
940 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
941 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
942 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
944 printf ("Printer Driver Info 2:\n");
945 printf ("\tVersion: [%x]\n", i1->version);
946 printf ("\tDriver Name: [%s]\n", name);
947 printf ("\tArchitecture: [%s]\n", architecture);
948 printf ("\tDriver Path: [%s]\n", driverpath);
949 printf ("\tDatafile: [%s]\n", datafile);
950 printf ("\tConfigfile: [%s]\n\n", configfile);
952 return;
955 /****************************************************************************
956 printer info level 2 display function
957 ****************************************************************************/
958 static void display_print_driver_3(DRIVER_INFO_3 *i1)
960 fstring name = "";
961 fstring architecture = "";
962 fstring driverpath = "";
963 fstring datafile = "";
964 fstring configfile = "";
965 fstring helpfile = "";
966 fstring dependentfiles = "";
967 fstring monitorname = "";
968 fstring defaultdatatype = "";
970 int length=0;
971 BOOL valid = True;
973 if (i1 == NULL)
974 return;
976 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
977 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
978 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
979 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
980 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
981 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
982 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
983 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
985 printf ("Printer Driver Info 3:\n");
986 printf ("\tVersion: [%x]\n", i1->version);
987 printf ("\tDriver Name: [%s]\n",name);
988 printf ("\tArchitecture: [%s]\n", architecture);
989 printf ("\tDriver Path: [%s]\n", driverpath);
990 printf ("\tDatafile: [%s]\n", datafile);
991 printf ("\tConfigfile: [%s]\n", configfile);
992 printf ("\tHelpfile: [%s]\n\n", helpfile);
994 while (valid)
996 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
998 length+=strlen(dependentfiles)+1;
1000 if (strlen(dependentfiles) > 0)
1002 printf ("\tDependentfiles: [%s]\n", dependentfiles);
1004 else
1006 valid = False;
1010 printf ("\n");
1012 printf ("\tMonitorname: [%s]\n", monitorname);
1013 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
1015 return;
1018 /***********************************************************************
1019 * Get printer information
1021 static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
1022 TALLOC_CTX *mem_ctx,
1023 int argc, const char **argv)
1025 POLICY_HND pol;
1026 WERROR werror;
1027 uint32 info_level = 3;
1028 BOOL opened_hnd = False;
1029 PRINTER_DRIVER_CTR ctr;
1030 fstring printername,
1031 servername,
1032 user;
1033 uint32 i;
1034 BOOL success = False;
1036 if ((argc == 1) || (argc > 3))
1038 printf("Usage: %s <printername> [level]\n", argv[0]);
1039 return WERR_OK;
1042 /* get the arguments need to open the printer handle */
1043 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1044 strupper_m(servername);
1045 fstrcpy(user, cli->user_name);
1046 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1047 if (argc == 3)
1048 info_level = atoi(argv[2]);
1050 /* Open a printer handle */
1052 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1053 PRINTER_ACCESS_USE,
1054 servername, user, &pol);
1056 if (!W_ERROR_IS_OK(werror)) {
1057 printf("Error opening printer handle for %s!\n", printername);
1058 return werror;
1061 opened_hnd = True;
1063 /* loop through and print driver info level for each architecture */
1065 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1066 uint32 needed;
1068 werror = cli_spoolss_getprinterdriver(
1069 cli, mem_ctx, 0, &needed, &pol, info_level,
1070 archi_table[i].long_archi, archi_table[i].version,
1071 &ctr);
1073 if (W_ERROR_V(werror) == ERRinsufficientbuffer) {
1074 werror = cli_spoolss_getprinterdriver(
1075 cli, mem_ctx, needed, NULL, &pol, info_level,
1076 archi_table[i].long_archi, archi_table[i].version,
1077 &ctr);
1080 if (!W_ERROR_IS_OK(werror))
1081 continue;
1083 /* need at least one success */
1085 success = True;
1087 printf ("\n[%s]\n", archi_table[i].long_archi);
1089 switch (info_level) {
1090 case 1:
1091 display_print_driver_1 (ctr.info1);
1092 break;
1093 case 2:
1094 display_print_driver_2 (ctr.info2);
1095 break;
1096 case 3:
1097 display_print_driver_3 (ctr.info3);
1098 break;
1099 default:
1100 printf("unknown info level %d\n", info_level);
1101 break;
1105 /* Cleanup */
1107 if (opened_hnd)
1108 cli_spoolss_close_printer (cli, mem_ctx, &pol);
1110 if ( success )
1111 werror = WERR_OK;
1113 return werror;
1116 /***********************************************************************
1117 * Get printer information
1119 static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
1120 TALLOC_CTX *mem_ctx,
1121 int argc, const char **argv)
1123 WERROR werror;
1124 uint32 info_level = 1;
1125 PRINTER_DRIVER_CTR ctr;
1126 uint32 i, j,
1127 returned;
1129 if (argc > 2)
1131 printf("Usage: enumdrivers [level]\n");
1132 return WERR_OK;
1135 if (argc == 2)
1136 info_level = atoi(argv[1]);
1139 /* loop through and print driver info level for each architecture */
1140 for (i=0; archi_table[i].long_archi!=NULL; i++)
1142 uint32 needed;
1144 /* check to see if we already asked for this architecture string */
1146 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1147 continue;
1149 werror = cli_spoolss_enumprinterdrivers(
1150 cli, mem_ctx, 0, &needed, info_level,
1151 archi_table[i].long_archi, &returned, &ctr);
1153 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1154 werror = cli_spoolss_enumprinterdrivers(
1155 cli, mem_ctx, needed, NULL, info_level,
1156 archi_table[i].long_archi, &returned, &ctr);
1158 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1159 printf ("Server does not support environment [%s]\n",
1160 archi_table[i].long_archi);
1161 werror = WERR_OK;
1162 continue;
1165 if (returned == 0)
1166 continue;
1168 if (!W_ERROR_IS_OK(werror)) {
1169 printf ("Error getting driver for environment [%s] - %d\n",
1170 archi_table[i].long_archi, W_ERROR_V(werror));
1171 continue;
1174 printf ("\n[%s]\n", archi_table[i].long_archi);
1175 switch (info_level)
1178 case 1:
1179 for (j=0; j < returned; j++) {
1180 display_print_driver_1 (&(ctr.info1[j]));
1182 break;
1183 case 2:
1184 for (j=0; j < returned; j++) {
1185 display_print_driver_2 (&(ctr.info2[j]));
1187 break;
1188 case 3:
1189 for (j=0; j < returned; j++) {
1190 display_print_driver_3 (&(ctr.info3[j]));
1192 break;
1193 default:
1194 printf("unknown info level %d\n", info_level);
1195 break;
1199 return werror;
1202 /****************************************************************************
1203 printer info level 1 display function
1204 ****************************************************************************/
1205 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1207 fstring name;
1208 if (i1 == NULL)
1209 return;
1211 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1213 printf ("\tDirectory Name:[%s]\n", name);
1216 /***********************************************************************
1217 * Get printer driver directory information
1219 static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli,
1220 TALLOC_CTX *mem_ctx,
1221 int argc, const char **argv)
1223 WERROR result;
1224 fstring env;
1225 DRIVER_DIRECTORY_CTR ctr;
1226 uint32 needed;
1228 if (argc > 2) {
1229 printf("Usage: %s [environment]\n", argv[0]);
1230 return WERR_OK;
1233 /* Get the arguments need to open the printer handle */
1235 if (argc == 2)
1236 fstrcpy (env, argv[1]);
1237 else
1238 fstrcpy (env, "Windows NT x86");
1240 /* Get the directory. Only use Info level 1 */
1242 result = cli_spoolss_getprinterdriverdir(
1243 cli, mem_ctx, 0, &needed, 1, env, &ctr);
1245 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1246 result = cli_spoolss_getprinterdriverdir(
1247 cli, mem_ctx, needed, NULL, 1, env, &ctr);
1249 if (W_ERROR_IS_OK(result))
1250 display_printdriverdir_1(ctr.info1);
1252 return result;
1255 /*******************************************************************************
1256 set the version and environment fields of a DRIVER_INFO_3 struct
1257 ******************************************************************************/
1258 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1261 int i;
1263 for (i=0; archi_table[i].long_archi != NULL; i++)
1265 if (strcmp(arch, archi_table[i].short_archi) == 0)
1267 info->version = archi_table[i].version;
1268 init_unistr (&info->architecture, archi_table[i].long_archi);
1269 break;
1273 if (archi_table[i].long_archi == NULL)
1275 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1278 return;
1282 /**************************************************************************
1283 wrapper for strtok to get the next parameter from a delimited list.
1284 Needed to handle the empty parameter string denoted by "NULL"
1285 *************************************************************************/
1286 static char* get_driver_3_param (const char* str, const char* delim, UNISTR* dest)
1288 char *ptr;
1290 /* get the next token */
1291 ptr = strtok(str, delim);
1293 /* a string of 'NULL' is used to represent an empty
1294 parameter because two consecutive delimiters
1295 will not return an empty string. See man strtok(3)
1296 for details */
1297 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1298 ptr = NULL;
1300 if (dest != NULL)
1301 init_unistr(dest, ptr);
1303 return ptr;
1306 /********************************************************************************
1307 fill in the members of a DRIVER_INFO_3 struct using a character
1308 string in the form of
1309 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1310 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1311 <Default Data Type>:<Comma Separated list of Files>
1312 *******************************************************************************/
1313 static BOOL init_drv_info_3_members (
1314 TALLOC_CTX *mem_ctx,
1315 DRIVER_INFO_3 *info,
1316 const char *args
1319 char *str, *str2;
1320 uint32 len, i;
1322 /* fill in the UNISTR fields */
1323 str = get_driver_3_param (args, ":", &info->name);
1324 str = get_driver_3_param (NULL, ":", &info->driverpath);
1325 str = get_driver_3_param (NULL, ":", &info->datafile);
1326 str = get_driver_3_param (NULL, ":", &info->configfile);
1327 str = get_driver_3_param (NULL, ":", &info->helpfile);
1328 str = get_driver_3_param (NULL, ":", &info->monitorname);
1329 str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
1331 /* <Comma Separated List of Dependent Files> */
1332 str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
1333 str = str2;
1335 /* begin to strip out each filename */
1336 str = strtok(str, ",");
1337 len = 0;
1338 while (str != NULL)
1340 /* keep a cumlative count of the str lengths */
1341 len += strlen(str)+1;
1342 str = strtok(NULL, ",");
1345 /* allocate the space; add one extra slot for a terminating NULL.
1346 Each filename is NULL terminated and the end contains a double
1347 NULL */
1348 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1350 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1351 return False;
1353 for (i=0; i<len; i++)
1355 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1357 info->dependentfiles[len] = '\0';
1359 return True;
1363 static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
1364 TALLOC_CTX *mem_ctx,
1365 int argc, const char **argv)
1367 WERROR result;
1368 uint32 level = 3;
1369 PRINTER_DRIVER_CTR ctr;
1370 DRIVER_INFO_3 info3;
1371 const char *arch;
1372 fstring driver_name;
1374 /* parse the command arguements */
1375 if (argc != 3 && argc != 4)
1377 printf ("Usage: %s <Environment> \\\n", argv[0]);
1378 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1379 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1380 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1381 printf ("\t[version]\n");
1383 return WERR_OK;
1386 /* Fill in the DRIVER_INFO_3 struct */
1387 ZERO_STRUCT(info3);
1388 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1390 printf ("Error Unknown architechture [%s]\n", argv[1]);
1391 return WERR_INVALID_PARAM;
1393 else
1394 set_drv_info_3_env(&info3, arch);
1396 if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
1398 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1399 return WERR_INVALID_PARAM;
1402 /* if printer driver version specified, override the default version
1403 * used by the architecture. This allows installation of Windows
1404 * 2000 (version 3) printer drivers. */
1405 if (argc == 4)
1407 info3.version = atoi(argv[3]);
1411 ctr.info3 = &info3;
1412 result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1414 if (W_ERROR_IS_OK(result)) {
1415 rpcstr_pull(driver_name, info3.name.buffer,
1416 sizeof(driver_name), -1, STR_TERMINATE);
1417 printf ("Printer Driver %s successfully installed.\n",
1418 driver_name);
1421 return result;
1425 static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
1426 TALLOC_CTX *mem_ctx,
1427 int argc, const char **argv)
1429 WERROR result;
1430 uint32 level = 2;
1431 PRINTER_INFO_CTR ctr;
1432 PRINTER_INFO_2 info2;
1433 fstring servername;
1435 /* parse the command arguements */
1436 if (argc != 5)
1438 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1439 return WERR_OK;
1442 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1443 strupper_m(servername);
1445 /* Fill in the DRIVER_INFO_2 struct */
1446 ZERO_STRUCT(info2);
1447 #if 0 /* JERRY */
1448 init_unistr( &info2.servername, servername);
1449 #endif
1450 init_unistr( &info2.printername, argv[1]);
1451 init_unistr( &info2.sharename, argv[2]);
1452 init_unistr( &info2.drivername, argv[3]);
1453 init_unistr( &info2.portname, argv[4]);
1454 init_unistr( &info2.comment, "Created by rpcclient");
1455 init_unistr( &info2.printprocessor, "winprint");
1456 init_unistr( &info2.datatype, "RAW");
1457 info2.devmode = NULL;
1458 info2.secdesc = NULL;
1459 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1460 info2.priority = 0;
1461 info2.defaultpriority = 0;
1462 info2.starttime = 0;
1463 info2.untiltime = 0;
1465 /* These three fields must not be used by AddPrinter()
1466 as defined in the MS Platform SDK documentation..
1467 --jerry
1468 info2.status = 0;
1469 info2.cjobs = 0;
1470 info2.averageppm = 0;
1473 ctr.printers_2 = &info2;
1474 result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1476 if (W_ERROR_IS_OK(result))
1477 printf ("Printer %s successfully installed.\n", argv[1]);
1479 return result;
1482 static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
1483 TALLOC_CTX *mem_ctx,
1484 int argc, const char **argv)
1486 POLICY_HND pol;
1487 WERROR result;
1488 uint32 level = 2;
1489 BOOL opened_hnd = False;
1490 PRINTER_INFO_CTR ctr;
1491 PRINTER_INFO_2 info2;
1492 fstring servername,
1493 printername,
1494 user;
1495 uint32 needed;
1497 /* parse the command arguements */
1498 if (argc != 3)
1500 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1501 return WERR_OK;
1504 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1505 strupper_m(servername);
1506 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1507 fstrcpy(user, cli->user_name);
1509 /* Get a printer handle */
1511 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1512 PRINTER_ALL_ACCESS,
1513 servername, user, &pol);
1515 if (!W_ERROR_IS_OK(result))
1516 goto done;
1518 opened_hnd = True;
1520 /* Get printer info */
1522 ZERO_STRUCT (info2);
1523 ctr.printers_2 = &info2;
1525 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
1526 &pol, level, &ctr);
1528 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1529 result = cli_spoolss_getprinter(
1530 cli, mem_ctx, needed, NULL, &pol, level, &ctr);
1532 if (!W_ERROR_IS_OK(result)) {
1533 printf ("Unable to retrieve printer information!\n");
1534 goto done;
1537 /* Set the printer driver */
1539 init_unistr(&ctr.printers_2->drivername, argv[2]);
1541 result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1543 if (!W_ERROR_IS_OK(result)) {
1544 printf("SetPrinter call failed!\n");
1545 goto done;;
1548 printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
1550 done:
1551 /* Cleanup */
1553 if (opened_hnd)
1554 cli_spoolss_close_printer(cli, mem_ctx, &pol);
1556 return result;
1560 static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli,
1561 TALLOC_CTX *mem_ctx,
1562 int argc, const char **argv)
1564 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1566 int i;
1567 int vers = -1;
1569 const char *arch = NULL;
1571 /* parse the command arguements */
1572 if (argc < 2 || argc > 4) {
1573 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1574 return WERR_OK;
1577 if (argc >= 3)
1578 arch = argv[2];
1579 if (argc == 4)
1580 vers = atoi (argv[3]);
1583 /* delete the driver for all architectures */
1584 for (i=0; archi_table[i].long_archi; i++) {
1586 if (arch && !strequal( archi_table[i].long_archi, arch))
1587 continue;
1589 if (vers >= 0 && archi_table[i].version != vers)
1590 continue;
1592 /* make the call to remove the driver */
1593 result = cli_spoolss_deleteprinterdriverex(
1594 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1596 if ( !W_ERROR_IS_OK(result) )
1598 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1599 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1600 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1603 else
1605 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1606 archi_table[i].long_archi, archi_table[i].version);
1607 ret = WERR_OK;
1611 return ret;
1615 static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
1616 TALLOC_CTX *mem_ctx,
1617 int argc, const char **argv)
1619 WERROR result;
1620 fstring servername;
1621 int i;
1623 /* parse the command arguements */
1624 if (argc != 2)
1626 printf ("Usage: %s <driver>\n", argv[0]);
1627 return WERR_OK;
1630 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1631 strupper_m(servername);
1633 /* delete the driver for all architectures */
1634 for (i=0; archi_table[i].long_archi; i++)
1636 /* make the call to remove the driver */
1637 result = cli_spoolss_deleteprinterdriver(
1638 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1640 if ( !W_ERROR_IS_OK(result) ) {
1641 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1642 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1643 argv[1], archi_table[i].long_archi,
1644 W_ERROR_V(result));
1647 else
1649 printf ("Driver %s removed for arch [%s].\n", argv[1],
1650 archi_table[i].long_archi);
1654 return result;
1657 static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
1658 TALLOC_CTX *mem_ctx,
1659 int argc, const char **argv)
1661 WERROR result;
1662 char *servername = NULL, *environment = NULL;
1663 fstring procdir;
1664 uint32 needed;
1666 /* parse the command arguements */
1667 if (argc > 2) {
1668 printf ("Usage: %s [environment]\n", argv[0]);
1669 return WERR_OK;
1672 if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1673 return WERR_NOMEM;
1674 strupper_m(servername);
1676 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1677 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1678 SAFE_FREE(servername);
1679 return WERR_NOMEM;
1682 result = cli_spoolss_getprintprocessordirectory(
1683 cli, mem_ctx, 0, &needed, servername, environment, procdir);
1685 if (W_ERROR_V(result) == ERRinsufficientbuffer)
1686 result = cli_spoolss_getprintprocessordirectory(
1687 cli, mem_ctx, needed, NULL, servername, environment,
1688 procdir);
1690 if (W_ERROR_IS_OK(result))
1691 printf("%s\n", procdir);
1693 SAFE_FREE(servername);
1694 SAFE_FREE(environment);
1696 return result;
1699 /* Add a form */
1701 static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1702 int argc, const char **argv)
1704 POLICY_HND handle;
1705 WERROR werror;
1706 char *servername = NULL, *printername = NULL;
1707 FORM form;
1708 BOOL got_handle = False;
1710 /* Parse the command arguements */
1712 if (argc != 3) {
1713 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1714 return WERR_OK;
1717 /* Get a printer handle */
1719 asprintf(&servername, "\\\\%s", cli->desthost);
1720 strupper_m(servername);
1721 asprintf(&printername, "%s\\%s", servername, argv[1]);
1723 werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1724 PRINTER_ALL_ACCESS,
1725 servername, cli->user_name, &handle);
1727 if (!W_ERROR_IS_OK(werror))
1728 goto done;
1730 got_handle = True;
1732 /* Dummy up some values for the form data */
1734 form.flags = FORM_USER;
1735 form.size_x = form.size_y = 100;
1736 form.left = 0;
1737 form.top = 10;
1738 form.right = 20;
1739 form.bottom = 30;
1741 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1743 /* Add the form */
1746 werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1748 done:
1749 if (got_handle)
1750 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1752 SAFE_FREE(servername);
1753 SAFE_FREE(printername);
1755 return werror;
1758 /* Set a form */
1760 static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1761 int argc, const char **argv)
1763 POLICY_HND handle;
1764 WERROR werror;
1765 char *servername = NULL, *printername = NULL;
1766 FORM form;
1767 BOOL got_handle = False;
1769 /* Parse the command arguements */
1771 if (argc != 3) {
1772 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1773 return WERR_OK;
1776 /* Get a printer handle */
1778 asprintf(&servername, "\\\\%s", cli->desthost);
1779 strupper_m(servername);
1780 asprintf(&printername, "%s\\%s", servername, argv[1]);
1782 werror = cli_spoolss_open_printer_ex(
1783 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1784 servername, cli->user_name, &handle);
1786 if (!W_ERROR_IS_OK(werror))
1787 goto done;
1789 got_handle = True;
1791 /* Dummy up some values for the form data */
1793 form.flags = FORM_PRINTER;
1794 form.size_x = form.size_y = 100;
1795 form.left = 0;
1796 form.top = 1000;
1797 form.right = 2000;
1798 form.bottom = 3000;
1800 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1802 /* Set the form */
1804 werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1806 done:
1807 if (got_handle)
1808 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1810 SAFE_FREE(servername);
1811 SAFE_FREE(printername);
1813 return werror;
1816 /* Get a form */
1818 static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1819 int argc, const char **argv)
1821 POLICY_HND handle;
1822 WERROR werror;
1823 char *servername = NULL, *printername = NULL;
1824 FORM_1 form;
1825 BOOL got_handle = False;
1826 uint32 needed;
1828 /* Parse the command arguements */
1830 if (argc != 3) {
1831 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1832 return WERR_OK;
1835 /* Get a printer handle */
1837 asprintf(&servername, "\\\\%s", cli->desthost);
1838 strupper_m(servername);
1839 asprintf(&printername, "%s\\%s", servername, argv[1]);
1841 werror = cli_spoolss_open_printer_ex(
1842 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1843 servername, cli->user_name, &handle);
1845 if (!W_ERROR_IS_OK(werror))
1846 goto done;
1848 got_handle = True;
1850 /* Set the form */
1852 werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
1853 &handle, argv[2], 1, &form);
1855 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1856 werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
1857 &handle, argv[2], 1, &form);
1859 if (!W_ERROR_IS_OK(werror))
1860 goto done;
1862 printf("width: %d\n", form.width);
1863 printf("length: %d\n", form.length);
1864 printf("left: %d\n", form.left);
1865 printf("top: %d\n", form.top);
1866 printf("right: %d\n", form.right);
1867 printf("bottom: %d\n", form.bottom);
1869 done:
1870 if (got_handle)
1871 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1873 SAFE_FREE(servername);
1874 SAFE_FREE(printername);
1876 return werror;
1879 /* Delete a form */
1881 static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
1882 TALLOC_CTX *mem_ctx, int argc,
1883 const char **argv)
1885 POLICY_HND handle;
1886 WERROR werror;
1887 char *servername = NULL, *printername = NULL;
1888 BOOL got_handle = False;
1890 /* Parse the command arguements */
1892 if (argc != 3) {
1893 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1894 return WERR_OK;
1897 /* Get a printer handle */
1899 asprintf(&servername, "\\\\%s", cli->desthost);
1900 strupper_m(servername);
1901 asprintf(&printername, "%s\\%s", servername, argv[1]);
1903 werror = cli_spoolss_open_printer_ex(
1904 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1905 servername, cli->user_name, &handle);
1907 if (!W_ERROR_IS_OK(werror))
1908 goto done;
1910 got_handle = True;
1912 /* Delete the form */
1914 werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1916 done:
1917 if (got_handle)
1918 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1920 SAFE_FREE(servername);
1921 SAFE_FREE(printername);
1923 return werror;
1926 /* Enumerate forms */
1928 static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
1929 TALLOC_CTX *mem_ctx, int argc,
1930 const char **argv)
1932 POLICY_HND handle;
1933 WERROR werror;
1934 char *servername = NULL, *printername = NULL;
1935 BOOL got_handle = False;
1936 uint32 needed, num_forms, level = 1, i;
1937 FORM_1 *forms;
1939 /* Parse the command arguements */
1941 if (argc != 2) {
1942 printf ("Usage: %s <printer>\n", argv[0]);
1943 return WERR_OK;
1946 /* Get a printer handle */
1948 asprintf(&servername, "\\\\%s", cli->desthost);
1949 strupper_m(servername);
1950 asprintf(&printername, "%s\\%s", servername, argv[1]);
1952 werror = cli_spoolss_open_printer_ex(
1953 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1954 servername, cli->user_name, &handle);
1956 if (!W_ERROR_IS_OK(werror))
1957 goto done;
1959 got_handle = True;
1961 /* Enumerate forms */
1963 werror = cli_spoolss_enumforms(
1964 cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
1966 if (W_ERROR_V(werror) == ERRinsufficientbuffer)
1967 werror = cli_spoolss_enumforms(
1968 cli, mem_ctx, needed, NULL, &handle, level,
1969 &num_forms, &forms);
1971 if (!W_ERROR_IS_OK(werror))
1972 goto done;
1974 /* Display output */
1976 for (i = 0; i < num_forms; i++) {
1977 fstring form_name;
1979 if (forms[i].name.buffer)
1980 rpcstr_pull(form_name, forms[i].name.buffer,
1981 sizeof(form_name), -1, STR_TERMINATE);
1983 printf("%s\n", form_name);
1986 done:
1987 if (got_handle)
1988 cli_spoolss_close_printer(cli, mem_ctx, &handle);
1990 SAFE_FREE(servername);
1991 SAFE_FREE(printername);
1993 return werror;
1996 static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
1997 TALLOC_CTX *mem_ctx,
1998 int argc, const char **argv)
2000 WERROR result;
2001 uint32 needed;
2002 fstring servername, printername, user;
2003 POLICY_HND pol;
2004 BOOL opened_hnd = False;
2005 PRINTER_INFO_CTR ctr;
2006 PRINTER_INFO_0 info;
2007 REGISTRY_VALUE value;
2008 UNISTR2 data;
2010 /* parse the command arguements */
2011 if (argc != 4) {
2012 printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
2013 return WERR_OK;
2016 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2017 strupper_m(servername);
2018 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
2019 fstrcpy(user, cli->user_name);
2021 /* get a printer handle */
2022 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2023 MAXIMUM_ALLOWED_ACCESS, servername,
2024 user, &pol);
2025 if (!W_ERROR_IS_OK(result))
2026 goto done;
2028 opened_hnd = True;
2030 ctr.printers_0 = &info;
2032 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
2033 &pol, 0, &ctr);
2035 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2036 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2038 if (!W_ERROR_IS_OK(result))
2039 goto done;
2041 printf("%s\n", timestring(True));
2042 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2044 /* Set the printer data */
2046 init_unistr2(&data, argv[3], UNI_STR_TERMINATE);
2047 fstrcpy(value.valuename, argv[2]);
2048 value.type = REG_SZ;
2049 value.size = data.uni_str_len * 2;
2050 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2052 result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2054 if (!W_ERROR_IS_OK(result)) {
2055 printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
2056 goto done;
2058 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
2060 result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
2062 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2063 result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
2065 if (!W_ERROR_IS_OK(result))
2066 goto done;
2068 printf("%s\n", timestring(True));
2069 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2071 done:
2072 /* cleanup */
2073 if (opened_hnd)
2074 cli_spoolss_close_printer(cli, mem_ctx, &pol);
2076 return result;
2079 static void display_job_info_1(JOB_INFO_1 *job)
2081 fstring username = "", document = "", text_status = "";
2083 rpcstr_pull(username, job->username.buffer,
2084 sizeof(username), -1, STR_TERMINATE);
2086 rpcstr_pull(document, job->document.buffer,
2087 sizeof(document), -1, STR_TERMINATE);
2089 rpcstr_pull(text_status, job->text_status.buffer,
2090 sizeof(text_status), -1, STR_TERMINATE);
2092 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2093 username, document, text_status, job->pagesprinted,
2094 job->totalpages);
2097 static void display_job_info_2(JOB_INFO_2 *job)
2099 fstring username = "", document = "", text_status = "";
2101 rpcstr_pull(username, job->username.buffer,
2102 sizeof(username), -1, STR_TERMINATE);
2104 rpcstr_pull(document, job->document.buffer,
2105 sizeof(document), -1, STR_TERMINATE);
2107 rpcstr_pull(text_status, job->text_status.buffer,
2108 sizeof(text_status), -1, STR_TERMINATE);
2110 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2111 username, document, text_status, job->pagesprinted,
2112 job->totalpages, job->size);
2115 /* Enumerate jobs */
2117 static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
2118 TALLOC_CTX *mem_ctx, int argc,
2119 const char **argv)
2121 WERROR result;
2122 uint32 needed, level = 1, num_jobs, i;
2123 BOOL got_hnd = False;
2124 pstring printername;
2125 fstring servername, user;
2126 POLICY_HND hnd;
2127 JOB_INFO_CTR ctr;
2129 if (argc < 2 || argc > 3) {
2130 printf("Usage: %s printername [level]\n", argv[0]);
2131 return WERR_OK;
2134 if (argc == 3)
2135 level = atoi(argv[2]);
2137 /* Open printer handle */
2139 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2140 strupper_m(servername);
2141 fstrcpy(user, cli->user_name);
2142 slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
2143 strupper_m(printername);
2144 pstrcat(printername, argv[1]);
2146 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2147 "", MAXIMUM_ALLOWED_ACCESS,
2148 servername, user, &hnd);
2150 if (!W_ERROR_IS_OK(result))
2151 goto done;
2153 got_hnd = True;
2155 /* Enumerate ports */
2157 result = cli_spoolss_enumjobs(
2158 cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
2159 &num_jobs, &ctr);
2161 if (W_ERROR_V(result) == ERRinsufficientbuffer)
2162 result = cli_spoolss_enumjobs(
2163 cli, mem_ctx, needed, NULL, &hnd, level, 0,
2164 1000, &num_jobs, &ctr);
2166 if (!W_ERROR_IS_OK(result))
2167 goto done;
2169 for (i = 0; i < num_jobs; i++) {
2170 switch(level) {
2171 case 1:
2172 display_job_info_1(&ctr.job.job_info_1[i]);
2173 break;
2174 case 2:
2175 display_job_info_2(&ctr.job.job_info_2[i]);
2176 break;
2177 default:
2178 d_printf("unknown info level %d\n", level);
2179 break;
2183 done:
2184 if (got_hnd)
2185 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2187 return result;
2190 /* enumerate data */
2192 static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
2193 TALLOC_CTX *mem_ctx, int argc,
2194 const char **argv)
2196 WERROR result;
2197 uint32 i=0, val_needed, data_needed;
2198 BOOL got_hnd = False;
2199 pstring printername;
2200 fstring servername, user;
2201 POLICY_HND hnd;
2203 if (argc != 2) {
2204 printf("Usage: %s printername\n", argv[0]);
2205 return WERR_OK;
2208 /* Open printer handle */
2210 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2211 strupper_m(servername);
2212 fstrcpy(user, cli->user_name);
2213 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2214 strupper_m(printername);
2215 pstrcat(printername, argv[1]);
2217 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2218 "", MAXIMUM_ALLOWED_ACCESS,
2219 servername, user, &hnd);
2221 if (!W_ERROR_IS_OK(result))
2222 goto done;
2224 got_hnd = True;
2226 /* Enumerate data */
2228 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2229 &val_needed, &data_needed,
2230 NULL);
2231 while (W_ERROR_IS_OK(result)) {
2232 REGISTRY_VALUE value;
2233 result = cli_spoolss_enumprinterdata(
2234 cli, mem_ctx, &hnd, i++, val_needed,
2235 data_needed, 0, 0, &value);
2236 if (W_ERROR_IS_OK(result))
2237 display_reg_value(value);
2239 if (W_ERROR_V(result) == ERRnomoreitems)
2240 result = W_ERROR(ERRsuccess);
2242 done:
2243 if (got_hnd)
2244 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2246 return result;
2249 /* enumerate data for a given key */
2251 static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
2252 TALLOC_CTX *mem_ctx, int argc,
2253 const char **argv)
2255 WERROR result;
2256 uint32 needed, i;
2257 BOOL got_hnd = False;
2258 pstring printername;
2259 fstring servername, user;
2260 const char *keyname = NULL;
2261 POLICY_HND hnd;
2262 REGVAL_CTR ctr;
2264 if (argc != 3) {
2265 printf("Usage: %s printername <keyname>\n", argv[0]);
2266 return WERR_OK;
2269 keyname = argv[2];
2271 /* Open printer handle */
2273 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2274 strupper_m(servername);
2275 fstrcpy(user, cli->user_name);
2276 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2277 strupper_m(printername);
2278 pstrcat(printername, argv[1]);
2280 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2281 "", MAXIMUM_ALLOWED_ACCESS,
2282 servername, user, &hnd);
2284 if (!W_ERROR_IS_OK(result))
2285 goto done;
2287 got_hnd = True;
2289 /* Enumerate subkeys */
2291 result = cli_spoolss_enumprinterdataex(
2292 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
2294 if (W_ERROR_V(result) == ERRmoredata)
2295 result = cli_spoolss_enumprinterdataex(
2296 cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
2298 if (!W_ERROR_IS_OK(result))
2299 goto done;
2301 for (i=0; i < ctr.num_values; i++) {
2302 display_reg_value(*(ctr.values[i]));
2305 regval_ctr_destroy(&ctr);
2307 done:
2308 if (got_hnd)
2309 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2311 return result;
2314 /* enumerate subkeys */
2316 static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
2317 TALLOC_CTX *mem_ctx, int argc,
2318 const char **argv)
2320 WERROR result;
2321 uint32 needed, returned;
2322 BOOL got_hnd = False;
2323 pstring printername;
2324 fstring servername, user;
2325 const char *keyname = NULL;
2326 POLICY_HND hnd;
2327 uint16 *keylist = NULL, *curkey;
2329 if (argc < 2 || argc > 3) {
2330 printf("Usage: %s printername [keyname]\n", argv[0]);
2331 return WERR_OK;
2334 if (argc == 3)
2335 keyname = argv[2];
2336 else
2337 keyname = "";
2339 /* Open printer handle */
2341 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2342 strupper_m(servername);
2343 fstrcpy(user, cli->user_name);
2344 slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
2345 strupper_m(printername);
2346 pstrcat(printername, argv[1]);
2348 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2349 "", MAXIMUM_ALLOWED_ACCESS,
2350 servername, user, &hnd);
2352 if (!W_ERROR_IS_OK(result))
2353 goto done;
2355 got_hnd = True;
2357 /* Enumerate subkeys */
2359 result = cli_spoolss_enumprinterkey(
2360 cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
2362 if (W_ERROR_V(result) == ERRmoredata)
2363 result = cli_spoolss_enumprinterkey(
2364 cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
2365 &returned);
2367 if (!W_ERROR_IS_OK(result))
2368 goto done;
2370 curkey = keylist;
2371 while (*curkey != 0) {
2372 pstring subkey;
2373 rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
2374 STR_TERMINATE);
2375 printf("%s\n", subkey);
2376 curkey += strlen(subkey) + 1;
2379 safe_free(keylist);
2381 done:
2382 if (got_hnd)
2383 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2385 return result;
2388 static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
2389 TALLOC_CTX *mem_ctx, int argc,
2390 const char **argv)
2392 fstring servername, printername;
2393 POLICY_HND hnd;
2394 BOOL got_hnd = False;
2395 WERROR result;
2396 SPOOL_NOTIFY_OPTION option;
2398 if (argc != 2) {
2399 printf("Usage: %s printername\n", argv[0]);
2400 result = WERR_OK;
2401 goto done;
2404 /* Open printer */
2406 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2407 strupper_m(servername);
2409 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
2410 argv[1]);
2411 strupper_m(printername);
2413 result = cli_spoolss_open_printer_ex(
2414 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2415 servername, cli->user_name, &hnd);
2417 if (!W_ERROR_IS_OK(result)) {
2418 printf("Error opening %s\n", argv[1]);
2419 goto done;
2422 got_hnd = True;
2424 /* Create spool options */
2426 ZERO_STRUCT(option);
2428 option.version = 2;
2429 option.option_type_ptr = 1;
2430 option.count = option.ctr.count = 2;
2432 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2434 ZERO_STRUCT(option.ctr.type[0]);
2435 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2436 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2437 option.ctr.type[0].fields_ptr = 1;
2438 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2440 ZERO_STRUCT(option.ctr.type[1]);
2441 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2442 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2443 option.ctr.type[1].fields_ptr = 1;
2444 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2446 /* Send rffpcnex */
2448 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2449 strupper_m(servername);
2451 result = cli_spoolss_rffpcnex(
2452 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2454 if (!W_ERROR_IS_OK(result)) {
2455 printf("Error rffpcnex %s\n", argv[1]);
2456 goto done;
2459 done:
2460 if (got_hnd)
2461 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
2463 return result;
2466 /* List of commands exported by this module */
2467 struct cmd_set spoolss_commands[] = {
2469 { "SPOOLSS" },
2471 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" },
2472 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" },
2473 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" },
2474 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, "Delete a printer driver with files", "" },
2475 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" },
2476 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" },
2477 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" },
2478 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" },
2479 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" },
2480 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" },
2481 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" },
2482 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" },
2483 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""},
2484 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" },
2485 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" },
2486 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" },
2487 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" },
2488 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" },
2489 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
2490 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" },
2491 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" },
2492 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" },
2493 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" },
2494 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" },
2495 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" },
2496 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, "Set printername", "" },
2497 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" },
2498 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" },
2500 { NULL }