2 Unix SMB/CIFS implementation.
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.
26 #include "rpcclient.h"
29 const char *long_archi
;
30 const char *short_archi
;
34 static const struct table_node archi_table
[]= {
36 {"Windows 4.0", "WIN40", 0 },
37 {"Windows NT x86", "W32X86", 2 },
38 {"Windows NT x86", "W32X86", 3 },
39 {"Windows NT R4000", "W32MIPS", 2 },
40 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
41 {"Windows NT PowerPC", "W32PPC", 2 },
42 {"Windows IA64", "IA64", 3 },
49 * rpcclient module for SPOOLSS rpc pipe.
51 * This generally just parses and checks command lines, and then calls
52 * a cli_spoolss function.
55 /****************************************************************************
56 function to do the mapping between the long architecture name and
58 ****************************************************************************/
59 static const char *cmd_spoolss_get_short_archi(const char *long_archi
)
63 DEBUG(107,("Getting architecture dependant directory\n"));
66 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
67 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
69 if (archi_table
[i
].long_archi
==NULL
) {
70 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
74 /* this might be client code - but shouldn't this be an fstrcpy etc? */
77 DEBUGADD(108,("index: [%d]\n", i
));
78 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
79 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
81 return archi_table
[i
].short_archi
;
85 /**********************************************************************
86 * dummy function -- placeholder
88 static WERROR
cmd_spoolss_not_implemented(struct cli_state
*cli
,
90 int argc
, const char **argv
)
92 printf ("(*) This command is not currently implemented.\n");
97 /***********************************************************************
98 * Get printer information
100 static WERROR
cmd_spoolss_open_printer_ex(struct cli_state
*cli
,
102 int argc
, const char **argv
)
106 fstring servername
, user
;
110 printf("Usage: %s <printername>\n", argv
[0]);
115 return WERR_GENERAL_FAILURE
;
117 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
118 strupper_m(servername
);
119 fstrcpy(user
, cli
->user_name
);
120 fstrcpy(printername
, argv
[1]);
122 /* Open the printer handle */
124 werror
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
125 "", PRINTER_ALL_ACCESS
,
126 servername
, user
, &hnd
);
128 if (W_ERROR_IS_OK(werror
)) {
129 printf("Printer %s opened successfully\n", printername
);
130 werror
= cli_spoolss_close_printer(cli
, mem_ctx
, &hnd
);
132 if (!W_ERROR_IS_OK(werror
)) {
133 printf("Error closing printer handle! (%s)\n",
134 get_dos_error_msg(werror
));
142 /****************************************************************************
143 printer info level 0 display function
144 ****************************************************************************/
145 static void display_print_info_0(PRINTER_INFO_0
*i0
)
148 fstring servername
= "";
153 rpcstr_pull(name
, i0
->printername
.buffer
, sizeof(name
), -1, STR_TERMINATE
);
155 rpcstr_pull(servername
, i0
->servername
.buffer
, sizeof(servername
), -1,STR_TERMINATE
);
157 printf("\tprintername:[%s]\n", name
);
158 printf("\tservername:[%s]\n", servername
);
159 printf("\tcjobs:[0x%x]\n", i0
->cjobs
);
160 printf("\ttotal_jobs:[0x%x]\n", i0
->total_jobs
);
162 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0
->year
, i0
->month
,
163 i0
->day
, i0
->dayofweek
);
164 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0
->hour
, i0
->minute
,
165 i0
->second
, i0
->milliseconds
);
167 printf("\tglobal_counter:[0x%x]\n", i0
->global_counter
);
168 printf("\ttotal_pages:[0x%x]\n", i0
->total_pages
);
170 printf("\tmajorversion:[0x%x]\n", i0
->major_version
);
171 printf("\tbuildversion:[0x%x]\n", i0
->build_version
);
173 printf("\tunknown7:[0x%x]\n", i0
->unknown7
);
174 printf("\tunknown8:[0x%x]\n", i0
->unknown8
);
175 printf("\tunknown9:[0x%x]\n", i0
->unknown9
);
176 printf("\tsession_counter:[0x%x]\n", i0
->session_counter
);
177 printf("\tunknown11:[0x%x]\n", i0
->unknown11
);
178 printf("\tprinter_errors:[0x%x]\n", i0
->printer_errors
);
179 printf("\tunknown13:[0x%x]\n", i0
->unknown13
);
180 printf("\tunknown14:[0x%x]\n", i0
->unknown14
);
181 printf("\tunknown15:[0x%x]\n", i0
->unknown15
);
182 printf("\tunknown16:[0x%x]\n", i0
->unknown16
);
183 printf("\tchange_id:[0x%x]\n", i0
->change_id
);
184 printf("\tunknown18:[0x%x]\n", i0
->unknown18
);
185 printf("\tstatus:[0x%x]\n", i0
->status
);
186 printf("\tunknown20:[0x%x]\n", i0
->unknown20
);
187 printf("\tc_setprinter:[0x%x]\n", i0
->c_setprinter
);
188 printf("\tunknown22:[0x%x]\n", i0
->unknown22
);
189 printf("\tunknown23:[0x%x]\n", i0
->unknown23
);
190 printf("\tunknown24:[0x%x]\n", i0
->unknown24
);
191 printf("\tunknown25:[0x%x]\n", i0
->unknown25
);
192 printf("\tunknown26:[0x%x]\n", i0
->unknown26
);
193 printf("\tunknown27:[0x%x]\n", i0
->unknown27
);
194 printf("\tunknown28:[0x%x]\n", i0
->unknown28
);
195 printf("\tunknown29:[0x%x]\n", i0
->unknown29
);
200 /****************************************************************************
201 printer info level 1 display function
202 ****************************************************************************/
203 static void display_print_info_1(PRINTER_INFO_1
*i1
)
209 rpcstr_pull(desc
, i1
->description
.buffer
, sizeof(desc
), -1,
212 rpcstr_pull(name
, i1
->name
.buffer
, sizeof(name
), -1, STR_TERMINATE
);
213 rpcstr_pull(comm
, i1
->comment
.buffer
, sizeof(comm
), -1, STR_TERMINATE
);
215 printf("\tflags:[0x%x]\n", i1
->flags
);
216 printf("\tname:[%s]\n", name
);
217 printf("\tdescription:[%s]\n", desc
);
218 printf("\tcomment:[%s]\n", comm
);
223 /****************************************************************************
224 printer info level 2 display function
225 ****************************************************************************/
226 static void display_print_info_2(PRINTER_INFO_2
*i2
)
228 fstring servername
= "";
229 fstring printername
= "";
230 fstring sharename
= "";
231 fstring portname
= "";
232 fstring drivername
= "";
233 fstring comment
= "";
234 fstring location
= "";
235 fstring sepfile
= "";
236 fstring printprocessor
= "";
237 fstring datatype
= "";
238 fstring parameters
= "";
240 rpcstr_pull(servername
, i2
->servername
.buffer
,sizeof(servername
), -1, STR_TERMINATE
);
242 rpcstr_pull(printername
, i2
->printername
.buffer
,sizeof(printername
), -1, STR_TERMINATE
);
244 rpcstr_pull(sharename
, i2
->sharename
.buffer
,sizeof(sharename
), -1, STR_TERMINATE
);
246 rpcstr_pull(portname
, i2
->portname
.buffer
,sizeof(portname
), -1, STR_TERMINATE
);
248 rpcstr_pull(drivername
, i2
->drivername
.buffer
,sizeof(drivername
), -1, STR_TERMINATE
);
250 rpcstr_pull(comment
, i2
->comment
.buffer
,sizeof(comment
), -1, STR_TERMINATE
);
252 rpcstr_pull(location
, i2
->location
.buffer
,sizeof(location
), -1, STR_TERMINATE
);
254 rpcstr_pull(sepfile
, i2
->sepfile
.buffer
,sizeof(sepfile
), -1, STR_TERMINATE
);
256 rpcstr_pull(printprocessor
, i2
->printprocessor
.buffer
,sizeof(printprocessor
), -1, STR_TERMINATE
);
258 rpcstr_pull(datatype
, i2
->datatype
.buffer
,sizeof(datatype
), -1, STR_TERMINATE
);
260 rpcstr_pull(parameters
, i2
->parameters
.buffer
,sizeof(parameters
), -1, STR_TERMINATE
);
262 printf("\tservername:[%s]\n", servername
);
263 printf("\tprintername:[%s]\n", printername
);
264 printf("\tsharename:[%s]\n", sharename
);
265 printf("\tportname:[%s]\n", portname
);
266 printf("\tdrivername:[%s]\n", drivername
);
267 printf("\tcomment:[%s]\n", comment
);
268 printf("\tlocation:[%s]\n", location
);
269 printf("\tsepfile:[%s]\n", sepfile
);
270 printf("\tprintprocessor:[%s]\n", printprocessor
);
271 printf("\tdatatype:[%s]\n", datatype
);
272 printf("\tparameters:[%s]\n", parameters
);
273 printf("\tattributes:[0x%x]\n", i2
->attributes
);
274 printf("\tpriority:[0x%x]\n", i2
->priority
);
275 printf("\tdefaultpriority:[0x%x]\n", i2
->defaultpriority
);
276 printf("\tstarttime:[0x%x]\n", i2
->starttime
);
277 printf("\tuntiltime:[0x%x]\n", i2
->untiltime
);
278 printf("\tstatus:[0x%x]\n", i2
->status
);
279 printf("\tcjobs:[0x%x]\n", i2
->cjobs
);
280 printf("\taverageppm:[0x%x]\n", i2
->averageppm
);
283 display_sec_desc(i2
->secdesc
);
288 /****************************************************************************
289 printer info level 3 display function
290 ****************************************************************************/
291 static void display_print_info_3(PRINTER_INFO_3
*i3
)
293 printf("\tflags:[0x%x]\n", i3
->flags
);
295 display_sec_desc(i3
->secdesc
);
300 /****************************************************************************
301 printer info level 7 display function
302 ****************************************************************************/
303 static void display_print_info_7(PRINTER_INFO_7
*i7
)
306 rpcstr_pull(guid
, i7
->guid
.buffer
,sizeof(guid
), -1, STR_TERMINATE
);
307 printf("\tguid:[%s]\n", guid
);
308 printf("\taction:[0x%x]\n", i7
->action
);
312 /* Enumerate printers */
314 static WERROR
cmd_spoolss_enum_printers(struct cli_state
*cli
,
316 int argc
, const char **argv
)
319 uint32 info_level
= 1;
320 PRINTER_INFO_CTR ctr
;
321 uint32 i
= 0, num_printers
, needed
;
326 printf("Usage: %s [level] [name]\n", argv
[0]);
331 info_level
= atoi(argv
[1]);
334 fstrcpy(name
, argv
[2]);
336 slprintf(name
, sizeof(name
)-1, "\\\\%s", cli
->desthost
);
340 /* Enumerate printers -- Should we enumerate types other
341 than PRINTER_ENUM_LOCAL? Maybe accept as a parameter? --jerry */
345 result
= cli_spoolss_enum_printers(
346 cli
, mem_ctx
, 0, &needed
, name
, PRINTER_ENUM_LOCAL
,
347 info_level
, &num_printers
, &ctr
);
349 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
350 result
= cli_spoolss_enum_printers(
351 cli
, mem_ctx
, needed
, NULL
, name
, PRINTER_ENUM_LOCAL
,
352 info_level
, &num_printers
, &ctr
);
354 if (W_ERROR_IS_OK(result
)) {
357 printf ("No printers returned.\n");
361 for (i
= 0; i
< num_printers
; i
++) {
364 display_print_info_0(&ctr
.printers_0
[i
]);
367 display_print_info_1(&ctr
.printers_1
[i
]);
370 display_print_info_2(&ctr
.printers_2
[i
]);
373 display_print_info_3(&ctr
.printers_3
[i
]);
376 printf("unknown info level %d\n", info_level
);
386 /****************************************************************************
387 port info level 1 display function
388 ****************************************************************************/
389 static void display_port_info_1(PORT_INFO_1
*i1
)
393 rpcstr_pull(buffer
, i1
->port_name
.buffer
, sizeof(buffer
), -1, STR_TERMINATE
);
394 printf("\tPort Name:\t[%s]\n", buffer
);
397 /****************************************************************************
398 port info level 2 display function
399 ****************************************************************************/
400 static void display_port_info_2(PORT_INFO_2
*i2
)
404 rpcstr_pull(buffer
, i2
->port_name
.buffer
, sizeof(buffer
), -1, STR_TERMINATE
);
405 printf("\tPort Name:\t[%s]\n", buffer
);
406 rpcstr_pull(buffer
, i2
->monitor_name
.buffer
, sizeof(buffer
), -1, STR_TERMINATE
);
408 printf("\tMonitor Name:\t[%s]\n", buffer
);
409 rpcstr_pull(buffer
, i2
->description
.buffer
, sizeof(buffer
), -1, STR_TERMINATE
);
411 printf("\tDescription:\t[%s]\n", buffer
);
412 printf("\tPort Type:\t" );
413 if ( i2
->port_type
) {
414 int comma
= 0; /* hack */
416 if ( i2
->port_type
& PORT_TYPE_READ
) {
420 if ( i2
->port_type
& PORT_TYPE_WRITE
) {
421 printf( "%sWrite", comma
? ", " : "" );
424 /* These two have slightly different interpretations
425 on 95/98/ME but I'm disregarding that for now */
426 if ( i2
->port_type
& PORT_TYPE_REDIRECTED
) {
427 printf( "%sRedirected", comma
? ", " : "" );
430 if ( i2
->port_type
& PORT_TYPE_NET_ATTACHED
) {
431 printf( "%sNet-Attached", comma
? ", " : "" );
435 printf( "[Unset]\n" );
437 printf("\tReserved:\t[%d]\n", i2
->reserved
);
441 /* Enumerate ports */
443 static WERROR
cmd_spoolss_enum_ports(struct cli_state
*cli
,
444 TALLOC_CTX
*mem_ctx
, int argc
,
448 uint32 needed
, info_level
= 1;
453 printf("Usage: %s [level]\n", argv
[0]);
458 info_level
= atoi(argv
[1]);
460 /* Enumerate ports */
464 result
= cli_spoolss_enum_ports(cli
, mem_ctx
, 0, &needed
, info_level
,
467 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
468 result
= cli_spoolss_enum_ports(cli
, mem_ctx
, needed
, NULL
,
469 info_level
, &returned
, &ctr
);
471 if (W_ERROR_IS_OK(result
)) {
474 for (i
= 0; i
< returned
; i
++) {
475 switch (info_level
) {
477 display_port_info_1(&ctr
.port
.info_1
[i
]);
480 display_port_info_2(&ctr
.port
.info_2
[i
]);
483 printf("unknown info level %d\n", info_level
);
492 /***********************************************************************
493 * Set printer comment - use a level2 set.
495 static WERROR
cmd_spoolss_setprinter(struct cli_state
*cli
,
497 int argc
, const char **argv
)
502 uint32 info_level
= 2;
503 BOOL opened_hnd
= False
;
504 PRINTER_INFO_CTR ctr
;
510 if (argc
== 1 || argc
> 3) {
511 printf("Usage: %s printername comment\n", argv
[0]);
516 /* Open a printer handle */
518 fstrcpy(comment
, argv
[2]);
521 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
522 strupper_m(servername
);
523 fstrcpy(printername
, argv
[1]);
524 fstrcpy(user
, cli
->user_name
);
526 /* get a printer handle */
527 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
, "",
528 PRINTER_ALL_ACCESS
, servername
,
531 if (!W_ERROR_IS_OK(result
))
536 /* Get printer info */
537 result
= cli_spoolss_getprinter(cli
, mem_ctx
, 0, &needed
, &pol
, info_level
, &ctr
);
539 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
540 result
= cli_spoolss_getprinter(cli
, mem_ctx
, needed
, NULL
, &pol
, info_level
, &ctr
);
542 if (!W_ERROR_IS_OK(result
))
546 /* Modify the comment. */
547 init_unistr(&ctr
.printers_2
->comment
, comment
);
548 ctr
.printers_2
->devmode
= NULL
;
549 ctr
.printers_2
->secdesc
= NULL
;
551 result
= cli_spoolss_setprinter(cli
, mem_ctx
, &pol
, info_level
, &ctr
, 0);
552 if (W_ERROR_IS_OK(result
))
553 printf("Success in setting comment.\n");
557 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
562 /***********************************************************************
563 * Set printer name - use a level2 set.
565 static WERROR
cmd_spoolss_setprintername(struct cli_state
*cli
,
567 int argc
, const char **argv
)
572 uint32 info_level
= 2;
573 BOOL opened_hnd
= False
;
574 PRINTER_INFO_CTR ctr
;
580 if (argc
== 1 || argc
> 3) {
581 printf("Usage: %s printername new_printername\n", argv
[0]);
586 /* Open a printer handle */
588 fstrcpy(new_printername
, argv
[2]);
591 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
592 strupper_m(servername
);
593 fstrcpy(printername
, argv
[1]);
594 fstrcpy(user
, cli
->user_name
);
596 /* get a printer handle */
597 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
, "",
598 PRINTER_ALL_ACCESS
, servername
,
601 if (!W_ERROR_IS_OK(result
))
606 /* Get printer info */
607 result
= cli_spoolss_getprinter(cli
, mem_ctx
, 0, &needed
, &pol
, info_level
, &ctr
);
609 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
610 result
= cli_spoolss_getprinter(cli
, mem_ctx
, needed
, NULL
, &pol
, info_level
, &ctr
);
612 if (!W_ERROR_IS_OK(result
))
616 /* Modify the printername. */
617 init_unistr(&ctr
.printers_2
->printername
, new_printername
);
618 ctr
.printers_2
->devmode
= NULL
;
619 ctr
.printers_2
->secdesc
= NULL
;
621 result
= cli_spoolss_setprinter(cli
, mem_ctx
, &pol
, info_level
, &ctr
, 0);
622 if (W_ERROR_IS_OK(result
))
623 printf("Success in setting printername.\n");
627 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
632 /***********************************************************************
633 * Get printer information
635 static WERROR
cmd_spoolss_getprinter(struct cli_state
*cli
,
637 int argc
, const char **argv
)
641 uint32 info_level
= 1;
642 BOOL opened_hnd
= False
;
643 PRINTER_INFO_CTR ctr
;
649 if (argc
== 1 || argc
> 3) {
650 printf("Usage: %s <printername> [level]\n", argv
[0]);
654 /* Open a printer handle */
656 info_level
= atoi(argv
[2]);
659 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
660 strupper_m(servername
);
661 slprintf(printername
, sizeof(printername
)-1, "%s\\%s", servername
, argv
[1]);
662 fstrcpy(user
, cli
->user_name
);
664 /* get a printer handle */
666 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
667 "", MAXIMUM_ALLOWED_ACCESS
,
668 servername
, user
, &pol
);
670 if (!W_ERROR_IS_OK(result
))
675 /* Get printer info */
677 result
= cli_spoolss_getprinter(cli
, mem_ctx
, 0, &needed
,
678 &pol
, info_level
, &ctr
);
680 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
681 result
= cli_spoolss_getprinter(
682 cli
, mem_ctx
, needed
, NULL
, &pol
, info_level
, &ctr
);
684 if (!W_ERROR_IS_OK(result
))
687 /* Display printer info */
689 switch (info_level
) {
691 display_print_info_0(ctr
.printers_0
);
694 display_print_info_1(ctr
.printers_1
);
697 display_print_info_2(ctr
.printers_2
);
700 display_print_info_3(ctr
.printers_3
);
703 display_print_info_7(ctr
.printers_7
);
706 printf("unknown info level %d\n", info_level
);
712 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
717 static void display_reg_value(REGISTRY_VALUE value
)
723 printf("%s: REG_DWORD: 0x%08x\n", value
.valuename
,
724 *((uint32
*) value
.data_p
));
727 rpcstr_pull(text
, value
.data_p
, sizeof(text
), value
.size
,
729 printf("%s: REG_SZ: %s\n", value
.valuename
, text
);
732 printf("%s: REG_BINARY: unknown length value not displayed\n",
736 uint16
*curstr
= (uint16
*) value
.data_p
;
737 uint8
*start
= value
.data_p
;
738 printf("%s: REG_MULTI_SZ:\n", value
.valuename
);
739 while ((*curstr
!= 0) &&
740 ((uint8
*) curstr
< start
+ value
.size
)) {
741 rpcstr_pull(text
, curstr
, sizeof(text
), -1,
743 printf(" %s\n", text
);
744 curstr
+= strlen(text
) + 1;
749 printf("%s: unknown type %d\n", value
.valuename
, value
.type
);
754 /***********************************************************************
757 static WERROR
cmd_spoolss_getprinterdata(struct cli_state
*cli
,
759 int argc
, const char **argv
)
763 BOOL opened_hnd
= False
;
768 const char *valuename
;
769 REGISTRY_VALUE value
;
772 printf("Usage: %s <printername> <valuename>\n", argv
[0]);
773 printf("<printername> of . queries print server\n");
778 /* Open a printer handle */
780 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
781 strupper_m(servername
);
782 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
783 fstrcpy(printername
, servername
);
785 slprintf(printername
, sizeof(servername
)-1, "%s\\%s",
786 servername
, argv
[1]);
787 fstrcpy(user
, cli
->user_name
);
789 /* get a printer handle */
791 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
792 "", MAXIMUM_ALLOWED_ACCESS
,
793 servername
, user
, &pol
);
795 if (!W_ERROR_IS_OK(result
))
800 /* Get printer info */
802 result
= cli_spoolss_getprinterdata(cli
, mem_ctx
, 0, &needed
,
803 &pol
, valuename
, &value
);
805 if (W_ERROR_V(result
) == ERRmoredata
)
806 result
= cli_spoolss_getprinterdata(
807 cli
, mem_ctx
, needed
, NULL
, &pol
, valuename
, &value
);
809 if (!W_ERROR_IS_OK(result
))
812 /* Display printer data */
814 fstrcpy(value
.valuename
, valuename
);
815 display_reg_value(value
);
820 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
825 /***********************************************************************
828 static WERROR
cmd_spoolss_getprinterdataex(struct cli_state
*cli
,
830 int argc
, const char **argv
)
834 BOOL opened_hnd
= False
;
839 const char *valuename
, *keyname
;
840 REGISTRY_VALUE value
;
843 printf("Usage: %s <printername> <keyname> <valuename>\n",
845 printf("<printername> of . queries print server\n");
851 /* Open a printer handle */
853 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
854 strupper_m(servername
);
855 if (strncmp(argv
[1], ".", sizeof(".")) == 0)
856 fstrcpy(printername
, servername
);
858 slprintf(printername
, sizeof(printername
)-1, "%s\\%s",
859 servername
, argv
[1]);
860 fstrcpy(user
, cli
->user_name
);
862 /* get a printer handle */
864 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
865 "", MAXIMUM_ALLOWED_ACCESS
,
866 servername
, user
, &pol
);
868 if (!W_ERROR_IS_OK(result
))
873 /* Get printer info */
875 result
= cli_spoolss_getprinterdataex(cli
, mem_ctx
, 0, &needed
,
876 &pol
, keyname
, valuename
,
879 if (W_ERROR_V(result
) == ERRmoredata
)
880 result
= cli_spoolss_getprinterdataex(cli
, mem_ctx
, needed
,
884 if (!W_ERROR_IS_OK(result
))
887 /* Display printer data */
889 fstrcpy(value
.valuename
, valuename
);
890 display_reg_value(value
);
895 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
900 /****************************************************************************
901 printer info level 0 display function
902 ****************************************************************************/
903 static void display_print_driver_1(DRIVER_INFO_1
*i1
)
909 rpcstr_pull(name
, i1
->name
.buffer
, sizeof(name
), -1, STR_TERMINATE
);
911 printf ("Printer Driver Info 1:\n");
912 printf ("\tDriver Name: [%s]\n\n", name
);
917 /****************************************************************************
918 printer info level 1 display function
919 ****************************************************************************/
920 static void display_print_driver_2(DRIVER_INFO_2
*i1
)
923 fstring architecture
;
930 rpcstr_pull(name
, i1
->name
.buffer
, sizeof(name
), -1, STR_TERMINATE
);
931 rpcstr_pull(architecture
, i1
->architecture
.buffer
, sizeof(architecture
), -1, STR_TERMINATE
);
932 rpcstr_pull(driverpath
, i1
->driverpath
.buffer
, sizeof(driverpath
), -1, STR_TERMINATE
);
933 rpcstr_pull(datafile
, i1
->datafile
.buffer
, sizeof(datafile
), -1, STR_TERMINATE
);
934 rpcstr_pull(configfile
, i1
->configfile
.buffer
, sizeof(configfile
), -1, STR_TERMINATE
);
936 printf ("Printer Driver Info 2:\n");
937 printf ("\tVersion: [%x]\n", i1
->version
);
938 printf ("\tDriver Name: [%s]\n", name
);
939 printf ("\tArchitecture: [%s]\n", architecture
);
940 printf ("\tDriver Path: [%s]\n", driverpath
);
941 printf ("\tDatafile: [%s]\n", datafile
);
942 printf ("\tConfigfile: [%s]\n\n", configfile
);
947 /****************************************************************************
948 printer info level 2 display function
949 ****************************************************************************/
950 static void display_print_driver_3(DRIVER_INFO_3
*i1
)
953 fstring architecture
= "";
954 fstring driverpath
= "";
955 fstring datafile
= "";
956 fstring configfile
= "";
957 fstring helpfile
= "";
958 fstring dependentfiles
= "";
959 fstring monitorname
= "";
960 fstring defaultdatatype
= "";
968 rpcstr_pull(name
, i1
->name
.buffer
, sizeof(name
), -1, STR_TERMINATE
);
969 rpcstr_pull(architecture
, i1
->architecture
.buffer
, sizeof(architecture
), -1, STR_TERMINATE
);
970 rpcstr_pull(driverpath
, i1
->driverpath
.buffer
, sizeof(driverpath
), -1, STR_TERMINATE
);
971 rpcstr_pull(datafile
, i1
->datafile
.buffer
, sizeof(datafile
), -1, STR_TERMINATE
);
972 rpcstr_pull(configfile
, i1
->configfile
.buffer
, sizeof(configfile
), -1, STR_TERMINATE
);
973 rpcstr_pull(helpfile
, i1
->helpfile
.buffer
, sizeof(helpfile
), -1, STR_TERMINATE
);
974 rpcstr_pull(monitorname
, i1
->monitorname
.buffer
, sizeof(monitorname
), -1, STR_TERMINATE
);
975 rpcstr_pull(defaultdatatype
, i1
->defaultdatatype
.buffer
, sizeof(defaultdatatype
), -1, STR_TERMINATE
);
977 printf ("Printer Driver Info 3:\n");
978 printf ("\tVersion: [%x]\n", i1
->version
);
979 printf ("\tDriver Name: [%s]\n",name
);
980 printf ("\tArchitecture: [%s]\n", architecture
);
981 printf ("\tDriver Path: [%s]\n", driverpath
);
982 printf ("\tDatafile: [%s]\n", datafile
);
983 printf ("\tConfigfile: [%s]\n", configfile
);
984 printf ("\tHelpfile: [%s]\n\n", helpfile
);
988 rpcstr_pull(dependentfiles
, i1
->dependentfiles
+length
, sizeof(dependentfiles
), -1, STR_TERMINATE
);
990 length
+=strlen(dependentfiles
)+1;
992 if (strlen(dependentfiles
) > 0)
994 printf ("\tDependentfiles: [%s]\n", dependentfiles
);
1004 printf ("\tMonitorname: [%s]\n", monitorname
);
1005 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype
);
1010 /***********************************************************************
1011 * Get printer information
1013 static WERROR
cmd_spoolss_getdriver(struct cli_state
*cli
,
1014 TALLOC_CTX
*mem_ctx
,
1015 int argc
, const char **argv
)
1019 uint32 info_level
= 3;
1020 BOOL opened_hnd
= False
;
1021 PRINTER_DRIVER_CTR ctr
;
1022 fstring printername
,
1026 BOOL success
= False
;
1028 if ((argc
== 1) || (argc
> 3))
1030 printf("Usage: %s <printername> [level]\n", argv
[0]);
1034 /* get the arguments need to open the printer handle */
1035 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
1036 strupper_m(servername
);
1037 fstrcpy(user
, cli
->user_name
);
1038 fstrcpy(printername
, argv
[1]);
1040 info_level
= atoi(argv
[2]);
1042 /* Open a printer handle */
1044 werror
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
, "",
1046 servername
, user
, &pol
);
1048 if (!W_ERROR_IS_OK(werror
)) {
1049 printf("Error opening printer handle for %s!\n", printername
);
1055 /* loop through and print driver info level for each architecture */
1057 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1060 werror
= cli_spoolss_getprinterdriver(
1061 cli
, mem_ctx
, 0, &needed
, &pol
, info_level
,
1062 archi_table
[i
].long_archi
, archi_table
[i
].version
,
1065 if (W_ERROR_V(werror
) == ERRinsufficientbuffer
) {
1066 werror
= cli_spoolss_getprinterdriver(
1067 cli
, mem_ctx
, needed
, NULL
, &pol
, info_level
,
1068 archi_table
[i
].long_archi
, archi_table
[i
].version
,
1072 if (!W_ERROR_IS_OK(werror
))
1075 /* need at least one success */
1079 printf ("\n[%s]\n", archi_table
[i
].long_archi
);
1081 switch (info_level
) {
1083 display_print_driver_1 (ctr
.info1
);
1086 display_print_driver_2 (ctr
.info2
);
1089 display_print_driver_3 (ctr
.info3
);
1092 printf("unknown info level %d\n", info_level
);
1100 cli_spoolss_close_printer (cli
, mem_ctx
, &pol
);
1108 /***********************************************************************
1109 * Get printer information
1111 static WERROR
cmd_spoolss_enum_drivers(struct cli_state
*cli
,
1112 TALLOC_CTX
*mem_ctx
,
1113 int argc
, const char **argv
)
1116 uint32 info_level
= 1;
1117 PRINTER_DRIVER_CTR ctr
;
1123 printf("Usage: enumdrivers [level]\n");
1128 info_level
= atoi(argv
[1]);
1131 /* loop through and print driver info level for each architecture */
1132 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++)
1136 werror
= cli_spoolss_enumprinterdrivers(
1137 cli
, mem_ctx
, 0, &needed
, info_level
,
1138 archi_table
[i
].long_archi
, &returned
, &ctr
);
1140 if (W_ERROR_V(werror
) == ERRinsufficientbuffer
)
1141 werror
= cli_spoolss_enumprinterdrivers(
1142 cli
, mem_ctx
, needed
, NULL
, info_level
,
1143 archi_table
[i
].long_archi
, &returned
, &ctr
);
1145 if (W_ERROR_V(werror
) == W_ERROR_V(WERR_INVALID_ENVIRONMENT
)) {
1146 printf ("Server does not support environment [%s]\n",
1147 archi_table
[i
].long_archi
);
1155 if (!W_ERROR_IS_OK(werror
)) {
1156 printf ("Error getting driver for environment [%s] - %d\n",
1157 archi_table
[i
].long_archi
, W_ERROR_V(werror
));
1161 printf ("\n[%s]\n", archi_table
[i
].long_archi
);
1166 for (j
=0; j
< returned
; j
++) {
1167 display_print_driver_1 (&(ctr
.info1
[j
]));
1171 for (j
=0; j
< returned
; j
++) {
1172 display_print_driver_2 (&(ctr
.info2
[j
]));
1176 for (j
=0; j
< returned
; j
++) {
1177 display_print_driver_3 (&(ctr
.info3
[j
]));
1181 printf("unknown info level %d\n", info_level
);
1189 /****************************************************************************
1190 printer info level 1 display function
1191 ****************************************************************************/
1192 static void display_printdriverdir_1(DRIVER_DIRECTORY_1
*i1
)
1198 rpcstr_pull(name
, i1
->name
.buffer
, sizeof(name
), -1, STR_TERMINATE
);
1200 printf ("\tDirectory Name:[%s]\n", name
);
1203 /***********************************************************************
1204 * Get printer driver directory information
1206 static WERROR
cmd_spoolss_getdriverdir(struct cli_state
*cli
,
1207 TALLOC_CTX
*mem_ctx
,
1208 int argc
, const char **argv
)
1212 DRIVER_DIRECTORY_CTR ctr
;
1216 printf("Usage: %s [environment]\n", argv
[0]);
1220 /* Get the arguments need to open the printer handle */
1223 fstrcpy (env
, argv
[1]);
1225 fstrcpy (env
, "Windows NT x86");
1227 /* Get the directory. Only use Info level 1 */
1229 result
= cli_spoolss_getprinterdriverdir(
1230 cli
, mem_ctx
, 0, &needed
, 1, env
, &ctr
);
1232 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
1233 result
= cli_spoolss_getprinterdriverdir(
1234 cli
, mem_ctx
, needed
, NULL
, 1, env
, &ctr
);
1236 if (W_ERROR_IS_OK(result
))
1237 display_printdriverdir_1(ctr
.info1
);
1242 /*******************************************************************************
1243 set the version and environment fields of a DRIVER_INFO_3 struct
1244 ******************************************************************************/
1245 void set_drv_info_3_env (DRIVER_INFO_3
*info
, const char *arch
)
1250 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1252 if (strcmp(arch
, archi_table
[i
].short_archi
) == 0)
1254 info
->version
= archi_table
[i
].version
;
1255 init_unistr (&info
->architecture
, archi_table
[i
].long_archi
);
1260 if (archi_table
[i
].long_archi
== NULL
)
1262 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch
));
1269 /**************************************************************************
1270 wrapper for strtok to get the next parameter from a delimited list.
1271 Needed to handle the empty parameter string denoted by "NULL"
1272 *************************************************************************/
1273 static char* get_driver_3_param (const char* str
, const char* delim
, UNISTR
* dest
)
1277 /* get the next token */
1278 ptr
= strtok(str
, delim
);
1280 /* a string of 'NULL' is used to represent an empty
1281 parameter because two consecutive delimiters
1282 will not return an empty string. See man strtok(3)
1284 if (ptr
&& (StrCaseCmp(ptr
, "NULL") == 0))
1288 init_unistr(dest
, ptr
);
1293 /********************************************************************************
1294 fill in the members of a DRIVER_INFO_3 struct using a character
1295 string in the form of
1296 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1297 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1298 <Default Data Type>:<Comma Separated list of Files>
1299 *******************************************************************************/
1300 static BOOL
init_drv_info_3_members (
1301 TALLOC_CTX
*mem_ctx
,
1302 DRIVER_INFO_3
*info
,
1309 /* fill in the UNISTR fields */
1310 str
= get_driver_3_param (args
, ":", &info
->name
);
1311 str
= get_driver_3_param (NULL
, ":", &info
->driverpath
);
1312 str
= get_driver_3_param (NULL
, ":", &info
->datafile
);
1313 str
= get_driver_3_param (NULL
, ":", &info
->configfile
);
1314 str
= get_driver_3_param (NULL
, ":", &info
->helpfile
);
1315 str
= get_driver_3_param (NULL
, ":", &info
->monitorname
);
1316 str
= get_driver_3_param (NULL
, ":", &info
->defaultdatatype
);
1318 /* <Comma Separated List of Dependent Files> */
1319 str2
= get_driver_3_param (NULL
, ":", NULL
); /* save the beginning of the string */
1322 /* begin to strip out each filename */
1323 str
= strtok(str
, ",");
1327 /* keep a cumlative count of the str lengths */
1328 len
+= strlen(str
)+1;
1329 str
= strtok(NULL
, ",");
1332 /* allocate the space; add one extra slot for a terminating NULL.
1333 Each filename is NULL terminated and the end contains a double
1335 if ((info
->dependentfiles
=(uint16
*)talloc(mem_ctx
, (len
+1)*sizeof(uint16
))) == NULL
)
1337 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1340 for (i
=0; i
<len
; i
++)
1342 SSVAL(&info
->dependentfiles
[i
], 0, str2
[i
]);
1344 info
->dependentfiles
[len
] = '\0';
1350 static WERROR
cmd_spoolss_addprinterdriver(struct cli_state
*cli
,
1351 TALLOC_CTX
*mem_ctx
,
1352 int argc
, const char **argv
)
1356 PRINTER_DRIVER_CTR ctr
;
1357 DRIVER_INFO_3 info3
;
1359 fstring driver_name
;
1361 /* parse the command arguements */
1362 if (argc
!= 3 && argc
!= 4)
1364 printf ("Usage: %s <Environment> \\\n", argv
[0]);
1365 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1366 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1367 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1368 printf ("\t[version]\n");
1373 /* Fill in the DRIVER_INFO_3 struct */
1375 if (!(arch
= cmd_spoolss_get_short_archi(argv
[1])))
1377 printf ("Error Unknown architechture [%s]\n", argv
[1]);
1378 return WERR_INVALID_PARAM
;
1381 set_drv_info_3_env(&info3
, arch
);
1383 if (!init_drv_info_3_members(mem_ctx
, &info3
, argv
[2]))
1385 printf ("Error Invalid parameter list - %s.\n", argv
[2]);
1386 return WERR_INVALID_PARAM
;
1389 /* if printer driver version specified, override the default version
1390 * used by the architecture. This allows installation of Windows
1391 * 2000 (version 3) printer drivers. */
1394 info3
.version
= atoi(argv
[3]);
1399 result
= cli_spoolss_addprinterdriver (cli
, mem_ctx
, level
, &ctr
);
1401 if (W_ERROR_IS_OK(result
)) {
1402 rpcstr_pull(driver_name
, info3
.name
.buffer
,
1403 sizeof(driver_name
), -1, STR_TERMINATE
);
1404 printf ("Printer Driver %s successfully installed.\n",
1412 static WERROR
cmd_spoolss_addprinterex(struct cli_state
*cli
,
1413 TALLOC_CTX
*mem_ctx
,
1414 int argc
, const char **argv
)
1418 PRINTER_INFO_CTR ctr
;
1419 PRINTER_INFO_2 info2
;
1422 /* parse the command arguements */
1425 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv
[0]);
1429 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
1430 strupper_m(servername
);
1432 /* Fill in the DRIVER_INFO_2 struct */
1435 init_unistr( &info2
.servername
, servername
);
1437 init_unistr( &info2
.printername
, argv
[1]);
1438 init_unistr( &info2
.sharename
, argv
[2]);
1439 init_unistr( &info2
.drivername
, argv
[3]);
1440 init_unistr( &info2
.portname
, argv
[4]);
1441 init_unistr( &info2
.comment
, "Created by rpcclient");
1442 init_unistr( &info2
.printprocessor
, "winprint");
1443 init_unistr( &info2
.datatype
, "RAW");
1444 info2
.devmode
= NULL
;
1445 info2
.secdesc
= NULL
;
1446 info2
.attributes
= PRINTER_ATTRIBUTE_SHARED
;
1448 info2
.defaultpriority
= 0;
1449 info2
.starttime
= 0;
1450 info2
.untiltime
= 0;
1452 /* These three fields must not be used by AddPrinter()
1453 as defined in the MS Platform SDK documentation..
1457 info2.averageppm = 0;
1460 ctr
.printers_2
= &info2
;
1461 result
= cli_spoolss_addprinterex (cli
, mem_ctx
, level
, &ctr
);
1463 if (W_ERROR_IS_OK(result
))
1464 printf ("Printer %s successfully installed.\n", argv
[1]);
1469 static WERROR
cmd_spoolss_setdriver(struct cli_state
*cli
,
1470 TALLOC_CTX
*mem_ctx
,
1471 int argc
, const char **argv
)
1476 BOOL opened_hnd
= False
;
1477 PRINTER_INFO_CTR ctr
;
1478 PRINTER_INFO_2 info2
;
1484 /* parse the command arguements */
1487 printf ("Usage: %s <printer> <driver>\n", argv
[0]);
1491 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
1492 strupper_m(servername
);
1493 slprintf(printername
, sizeof(printername
)-1, "%s\\%s", servername
, argv
[1]);
1494 fstrcpy(user
, cli
->user_name
);
1496 /* Get a printer handle */
1498 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
, "",
1500 servername
, user
, &pol
);
1502 if (!W_ERROR_IS_OK(result
))
1507 /* Get printer info */
1509 ZERO_STRUCT (info2
);
1510 ctr
.printers_2
= &info2
;
1512 result
= cli_spoolss_getprinter(cli
, mem_ctx
, 0, &needed
,
1515 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
1516 result
= cli_spoolss_getprinter(
1517 cli
, mem_ctx
, needed
, NULL
, &pol
, level
, &ctr
);
1519 if (!W_ERROR_IS_OK(result
)) {
1520 printf ("Unable to retrieve printer information!\n");
1524 /* Set the printer driver */
1526 init_unistr(&ctr
.printers_2
->drivername
, argv
[2]);
1528 result
= cli_spoolss_setprinter(cli
, mem_ctx
, &pol
, level
, &ctr
, 0);
1530 if (!W_ERROR_IS_OK(result
)) {
1531 printf("SetPrinter call failed!\n");
1535 printf("Succesfully set %s to driver %s.\n", argv
[1], argv
[2]);
1541 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
1547 static WERROR
cmd_spoolss_deletedriver(struct cli_state
*cli
,
1548 TALLOC_CTX
*mem_ctx
,
1549 int argc
, const char **argv
)
1555 /* parse the command arguements */
1558 printf ("Usage: %s <driver>\n", argv
[0]);
1562 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
1563 strupper_m(servername
);
1565 /* delete the driver for all architectures */
1566 for (i
=0; archi_table
[i
].long_archi
; i
++)
1568 /* make the call to remove the driver */
1569 result
= cli_spoolss_deleteprinterdriver(
1570 cli
, mem_ctx
, archi_table
[i
].long_archi
, argv
[1]);
1572 if ( !W_ERROR_IS_OK(result
) ) {
1573 if ( !W_ERROR_EQUAL(result
, WERR_UNKNOWN_PRINTER_DRIVER
) ) {
1574 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1575 argv
[1], archi_table
[i
].long_archi
,
1581 printf ("Driver %s removed for arch [%s].\n", argv
[1],
1582 archi_table
[i
].long_archi
);
1589 static WERROR
cmd_spoolss_getprintprocdir(struct cli_state
*cli
,
1590 TALLOC_CTX
*mem_ctx
,
1591 int argc
, const char **argv
)
1594 char *servername
= NULL
, *environment
= NULL
;
1598 /* parse the command arguements */
1600 printf ("Usage: %s [environment]\n", argv
[0]);
1604 if (asprintf(&servername
, "\\\\%s", cli
->desthost
) < 0)
1606 strupper_m(servername
);
1608 if (asprintf(&environment
, "%s", (argc
== 2) ? argv
[1] :
1609 PRINTER_DRIVER_ARCHITECTURE
) < 0) {
1610 SAFE_FREE(servername
);
1614 result
= cli_spoolss_getprintprocessordirectory(
1615 cli
, mem_ctx
, 0, &needed
, servername
, environment
, procdir
);
1617 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
1618 result
= cli_spoolss_getprintprocessordirectory(
1619 cli
, mem_ctx
, needed
, NULL
, servername
, environment
,
1622 if (W_ERROR_IS_OK(result
))
1623 printf("%s\n", procdir
);
1625 SAFE_FREE(servername
);
1626 SAFE_FREE(environment
);
1633 static WERROR
cmd_spoolss_addform(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
1634 int argc
, const char **argv
)
1638 char *servername
= NULL
, *printername
= NULL
;
1640 BOOL got_handle
= False
;
1642 /* Parse the command arguements */
1645 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
1649 /* Get a printer handle */
1651 asprintf(&servername
, "\\\\%s", cli
->desthost
);
1652 strupper_m(servername
);
1653 asprintf(&printername
, "%s\\%s", servername
, argv
[1]);
1655 werror
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
, "",
1656 MAXIMUM_ALLOWED_ACCESS
,
1657 servername
, cli
->user_name
, &handle
);
1659 if (!W_ERROR_IS_OK(werror
))
1664 /* Dummy up some values for the form data */
1666 form
.flags
= FORM_USER
;
1667 form
.size_x
= form
.size_y
= 100;
1673 init_unistr2(&form
.name
, argv
[2], UNI_STR_TERMINATE
);
1678 werror
= cli_spoolss_addform(cli
, mem_ctx
, &handle
, 1, &form
);
1682 cli_spoolss_close_printer(cli
, mem_ctx
, &handle
);
1684 SAFE_FREE(servername
);
1685 SAFE_FREE(printername
);
1692 static WERROR
cmd_spoolss_setform(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
1693 int argc
, const char **argv
)
1697 char *servername
= NULL
, *printername
= NULL
;
1699 BOOL got_handle
= False
;
1701 /* Parse the command arguements */
1704 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
1708 /* Get a printer handle */
1710 asprintf(&servername
, "\\\\%s", cli
->desthost
);
1711 strupper_m(servername
);
1712 asprintf(&printername
, "%s\\%s", servername
, argv
[1]);
1714 werror
= cli_spoolss_open_printer_ex(
1715 cli
, mem_ctx
, printername
, "", MAXIMUM_ALLOWED_ACCESS
,
1716 servername
, cli
->user_name
, &handle
);
1718 if (!W_ERROR_IS_OK(werror
))
1723 /* Dummy up some values for the form data */
1725 form
.flags
= FORM_PRINTER
;
1726 form
.size_x
= form
.size_y
= 100;
1732 init_unistr2(&form
.name
, argv
[2], UNI_STR_TERMINATE
);
1736 werror
= cli_spoolss_setform(cli
, mem_ctx
, &handle
, 1, argv
[2], &form
);
1740 cli_spoolss_close_printer(cli
, mem_ctx
, &handle
);
1742 SAFE_FREE(servername
);
1743 SAFE_FREE(printername
);
1750 static WERROR
cmd_spoolss_getform(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
1751 int argc
, const char **argv
)
1755 char *servername
= NULL
, *printername
= NULL
;
1757 BOOL got_handle
= False
;
1760 /* Parse the command arguements */
1763 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
1767 /* Get a printer handle */
1769 asprintf(&servername
, "\\\\%s", cli
->desthost
);
1770 strupper_m(servername
);
1771 asprintf(&printername
, "%s\\%s", servername
, argv
[1]);
1773 werror
= cli_spoolss_open_printer_ex(
1774 cli
, mem_ctx
, printername
, "", MAXIMUM_ALLOWED_ACCESS
,
1775 servername
, cli
->user_name
, &handle
);
1777 if (!W_ERROR_IS_OK(werror
))
1784 werror
= cli_spoolss_getform(cli
, mem_ctx
, 0, &needed
,
1785 &handle
, argv
[2], 1, &form
);
1787 if (W_ERROR_V(werror
) == ERRinsufficientbuffer
)
1788 werror
= cli_spoolss_getform(cli
, mem_ctx
, needed
, NULL
,
1789 &handle
, argv
[2], 1, &form
);
1791 if (!W_ERROR_IS_OK(werror
))
1794 printf("width: %d\n", form
.width
);
1795 printf("length: %d\n", form
.length
);
1796 printf("left: %d\n", form
.left
);
1797 printf("top: %d\n", form
.top
);
1798 printf("right: %d\n", form
.right
);
1799 printf("bottom: %d\n", form
.bottom
);
1803 cli_spoolss_close_printer(cli
, mem_ctx
, &handle
);
1805 SAFE_FREE(servername
);
1806 SAFE_FREE(printername
);
1813 static WERROR
cmd_spoolss_deleteform(struct cli_state
*cli
,
1814 TALLOC_CTX
*mem_ctx
, int argc
,
1819 char *servername
= NULL
, *printername
= NULL
;
1820 BOOL got_handle
= False
;
1822 /* Parse the command arguements */
1825 printf ("Usage: %s <printer> <formname>\n", argv
[0]);
1829 /* Get a printer handle */
1831 asprintf(&servername
, "\\\\%s", cli
->desthost
);
1832 strupper_m(servername
);
1833 asprintf(&printername
, "%s\\%s", servername
, argv
[1]);
1835 werror
= cli_spoolss_open_printer_ex(
1836 cli
, mem_ctx
, printername
, "", MAXIMUM_ALLOWED_ACCESS
,
1837 servername
, cli
->user_name
, &handle
);
1839 if (!W_ERROR_IS_OK(werror
))
1844 /* Delete the form */
1846 werror
= cli_spoolss_deleteform(cli
, mem_ctx
, &handle
, argv
[2]);
1850 cli_spoolss_close_printer(cli
, mem_ctx
, &handle
);
1852 SAFE_FREE(servername
);
1853 SAFE_FREE(printername
);
1858 /* Enumerate forms */
1860 static WERROR
cmd_spoolss_enum_forms(struct cli_state
*cli
,
1861 TALLOC_CTX
*mem_ctx
, int argc
,
1866 char *servername
= NULL
, *printername
= NULL
;
1867 BOOL got_handle
= False
;
1868 uint32 needed
, num_forms
, level
= 1, i
;
1871 /* Parse the command arguements */
1874 printf ("Usage: %s <printer>\n", argv
[0]);
1878 /* Get a printer handle */
1880 asprintf(&servername
, "\\\\%s", cli
->desthost
);
1881 strupper_m(servername
);
1882 asprintf(&printername
, "%s\\%s", servername
, argv
[1]);
1884 werror
= cli_spoolss_open_printer_ex(
1885 cli
, mem_ctx
, printername
, "", MAXIMUM_ALLOWED_ACCESS
,
1886 servername
, cli
->user_name
, &handle
);
1888 if (!W_ERROR_IS_OK(werror
))
1893 /* Enumerate forms */
1895 werror
= cli_spoolss_enumforms(
1896 cli
, mem_ctx
, 0, &needed
, &handle
, level
, &num_forms
, &forms
);
1898 if (W_ERROR_V(werror
) == ERRinsufficientbuffer
)
1899 werror
= cli_spoolss_enumforms(
1900 cli
, mem_ctx
, needed
, NULL
, &handle
, level
,
1901 &num_forms
, &forms
);
1903 if (!W_ERROR_IS_OK(werror
))
1906 /* Display output */
1908 for (i
= 0; i
< num_forms
; i
++) {
1911 if (forms
[i
].name
.buffer
)
1912 rpcstr_pull(form_name
, forms
[i
].name
.buffer
,
1913 sizeof(form_name
), -1, STR_TERMINATE
);
1915 printf("%s\n", form_name
);
1920 cli_spoolss_close_printer(cli
, mem_ctx
, &handle
);
1922 SAFE_FREE(servername
);
1923 SAFE_FREE(printername
);
1928 static WERROR
cmd_spoolss_setprinterdata(struct cli_state
*cli
,
1929 TALLOC_CTX
*mem_ctx
,
1930 int argc
, const char **argv
)
1934 fstring servername
, printername
, user
;
1936 BOOL opened_hnd
= False
;
1937 PRINTER_INFO_CTR ctr
;
1938 PRINTER_INFO_0 info
;
1939 REGISTRY_VALUE value
;
1942 /* parse the command arguements */
1944 printf ("Usage: %s <printer> <value> <data>\n", argv
[0]);
1948 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
1949 strupper_m(servername
);
1950 slprintf(printername
, sizeof(servername
)-1, "%s\\%s", servername
, argv
[1]);
1951 fstrcpy(user
, cli
->user_name
);
1953 /* get a printer handle */
1954 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
, "",
1955 MAXIMUM_ALLOWED_ACCESS
, servername
,
1957 if (!W_ERROR_IS_OK(result
))
1962 ctr
.printers_0
= &info
;
1964 result
= cli_spoolss_getprinter(cli
, mem_ctx
, 0, &needed
,
1967 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
1968 result
= cli_spoolss_getprinter(cli
, mem_ctx
, needed
, NULL
, &pol
, 0, &ctr
);
1970 if (!W_ERROR_IS_OK(result
))
1973 printf("%s\n", timestring(True
));
1974 printf("\tchange_id (before set)\t:[0x%x]\n", info
.change_id
);
1976 /* Set the printer data */
1978 init_unistr2(&data
, argv
[3], UNI_STR_TERMINATE
);
1979 fstrcpy(value
.valuename
, argv
[2]);
1980 value
.type
= REG_SZ
;
1981 value
.size
= data
.uni_str_len
* 2;
1982 value
.data_p
= talloc_memdup(mem_ctx
, data
.buffer
, value
.size
);
1984 result
= cli_spoolss_setprinterdata(cli
, mem_ctx
, &pol
, &value
);
1986 if (!W_ERROR_IS_OK(result
)) {
1987 printf ("Unable to set [%s=%s]!\n", argv
[2], argv
[3]);
1990 printf("\tSetPrinterData succeeded [%s: %s]\n", argv
[2], argv
[3]);
1992 result
= cli_spoolss_getprinter(cli
, mem_ctx
, 0, &needed
, &pol
, 0, &ctr
);
1994 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
1995 result
= cli_spoolss_getprinter(cli
, mem_ctx
, needed
, NULL
, &pol
, 0, &ctr
);
1997 if (!W_ERROR_IS_OK(result
))
2000 printf("%s\n", timestring(True
));
2001 printf("\tchange_id (after set)\t:[0x%x]\n", info
.change_id
);
2006 cli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
2011 static void display_job_info_1(JOB_INFO_1
*job
)
2013 fstring username
= "", document
= "", text_status
= "";
2015 rpcstr_pull(username
, job
->username
.buffer
,
2016 sizeof(username
), -1, STR_TERMINATE
);
2018 rpcstr_pull(document
, job
->document
.buffer
,
2019 sizeof(document
), -1, STR_TERMINATE
);
2021 rpcstr_pull(text_status
, job
->text_status
.buffer
,
2022 sizeof(text_status
), -1, STR_TERMINATE
);
2024 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job
->position
, job
->jobid
,
2025 username
, document
, text_status
, job
->pagesprinted
,
2029 static void display_job_info_2(JOB_INFO_2
*job
)
2031 fstring username
= "", document
= "", text_status
= "";
2033 rpcstr_pull(username
, job
->username
.buffer
,
2034 sizeof(username
), -1, STR_TERMINATE
);
2036 rpcstr_pull(document
, job
->document
.buffer
,
2037 sizeof(document
), -1, STR_TERMINATE
);
2039 rpcstr_pull(text_status
, job
->text_status
.buffer
,
2040 sizeof(text_status
), -1, STR_TERMINATE
);
2042 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job
->position
, job
->jobid
,
2043 username
, document
, text_status
, job
->pagesprinted
,
2044 job
->totalpages
, job
->size
);
2047 /* Enumerate jobs */
2049 static WERROR
cmd_spoolss_enum_jobs(struct cli_state
*cli
,
2050 TALLOC_CTX
*mem_ctx
, int argc
,
2054 uint32 needed
, level
= 1, num_jobs
, i
;
2055 BOOL got_hnd
= False
;
2056 pstring printername
;
2057 fstring servername
, user
;
2061 if (argc
< 2 || argc
> 3) {
2062 printf("Usage: %s printername [level]\n", argv
[0]);
2067 level
= atoi(argv
[2]);
2069 /* Open printer handle */
2071 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
2072 strupper_m(servername
);
2073 fstrcpy(user
, cli
->user_name
);
2074 slprintf(printername
, sizeof(servername
)-1, "\\\\%s\\", cli
->desthost
);
2075 strupper_m(printername
);
2076 pstrcat(printername
, argv
[1]);
2078 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
2079 "", MAXIMUM_ALLOWED_ACCESS
,
2080 servername
, user
, &hnd
);
2082 if (!W_ERROR_IS_OK(result
))
2087 /* Enumerate ports */
2089 result
= cli_spoolss_enumjobs(
2090 cli
, mem_ctx
, 0, &needed
, &hnd
, level
, 0, 1000,
2093 if (W_ERROR_V(result
) == ERRinsufficientbuffer
)
2094 result
= cli_spoolss_enumjobs(
2095 cli
, mem_ctx
, needed
, NULL
, &hnd
, level
, 0,
2096 1000, &num_jobs
, &ctr
);
2098 if (!W_ERROR_IS_OK(result
))
2101 for (i
= 0; i
< num_jobs
; i
++) {
2104 display_job_info_1(&ctr
.job
.job_info_1
[i
]);
2107 display_job_info_2(&ctr
.job
.job_info_2
[i
]);
2110 d_printf("unknown info level %d\n", level
);
2117 cli_spoolss_close_printer(cli
, mem_ctx
, &hnd
);
2122 /* enumerate data */
2124 static WERROR
cmd_spoolss_enum_data( struct cli_state
*cli
,
2125 TALLOC_CTX
*mem_ctx
, int argc
,
2129 uint32 i
=0, val_needed
, data_needed
;
2130 BOOL got_hnd
= False
;
2131 pstring printername
;
2132 fstring servername
, user
;
2136 printf("Usage: %s printername\n", argv
[0]);
2140 /* Open printer handle */
2142 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
2143 strupper_m(servername
);
2144 fstrcpy(user
, cli
->user_name
);
2145 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\", cli
->desthost
);
2146 strupper_m(printername
);
2147 pstrcat(printername
, argv
[1]);
2149 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
2150 "", MAXIMUM_ALLOWED_ACCESS
,
2151 servername
, user
, &hnd
);
2153 if (!W_ERROR_IS_OK(result
))
2158 /* Enumerate data */
2160 result
= cli_spoolss_enumprinterdata(cli
, mem_ctx
, &hnd
, i
, 0, 0,
2161 &val_needed
, &data_needed
,
2163 while (W_ERROR_IS_OK(result
)) {
2164 REGISTRY_VALUE value
;
2165 result
= cli_spoolss_enumprinterdata(
2166 cli
, mem_ctx
, &hnd
, i
++, val_needed
,
2167 data_needed
, 0, 0, &value
);
2168 if (W_ERROR_IS_OK(result
))
2169 display_reg_value(value
);
2171 if (W_ERROR_V(result
) == ERRnomoreitems
)
2172 result
= W_ERROR(ERRsuccess
);
2176 cli_spoolss_close_printer(cli
, mem_ctx
, &hnd
);
2181 /* enumerate data for a given key */
2183 static WERROR
cmd_spoolss_enum_data_ex( struct cli_state
*cli
,
2184 TALLOC_CTX
*mem_ctx
, int argc
,
2189 BOOL got_hnd
= False
;
2190 pstring printername
;
2191 fstring servername
, user
;
2192 const char *keyname
= NULL
;
2197 printf("Usage: %s printername <keyname>\n", argv
[0]);
2203 /* Open printer handle */
2205 slprintf(servername
, sizeof(servername
)-1, "\\\\%s", cli
->desthost
);
2206 strupper_m(servername
);
2207 fstrcpy(user
, cli
->user_name
);
2208 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\", cli
->desthost
);
2209 strupper_m(printername
);
2210 pstrcat(printername
, argv
[1]);
2212 result
= cli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
2213 "", MAXIMUM_ALLOWED_ACCESS
,
2214 servername
, user
, &hnd
);
2216 if (!W_ERROR_IS_OK(result
))
2221 /* Enumerate subkeys */
2223 result
= cli_spoolss_enumprinterdataex(
2224 cli
, mem_ctx
, 0, &needed
, &hnd
, keyname
, NULL
);
2226 if (W_ERROR_V(result
) == ERRmoredata
)
2227 result
= cli_spoolss_enumprinterdataex(
2228 cli
, mem_ctx
, needed
, NULL
, &hnd
, keyname
, &ctr
);
2230 if (!W_ERROR_IS_OK(result
))
2233 for (i
=0; i
< ctr
.num_values
; i
++) {
2234 display_reg_value(*(ctr
.values
[i
]));
2237 regval_ctr_destroy(&ctr
);
2241 cli_spoolss_close_printer(cli
, mem_ctx
, &hnd
);
2246 /* enumerate subkeys */
2248 static WERROR
cmd_spoolss_enum_printerkey( struct cli_state
*cli
,
2249 TALLOC_CTX
*mem_ctx
, int argc
,
2253 uint32 needed
, returned
;
2254 BOOL got_hnd
= False
;
2255 pstring printername
;
2256 fstring servername
, user
;
2257 const char *keyname
= NULL
;
2259 uint16
*keylist
= NULL
, *curkey
;
2261 if (argc
< 2 || argc
> 3) {
2262 printf("Usage: %s printername [keyname]\n", argv
[0]);
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
))
2289 /* Enumerate subkeys */
2291 result
= cli_spoolss_enumprinterkey(
2292 cli
, mem_ctx
, 0, &needed
, &hnd
, keyname
, NULL
, NULL
);
2294 if (W_ERROR_V(result
) == ERRmoredata
)
2295 result
= cli_spoolss_enumprinterkey(
2296 cli
, mem_ctx
, needed
, NULL
, &hnd
, keyname
, &keylist
,
2299 if (!W_ERROR_IS_OK(result
))
2303 while (*curkey
!= 0) {
2305 rpcstr_pull(subkey
, curkey
, sizeof(subkey
), -1,
2307 printf("%s\n", subkey
);
2308 curkey
+= strlen(subkey
) + 1;
2315 cli_spoolss_close_printer(cli
, mem_ctx
, &hnd
);
2320 static WERROR
cmd_spoolss_rffpcnex(struct cli_state
*cli
,
2321 TALLOC_CTX
*mem_ctx
, int argc
,
2324 fstring servername
, printername
;
2326 BOOL got_hnd
= False
;
2328 SPOOL_NOTIFY_OPTION option
;
2331 printf("Usage: %s printername\n", argv
[0]);
2338 slprintf(servername
, sizeof(servername
) - 1, "\\\\%s", cli
->desthost
);
2339 strupper_m(servername
);
2341 slprintf(printername
, sizeof(printername
) - 1, "\\\\%s\\%s", cli
->desthost
,
2343 strupper_m(printername
);
2345 result
= cli_spoolss_open_printer_ex(
2346 cli
, mem_ctx
, printername
, "", MAXIMUM_ALLOWED_ACCESS
,
2347 servername
, cli
->user_name
, &hnd
);
2349 if (!W_ERROR_IS_OK(result
)) {
2350 printf("Error opening %s\n", argv
[1]);
2356 /* Create spool options */
2358 ZERO_STRUCT(option
);
2361 option
.option_type_ptr
= 1;
2362 option
.count
= option
.ctr
.count
= 2;
2364 option
.ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)talloc(
2365 mem_ctx
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * 2);
2367 ZERO_STRUCT(option
.ctr
.type
[0]);
2368 option
.ctr
.type
[0].type
= PRINTER_NOTIFY_TYPE
;
2369 option
.ctr
.type
[0].count
= option
.ctr
.type
[0].count2
= 1;
2370 option
.ctr
.type
[0].fields_ptr
= 1;
2371 option
.ctr
.type
[0].fields
[0] = PRINTER_NOTIFY_SERVER_NAME
;
2373 ZERO_STRUCT(option
.ctr
.type
[1]);
2374 option
.ctr
.type
[1].type
= JOB_NOTIFY_TYPE
;
2375 option
.ctr
.type
[1].count
= option
.ctr
.type
[1].count2
= 1;
2376 option
.ctr
.type
[1].fields_ptr
= 1;
2377 option
.ctr
.type
[1].fields
[0] = JOB_NOTIFY_PRINTER_NAME
;
2381 slprintf(servername
, sizeof(servername
) - 1, "\\\\%s", myhostname());
2382 strupper_m(servername
);
2384 result
= cli_spoolss_rffpcnex(
2385 cli
, mem_ctx
, &hnd
, 0, 0, servername
, 123, &option
);
2387 if (!W_ERROR_IS_OK(result
)) {
2388 printf("Error rffpcnex %s\n", argv
[1]);
2394 cli_spoolss_close_printer(cli
, mem_ctx
, &hnd
);
2399 /* List of commands exported by this module */
2400 struct cmd_set spoolss_commands
[] = {
2404 { "adddriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterdriver
, PI_SPOOLSS
, "Add a print driver", "" },
2405 { "addprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addprinterex
, PI_SPOOLSS
, "Add a printer", "" },
2406 { "deldriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deletedriver
, PI_SPOOLSS
, "Delete a printer driver", "" },
2407 { "enumdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data
, PI_SPOOLSS
, "Enumerate printer data", "" },
2408 { "enumdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_data_ex
, PI_SPOOLSS
, "Enumerate printer data for a key", "" },
2409 { "enumkey", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printerkey
, PI_SPOOLSS
, "Enumerate printer keys", "" },
2410 { "enumjobs", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_jobs
, PI_SPOOLSS
, "Enumerate print jobs", "" },
2411 { "enumports", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_ports
, PI_SPOOLSS
, "Enumerate printer ports", "" },
2412 { "enumdrivers", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_drivers
, PI_SPOOLSS
, "Enumerate installed printer drivers", "" },
2413 { "enumprinters", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_printers
, PI_SPOOLSS
, "Enumerate printers", "" },
2414 { "getdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdata
, PI_SPOOLSS
, "Get print driver data", "" },
2415 { "getdataex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinterdataex
, PI_SPOOLSS
, "Get printer driver data with keyname", ""},
2416 { "getdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriver
, PI_SPOOLSS
, "Get print driver information", "" },
2417 { "getdriverdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getdriverdir
, PI_SPOOLSS
, "Get print driver upload directory", "" },
2418 { "getprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprinter
, PI_SPOOLSS
, "Get printer info", "" },
2419 { "openprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_open_printer_ex
, PI_SPOOLSS
, "Open printer handle", "" },
2420 { "setdriver", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setdriver
, PI_SPOOLSS
, "Set printer driver", "" },
2421 { "getprintprocdir", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getprintprocdir
, PI_SPOOLSS
, "Get print processor directory", "" },
2422 { "addform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_addform
, PI_SPOOLSS
, "Add form", "" },
2423 { "setform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setform
, PI_SPOOLSS
, "Set form", "" },
2424 { "getform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_getform
, PI_SPOOLSS
, "Get form", "" },
2425 { "deleteform", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_deleteform
, PI_SPOOLSS
, "Delete form", "" },
2426 { "enumforms", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_enum_forms
, PI_SPOOLSS
, "Enumerate forms", "" },
2427 { "setprinter", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinter
, PI_SPOOLSS
, "Set printer comment", "" },
2428 { "setprintername", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprintername
, PI_SPOOLSS
, "Set printername", "" },
2429 { "setprinterdata", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_setprinterdata
, PI_SPOOLSS
, "Set REG_SZ printer data", "" },
2430 { "rffpcnex", RPC_RTYPE_WERROR
, NULL
, cmd_spoolss_rffpcnex
, PI_SPOOLSS
, "Rffpcnex test", "" },