source: branches/samba-3.3.x/source/rpcclient/cmd_spoolss.c

Last change on this file was 221, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 to 3.3.1

File size: 78.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
4
5 Copyright (C) Gerald Carter 2001-2005
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 1992-1999
8 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
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.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "rpcclient.h"
26
27struct table_node {
28 const char *long_archi;
29 const char *short_archi;
30 int version;
31};
32
33/* The version int is used by getdrivers. Note that
34 all architecture strings that support mutliple
35 versions must be grouped together since enumdrivers
36 uses this property to prevent issuing multiple
37 enumdriver calls for the same arch */
38
39
40static const struct table_node archi_table[]= {
41
42 {"Windows 4.0", "WIN40", 0 },
43 {"Windows NT x86", "W32X86", 2 },
44 {"Windows NT x86", "W32X86", 3 },
45 {"Windows NT R4000", "W32MIPS", 2 },
46 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
47 {"Windows NT PowerPC", "W32PPC", 2 },
48 {"Windows IA64", "IA64", 3 },
49 {"Windows x64", "x64", 3 },
50 {NULL, "", -1 }
51};
52
53/**
54 * @file
55 *
56 * rpcclient module for SPOOLSS rpc pipe.
57 *
58 * This generally just parses and checks command lines, and then calls
59 * a cli_spoolss function.
60 **/
61
62/****************************************************************************
63 function to do the mapping between the long architecture name and
64 the short one.
65****************************************************************************/
66
67static const char *cmd_spoolss_get_short_archi(const char *long_archi)
68{
69 int i=-1;
70
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) );
76
77 if (archi_table[i].long_archi==NULL) {
78 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
79 return NULL;
80 }
81
82 /* this might be client code - but shouldn't this be an fstrcpy etc? */
83
84
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));
88
89 return archi_table[i].short_archi;
90}
91
92/****************************************************************************
93****************************************************************************/
94
95static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
96 TALLOC_CTX *mem_ctx,
97 int argc, const char **argv)
98{
99 WERROR werror;
100 fstring printername;
101 fstring servername, user;
102 POLICY_HND hnd;
103
104 if (argc != 2) {
105 printf("Usage: %s <printername>\n", argv[0]);
106 return WERR_OK;
107 }
108
109 if (!cli)
110 return WERR_GENERAL_FAILURE;
111
112 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
113 strupper_m(servername);
114 fstrcpy(user, cli->auth->user_name);
115 fstrcpy(printername, argv[1]);
116
117 /* Open the printer handle */
118
119 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
120 "", PRINTER_ALL_ACCESS,
121 servername, user, &hnd);
122
123 if (W_ERROR_IS_OK(werror)) {
124 printf("Printer %s opened successfully\n", printername);
125 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
126
127 if (!W_ERROR_IS_OK(werror)) {
128 printf("Error closing printer handle! (%s)\n",
129 get_dos_error_msg(werror));
130 }
131 }
132
133 return werror;
134}
135
136
137/****************************************************************************
138****************************************************************************/
139
140static void display_print_info_0(PRINTER_INFO_0 *i0)
141{
142 fstring name = "";
143 fstring servername = "";
144
145 if (!i0)
146 return;
147
148 rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
149
150 rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
151
152 printf("\tprintername:[%s]\n", name);
153 printf("\tservername:[%s]\n", servername);
154 printf("\tcjobs:[0x%x]\n", i0->cjobs);
155 printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
156
157 printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
158 i0->day, i0->dayofweek);
159 printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
160 i0->second, i0->milliseconds);
161
162 printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
163 printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
164
165 printf("\tmajorversion:[0x%x]\n", i0->major_version);
166 printf("\tbuildversion:[0x%x]\n", i0->build_version);
167
168 printf("\tunknown7:[0x%x]\n", i0->unknown7);
169 printf("\tunknown8:[0x%x]\n", i0->unknown8);
170 printf("\tunknown9:[0x%x]\n", i0->unknown9);
171 printf("\tsession_counter:[0x%x]\n", i0->session_counter);
172 printf("\tunknown11:[0x%x]\n", i0->unknown11);
173 printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
174 printf("\tunknown13:[0x%x]\n", i0->unknown13);
175 printf("\tunknown14:[0x%x]\n", i0->unknown14);
176 printf("\tunknown15:[0x%x]\n", i0->unknown15);
177 printf("\tunknown16:[0x%x]\n", i0->unknown16);
178 printf("\tchange_id:[0x%x]\n", i0->change_id);
179 printf("\tunknown18:[0x%x]\n", i0->unknown18);
180 printf("\tstatus:[0x%x]\n", i0->status);
181 printf("\tunknown20:[0x%x]\n", i0->unknown20);
182 printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
183 printf("\tunknown22:[0x%x]\n", i0->unknown22);
184 printf("\tunknown23:[0x%x]\n", i0->unknown23);
185 printf("\tunknown24:[0x%x]\n", i0->unknown24);
186 printf("\tunknown25:[0x%x]\n", i0->unknown25);
187 printf("\tunknown26:[0x%x]\n", i0->unknown26);
188 printf("\tunknown27:[0x%x]\n", i0->unknown27);
189 printf("\tunknown28:[0x%x]\n", i0->unknown28);
190 printf("\tunknown29:[0x%x]\n", i0->unknown29);
191
192 printf("\n");
193}
194
195/****************************************************************************
196****************************************************************************/
197
198static void display_print_info_1(PRINTER_INFO_1 *i1)
199{
200 fstring desc = "";
201 fstring name = "";
202 fstring comm = "";
203
204 rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
205 STR_TERMINATE);
206
207 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
208 rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
209
210 printf("\tflags:[0x%x]\n", i1->flags);
211 printf("\tname:[%s]\n", name);
212 printf("\tdescription:[%s]\n", desc);
213 printf("\tcomment:[%s]\n", comm);
214
215 printf("\n");
216}
217
218/****************************************************************************
219****************************************************************************/
220
221static void display_print_info_2(PRINTER_INFO_2 *i2)
222{
223 fstring servername = "";
224 fstring printername = "";
225 fstring sharename = "";
226 fstring portname = "";
227 fstring drivername = "";
228 fstring comment = "";
229 fstring location = "";
230 fstring sepfile = "";
231 fstring printprocessor = "";
232 fstring datatype = "";
233 fstring parameters = "";
234
235 rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
236 rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
237 rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
238 rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
239 rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
240 rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
241 rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
242 rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
243 rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
244 rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
245 rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
246
247 printf("\tservername:[%s]\n", servername);
248 printf("\tprintername:[%s]\n", printername);
249 printf("\tsharename:[%s]\n", sharename);
250 printf("\tportname:[%s]\n", portname);
251 printf("\tdrivername:[%s]\n", drivername);
252 printf("\tcomment:[%s]\n", comment);
253 printf("\tlocation:[%s]\n", location);
254 printf("\tsepfile:[%s]\n", sepfile);
255 printf("\tprintprocessor:[%s]\n", printprocessor);
256 printf("\tdatatype:[%s]\n", datatype);
257 printf("\tparameters:[%s]\n", parameters);
258 printf("\tattributes:[0x%x]\n", i2->attributes);
259 printf("\tpriority:[0x%x]\n", i2->priority);
260 printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
261 printf("\tstarttime:[0x%x]\n", i2->starttime);
262 printf("\tuntiltime:[0x%x]\n", i2->untiltime);
263 printf("\tstatus:[0x%x]\n", i2->status);
264 printf("\tcjobs:[0x%x]\n", i2->cjobs);
265 printf("\taverageppm:[0x%x]\n", i2->averageppm);
266
267 if (i2->secdesc)
268 display_sec_desc(i2->secdesc);
269
270 printf("\n");
271}
272
273/****************************************************************************
274****************************************************************************/
275
276static void display_print_info_3(PRINTER_INFO_3 *i3)
277{
278 display_sec_desc(i3->secdesc);
279
280 printf("\n");
281}
282
283/****************************************************************************
284****************************************************************************/
285
286static void display_print_info_7(PRINTER_INFO_7 *i7)
287{
288 fstring guid = "";
289 rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
290 printf("\tguid:[%s]\n", guid);
291 printf("\taction:[0x%x]\n", i7->action);
292}
293
294
295/****************************************************************************
296****************************************************************************/
297
298static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
299 TALLOC_CTX *mem_ctx,
300 int argc, const char **argv)
301{
302 WERROR result;
303 uint32 info_level = 1;
304 PRINTER_INFO_CTR ctr;
305 uint32 i = 0, num_printers;
306 fstring name;
307
308 if (argc > 3)
309 {
310 printf("Usage: %s [level] [name]\n", argv[0]);
311 return WERR_OK;
312 }
313
314 if (argc >= 2)
315 info_level = atoi(argv[1]);
316
317 if (argc == 3)
318 fstrcpy(name, argv[2]);
319 else {
320 slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
321 strupper_m(name);
322 }
323
324 ZERO_STRUCT(ctr);
325
326 result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
327 info_level, &num_printers, &ctr);
328
329 if (W_ERROR_IS_OK(result)) {
330
331 if (!num_printers) {
332 printf ("No printers returned.\n");
333 goto done;
334 }
335
336 for (i = 0; i < num_printers; i++) {
337 switch(info_level) {
338 case 0:
339 display_print_info_0(&ctr.printers_0[i]);
340 break;
341 case 1:
342 display_print_info_1(&ctr.printers_1[i]);
343 break;
344 case 2:
345 display_print_info_2(&ctr.printers_2[i]);
346 break;
347 case 3:
348 display_print_info_3(&ctr.printers_3[i]);
349 break;
350 default:
351 printf("unknown info level %d\n", info_level);
352 goto done;
353 }
354 }
355 }
356 done:
357
358 return result;
359}
360
361/****************************************************************************
362****************************************************************************/
363
364static void display_port_info_1(PORT_INFO_1 *i1)
365{
366 fstring buffer;
367
368 rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
369 printf("\tPort Name:\t[%s]\n", buffer);
370}
371
372/****************************************************************************
373****************************************************************************/
374
375static void display_port_info_2(PORT_INFO_2 *i2)
376{
377 fstring buffer;
378
379 rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
380 printf("\tPort Name:\t[%s]\n", buffer);
381 rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
382
383 printf("\tMonitor Name:\t[%s]\n", buffer);
384 rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
385
386 printf("\tDescription:\t[%s]\n", buffer);
387 printf("\tPort Type:\t" );
388 if ( i2->port_type ) {
389 int comma = 0; /* hack */
390 printf( "[" );
391 if ( i2->port_type & PORT_TYPE_READ ) {
392 printf( "Read" );
393 comma = 1;
394 }
395 if ( i2->port_type & PORT_TYPE_WRITE ) {
396 printf( "%sWrite", comma ? ", " : "" );
397 comma = 1;
398 }
399 /* These two have slightly different interpretations
400 on 95/98/ME but I'm disregarding that for now */
401 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
402 printf( "%sRedirected", comma ? ", " : "" );
403 comma = 1;
404 }
405 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
406 printf( "%sNet-Attached", comma ? ", " : "" );
407 }
408 printf( "]\n" );
409 } else {
410 printf( "[Unset]\n" );
411 }
412 printf("\tReserved:\t[%d]\n", i2->reserved);
413 printf("\n");
414}
415
416/****************************************************************************
417****************************************************************************/
418
419static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
420 TALLOC_CTX *mem_ctx, int argc,
421 const char **argv)
422{
423 WERROR result;
424 uint32 info_level = 1;
425 PORT_INFO_CTR ctr;
426 uint32 returned;
427
428 if (argc > 2) {
429 printf("Usage: %s [level]\n", argv[0]);
430 return WERR_OK;
431 }
432
433 if (argc == 2)
434 info_level = atoi(argv[1]);
435
436 /* Enumerate ports */
437
438 ZERO_STRUCT(ctr);
439
440 result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
441
442 if (W_ERROR_IS_OK(result)) {
443 int i;
444
445 for (i = 0; i < returned; i++) {
446 switch (info_level) {
447 case 1:
448 display_port_info_1(&ctr.port.info_1[i]);
449 break;
450 case 2:
451 display_port_info_2(&ctr.port.info_2[i]);
452 break;
453 default:
454 printf("unknown info level %d\n", info_level);
455 break;
456 }
457 }
458 }
459
460 return result;
461}
462
463/****************************************************************************
464****************************************************************************/
465
466static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
467 TALLOC_CTX *mem_ctx,
468 int argc, const char **argv)
469{
470 POLICY_HND pol;
471 WERROR result;
472 uint32 info_level = 2;
473 bool opened_hnd = False;
474 PRINTER_INFO_CTR ctr;
475 fstring printername,
476 servername,
477 user,
478 comment;
479
480 if (argc == 1 || argc > 3) {
481 printf("Usage: %s printername comment\n", argv[0]);
482
483 return WERR_OK;
484 }
485
486 /* Open a printer handle */
487 if (argc == 3) {
488 fstrcpy(comment, argv[2]);
489 }
490
491 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
492 strupper_m(servername);
493 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
494 fstrcpy(user, cli->auth->user_name);
495
496 /* get a printer handle */
497 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
498 PRINTER_ALL_ACCESS, servername,
499 user, &pol);
500
501 if (!W_ERROR_IS_OK(result))
502 goto done;
503
504 opened_hnd = True;
505
506 /* Get printer info */
507 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
508
509 if (!W_ERROR_IS_OK(result))
510 goto done;
511
512
513 /* Modify the comment. */
514 init_unistr(&ctr.printers_2->comment, comment);
515 ctr.printers_2->devmode = NULL;
516 ctr.printers_2->secdesc = NULL;
517
518 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
519 if (W_ERROR_IS_OK(result))
520 printf("Success in setting comment.\n");
521
522 done:
523 if (opened_hnd)
524 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
525
526 return result;
527}
528
529/****************************************************************************
530****************************************************************************/
531
532static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
533 TALLOC_CTX *mem_ctx,
534 int argc, const char **argv)
535{
536 POLICY_HND pol;
537 WERROR result;
538 uint32 info_level = 2;
539 bool opened_hnd = False;
540 PRINTER_INFO_CTR ctr;
541 fstring printername,
542 servername,
543 user,
544 new_printername;
545
546 if (argc == 1 || argc > 3) {
547 printf("Usage: %s printername new_printername\n", argv[0]);
548
549 return WERR_OK;
550 }
551
552 /* Open a printer handle */
553 if (argc == 3) {
554 fstrcpy(new_printername, argv[2]);
555 }
556
557 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
558 strupper_m(servername);
559 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
560 fstrcpy(user, cli->auth->user_name);
561
562 /* get a printer handle */
563 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
564 PRINTER_ALL_ACCESS, servername,
565 user, &pol);
566
567 if (!W_ERROR_IS_OK(result))
568 goto done;
569
570 opened_hnd = True;
571
572 /* Get printer info */
573 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
574
575 if (!W_ERROR_IS_OK(result))
576 goto done;
577
578 /* Modify the printername. */
579 init_unistr(&ctr.printers_2->printername, new_printername);
580 ctr.printers_2->devmode = NULL;
581 ctr.printers_2->secdesc = NULL;
582
583 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
584 if (W_ERROR_IS_OK(result))
585 printf("Success in setting printername.\n");
586
587 done:
588 if (opened_hnd)
589 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
590
591 return result;
592}
593
594/****************************************************************************
595****************************************************************************/
596
597static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
598 TALLOC_CTX *mem_ctx,
599 int argc, const char **argv)
600{
601 POLICY_HND pol;
602 WERROR result;
603 uint32 info_level = 1;
604 bool opened_hnd = False;
605 PRINTER_INFO_CTR ctr;
606 fstring printername,
607 servername,
608 user;
609
610 if (argc == 1 || argc > 3) {
611 printf("Usage: %s <printername> [level]\n", argv[0]);
612 return WERR_OK;
613 }
614
615 /* Open a printer handle */
616 if (argc == 3) {
617 info_level = atoi(argv[2]);
618 }
619
620 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
621 strupper_m(servername);
622 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
623 fstrcpy(user, cli->auth->user_name);
624
625 /* get a printer handle */
626
627 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
628 "", MAXIMUM_ALLOWED_ACCESS,
629 servername, user, &pol);
630
631 if (!W_ERROR_IS_OK(result))
632 goto done;
633
634 opened_hnd = True;
635
636 /* Get printer info */
637
638 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
639
640 if (!W_ERROR_IS_OK(result))
641 goto done;
642
643 /* Display printer info */
644
645 switch (info_level) {
646 case 0:
647 display_print_info_0(ctr.printers_0);
648 break;
649 case 1:
650 display_print_info_1(ctr.printers_1);
651 break;
652 case 2:
653 display_print_info_2(ctr.printers_2);
654 break;
655 case 3:
656 display_print_info_3(ctr.printers_3);
657 break;
658 case 7:
659 display_print_info_7(ctr.printers_7);
660 break;
661 default:
662 printf("unknown info level %d\n", info_level);
663 break;
664 }
665
666 done:
667 if (opened_hnd)
668 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
669
670 return result;
671}
672
673/****************************************************************************
674****************************************************************************/
675
676static void display_reg_value(REGISTRY_VALUE value)
677{
678 char *text = NULL;
679
680 switch(value.type) {
681 case REG_DWORD:
682 printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
683 *((uint32 *) value.data_p));
684 break;
685 case REG_SZ:
686 rpcstr_pull_talloc(talloc_tos(),
687 &text,
688 value.data_p,
689 value.size,
690 STR_TERMINATE);
691 printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
692 break;
693 case REG_BINARY: {
694 char *hex = hex_encode(NULL, value.data_p, value.size);
695 size_t i, len;
696 printf("%s: REG_BINARY:", value.valuename);
697 len = strlen(hex);
698 for (i=0; i<len; i++) {
699 if (hex[i] == '\0') {
700 break;
701 }
702 if (i%40 == 0) {
703 putchar('\n');
704 }
705 putchar(hex[i]);
706 }
707 TALLOC_FREE(hex);
708 putchar('\n');
709 break;
710 }
711 case REG_MULTI_SZ: {
712 uint32 i, num_values;
713 char **values;
714
715 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
716 value.size, &num_values,
717 &values))) {
718 d_printf("reg_pull_multi_sz failed\n");
719 break;
720 }
721
722 for (i=0; i<num_values; i++) {
723 d_printf("%s\n", values[i]);
724 }
725 TALLOC_FREE(values);
726 break;
727 }
728 default:
729 printf("%s: unknown type %d\n", value.valuename, value.type);
730 }
731
732}
733
734/****************************************************************************
735****************************************************************************/
736
737static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
738 TALLOC_CTX *mem_ctx,
739 int argc, const char **argv)
740{
741 POLICY_HND pol;
742 WERROR result;
743 bool opened_hnd = False;
744 fstring printername,
745 servername,
746 user;
747 const char *valuename;
748 REGISTRY_VALUE value;
749
750 if (argc != 3) {
751 printf("Usage: %s <printername> <valuename>\n", argv[0]);
752 printf("<printername> of . queries print server\n");
753 return WERR_OK;
754 }
755 valuename = argv[2];
756
757 /* Open a printer handle */
758
759 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
760 strupper_m(servername);
761 if (strncmp(argv[1], ".", sizeof(".")) == 0)
762 fstrcpy(printername, servername);
763 else
764 slprintf(printername, sizeof(servername)-1, "%s\\%s",
765 servername, argv[1]);
766 fstrcpy(user, cli->auth->user_name);
767
768 /* get a printer handle */
769
770 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
771 "", MAXIMUM_ALLOWED_ACCESS,
772 servername, user, &pol);
773
774 if (!W_ERROR_IS_OK(result))
775 goto done;
776
777 opened_hnd = True;
778
779 /* Get printer info */
780
781 result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
782
783 if (!W_ERROR_IS_OK(result))
784 goto done;
785
786 /* Display printer data */
787
788 fstrcpy(value.valuename, valuename);
789 display_reg_value(value);
790
791
792 done:
793 if (opened_hnd)
794 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
795
796 return result;
797}
798
799/****************************************************************************
800****************************************************************************/
801
802static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
803 TALLOC_CTX *mem_ctx,
804 int argc, const char **argv)
805{
806 POLICY_HND pol;
807 WERROR result;
808 bool opened_hnd = False;
809 fstring printername,
810 servername,
811 user;
812 const char *valuename, *keyname;
813 REGISTRY_VALUE value;
814
815 if (argc != 4) {
816 printf("Usage: %s <printername> <keyname> <valuename>\n",
817 argv[0]);
818 printf("<printername> of . queries print server\n");
819 return WERR_OK;
820 }
821 valuename = argv[3];
822 keyname = argv[2];
823
824 /* Open a printer handle */
825
826 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
827 strupper_m(servername);
828 if (strncmp(argv[1], ".", sizeof(".")) == 0)
829 fstrcpy(printername, servername);
830 else
831 slprintf(printername, sizeof(printername)-1, "%s\\%s",
832 servername, argv[1]);
833 fstrcpy(user, cli->auth->user_name);
834
835 /* get a printer handle */
836
837 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
838 "", MAXIMUM_ALLOWED_ACCESS,
839 servername, user, &pol);
840
841 if (!W_ERROR_IS_OK(result))
842 goto done;
843
844 opened_hnd = True;
845
846 /* Get printer info */
847
848 result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname,
849 valuename, &value);
850
851 if (!W_ERROR_IS_OK(result))
852 goto done;
853
854 /* Display printer data */
855
856 fstrcpy(value.valuename, valuename);
857 display_reg_value(value);
858
859
860 done:
861 if (opened_hnd)
862 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
863
864 return result;
865}
866
867/****************************************************************************
868****************************************************************************/
869
870static void display_print_driver_1(DRIVER_INFO_1 *i1)
871{
872 fstring name;
873 if (i1 == NULL)
874 return;
875
876 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
877
878 printf ("Printer Driver Info 1:\n");
879 printf ("\tDriver Name: [%s]\n\n", name);
880
881 return;
882}
883
884/****************************************************************************
885****************************************************************************/
886
887static void display_print_driver_2(DRIVER_INFO_2 *i1)
888{
889 fstring name;
890 fstring architecture;
891 fstring driverpath;
892 fstring datafile;
893 fstring configfile;
894 if (i1 == NULL)
895 return;
896
897 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
898 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
899 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
900 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
901 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
902
903 printf ("Printer Driver Info 2:\n");
904 printf ("\tVersion: [%x]\n", i1->version);
905 printf ("\tDriver Name: [%s]\n", name);
906 printf ("\tArchitecture: [%s]\n", architecture);
907 printf ("\tDriver Path: [%s]\n", driverpath);
908 printf ("\tDatafile: [%s]\n", datafile);
909 printf ("\tConfigfile: [%s]\n\n", configfile);
910
911 return;
912}
913
914/****************************************************************************
915****************************************************************************/
916
917static void display_print_driver_3(DRIVER_INFO_3 *i1)
918{
919 fstring name = "";
920 fstring architecture = "";
921 fstring driverpath = "";
922 fstring datafile = "";
923 fstring configfile = "";
924 fstring helpfile = "";
925 fstring dependentfiles = "";
926 fstring monitorname = "";
927 fstring defaultdatatype = "";
928
929 int length=0;
930 bool valid = True;
931
932 if (i1 == NULL)
933 return;
934
935 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
936 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
937 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
938 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
939 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
940 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
941 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
942 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
943
944 printf ("Printer Driver Info 3:\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", configfile);
951 printf ("\tHelpfile: [%s]\n\n", helpfile);
952
953 while (valid)
954 {
955 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
956
957 length+=strlen(dependentfiles)+1;
958
959 if (strlen(dependentfiles) > 0)
960 {
961 printf ("\tDependentfiles: [%s]\n", dependentfiles);
962 }
963 else
964 {
965 valid = False;
966 }
967 }
968
969 printf ("\n");
970
971 printf ("\tMonitorname: [%s]\n", monitorname);
972 printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
973
974 return;
975}
976
977/****************************************************************************
978****************************************************************************/
979
980static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
981 TALLOC_CTX *mem_ctx,
982 int argc, const char **argv)
983{
984 POLICY_HND pol;
985 WERROR werror;
986 uint32 info_level = 3;
987 bool opened_hnd = False;
988 PRINTER_DRIVER_CTR ctr;
989 fstring printername,
990 servername,
991 user;
992 uint32 i;
993 bool success = False;
994
995 if ((argc == 1) || (argc > 3))
996 {
997 printf("Usage: %s <printername> [level]\n", argv[0]);
998 return WERR_OK;
999 }
1000
1001 /* get the arguments need to open the printer handle */
1002 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1003 strupper_m(servername);
1004 fstrcpy(user, cli->auth->user_name);
1005 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
1006 if (argc == 3)
1007 info_level = atoi(argv[2]);
1008
1009 /* Open a printer handle */
1010
1011 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1012 PRINTER_ACCESS_USE,
1013 servername, user, &pol);
1014
1015 if (!W_ERROR_IS_OK(werror)) {
1016 printf("Error opening printer handle for %s!\n", printername);
1017 return werror;
1018 }
1019
1020 opened_hnd = True;
1021
1022 /* loop through and print driver info level for each architecture */
1023
1024 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1025
1026 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
1027 archi_table[i].long_archi, archi_table[i].version,
1028 &ctr);
1029
1030 if (!W_ERROR_IS_OK(werror))
1031 continue;
1032
1033 /* need at least one success */
1034
1035 success = True;
1036
1037 printf ("\n[%s]\n", archi_table[i].long_archi);
1038
1039 switch (info_level) {
1040 case 1:
1041 display_print_driver_1 (ctr.info1);
1042 break;
1043 case 2:
1044 display_print_driver_2 (ctr.info2);
1045 break;
1046 case 3:
1047 display_print_driver_3 (ctr.info3);
1048 break;
1049 default:
1050 printf("unknown info level %d\n", info_level);
1051 break;
1052 }
1053 }
1054
1055 /* Cleanup */
1056
1057 if (opened_hnd)
1058 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
1059
1060 if ( success )
1061 werror = WERR_OK;
1062
1063 return werror;
1064}
1065
1066/****************************************************************************
1067****************************************************************************/
1068
1069static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1070 TALLOC_CTX *mem_ctx,
1071 int argc, const char **argv)
1072{
1073 WERROR werror = WERR_OK;
1074 uint32 info_level = 1;
1075 PRINTER_DRIVER_CTR ctr;
1076 uint32 i, j,
1077 returned;
1078
1079 if (argc > 2) {
1080 printf("Usage: enumdrivers [level]\n");
1081 return WERR_OK;
1082 }
1083
1084 if (argc == 2)
1085 info_level = atoi(argv[1]);
1086
1087
1088 /* loop through and print driver info level for each architecture */
1089 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1090 /* check to see if we already asked for this architecture string */
1091
1092 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
1093 continue;
1094
1095 werror = rpccli_spoolss_enumprinterdrivers(
1096 cli, mem_ctx, info_level,
1097 archi_table[i].long_archi, &returned, &ctr);
1098
1099 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1100 printf ("Server does not support environment [%s]\n",
1101 archi_table[i].long_archi);
1102 werror = WERR_OK;
1103 continue;
1104 }
1105
1106 if (returned == 0)
1107 continue;
1108
1109 if (!W_ERROR_IS_OK(werror)) {
1110 printf ("Error getting driver for environment [%s] - %d\n",
1111 archi_table[i].long_archi, W_ERROR_V(werror));
1112 continue;
1113 }
1114
1115 printf ("\n[%s]\n", archi_table[i].long_archi);
1116 switch (info_level)
1117 {
1118
1119 case 1:
1120 for (j=0; j < returned; j++) {
1121 display_print_driver_1 (&ctr.info1[j]);
1122 }
1123 break;
1124 case 2:
1125 for (j=0; j < returned; j++) {
1126 display_print_driver_2 (&ctr.info2[j]);
1127 }
1128 break;
1129 case 3:
1130 for (j=0; j < returned; j++) {
1131 display_print_driver_3 (&ctr.info3[j]);
1132 }
1133 break;
1134 default:
1135 printf("unknown info level %d\n", info_level);
1136 return WERR_UNKNOWN_LEVEL;
1137 }
1138 }
1139
1140 return werror;
1141}
1142
1143/****************************************************************************
1144****************************************************************************/
1145
1146static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
1147{
1148 fstring name;
1149 if (i1 == NULL)
1150 return;
1151
1152 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
1153
1154 printf ("\tDirectory Name:[%s]\n", name);
1155}
1156
1157/****************************************************************************
1158****************************************************************************/
1159
1160static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1161 TALLOC_CTX *mem_ctx,
1162 int argc, const char **argv)
1163{
1164 WERROR result;
1165 fstring env;
1166 DRIVER_DIRECTORY_CTR ctr;
1167
1168 if (argc > 2) {
1169 printf("Usage: %s [environment]\n", argv[0]);
1170 return WERR_OK;
1171 }
1172
1173 /* Get the arguments need to open the printer handle */
1174
1175 if (argc == 2)
1176 fstrcpy (env, argv[1]);
1177 else
1178 fstrcpy (env, "Windows NT x86");
1179
1180 /* Get the directory. Only use Info level 1 */
1181
1182 result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
1183
1184 if (W_ERROR_IS_OK(result))
1185 display_printdriverdir_1(ctr.info1);
1186
1187 return result;
1188}
1189
1190/****************************************************************************
1191****************************************************************************/
1192
1193void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
1194{
1195
1196 int i;
1197
1198 for (i=0; archi_table[i].long_archi != NULL; i++)
1199 {
1200 if (strcmp(arch, archi_table[i].short_archi) == 0)
1201 {
1202 info->version = archi_table[i].version;
1203 init_unistr (&info->architecture, archi_table[i].long_archi);
1204 break;
1205 }
1206 }
1207
1208 if (archi_table[i].long_archi == NULL)
1209 {
1210 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1211 }
1212
1213 return;
1214}
1215
1216
1217/**************************************************************************
1218 wrapper for strtok to get the next parameter from a delimited list.
1219 Needed to handle the empty parameter string denoted by "NULL"
1220 *************************************************************************/
1221
1222static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
1223 char **saveptr)
1224{
1225 char *ptr;
1226
1227 /* get the next token */
1228 ptr = strtok_r(str, delim, saveptr);
1229
1230 /* a string of 'NULL' is used to represent an empty
1231 parameter because two consecutive delimiters
1232 will not return an empty string. See man strtok(3)
1233 for details */
1234 if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
1235 ptr = NULL;
1236
1237 if (dest != NULL)
1238 init_unistr(dest, ptr);
1239
1240 return ptr;
1241}
1242
1243/********************************************************************************
1244 fill in the members of a DRIVER_INFO_3 struct using a character
1245 string in the form of
1246 <Long Printer Name>:<Driver File Name>:<Data File Name>:\
1247 <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1248 <Default Data Type>:<Comma Separated list of Files>
1249 *******************************************************************************/
1250static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
1251 char *args )
1252{
1253 char *str, *str2;
1254 uint32 len, i;
1255 char *saveptr = NULL;
1256
1257 /* fill in the UNISTR fields */
1258 str = get_driver_3_param (args, ":", &info->name, &saveptr);
1259 str = get_driver_3_param (NULL, ":", &info->driverpath, &saveptr);
1260 str = get_driver_3_param (NULL, ":", &info->datafile, &saveptr);
1261 str = get_driver_3_param (NULL, ":", &info->configfile, &saveptr);
1262 str = get_driver_3_param (NULL, ":", &info->helpfile, &saveptr);
1263 str = get_driver_3_param (NULL, ":", &info->monitorname, &saveptr);
1264 str = get_driver_3_param (NULL, ":", &info->defaultdatatype, &saveptr);
1265
1266 /* <Comma Separated List of Dependent Files> */
1267 /* save the beginning of the string */
1268 str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
1269 str = str2;
1270
1271 /* begin to strip out each filename */
1272 str = strtok_r(str, ",", &saveptr);
1273 len = 0;
1274 while (str != NULL)
1275 {
1276 /* keep a cumlative count of the str lengths */
1277 len += strlen(str)+1;
1278 str = strtok_r(NULL, ",", &saveptr);
1279 }
1280
1281 /* allocate the space; add one extra slot for a terminating NULL.
1282 Each filename is NULL terminated and the end contains a double
1283 NULL */
1284 if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
1285 {
1286 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
1287 return False;
1288 }
1289 for (i=0; i<len; i++)
1290 {
1291 SSVAL(&info->dependentfiles[i], 0, str2[i]);
1292 }
1293 info->dependentfiles[len] = '\0';
1294
1295 return True;
1296}
1297
1298
1299/****************************************************************************
1300****************************************************************************/
1301
1302static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1303 TALLOC_CTX *mem_ctx,
1304 int argc, const char **argv)
1305{
1306 WERROR result;
1307 uint32 level = 3;
1308 PRINTER_DRIVER_CTR ctr;
1309 DRIVER_INFO_3 info3;
1310 const char *arch;
1311 fstring driver_name;
1312 char *driver_args;
1313
1314 /* parse the command arguments */
1315 if (argc != 3 && argc != 4)
1316 {
1317 printf ("Usage: %s <Environment> \\\n", argv[0]);
1318 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
1319 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1320 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1321 printf ("\t[version]\n");
1322
1323 return WERR_OK;
1324 }
1325
1326 /* Fill in the DRIVER_INFO_3 struct */
1327 ZERO_STRUCT(info3);
1328 if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
1329 {
1330 printf ("Error Unknown architechture [%s]\n", argv[1]);
1331 return WERR_INVALID_PARAM;
1332 }
1333 else
1334 set_drv_info_3_env(&info3, arch);
1335
1336 driver_args = talloc_strdup( mem_ctx, argv[2] );
1337 if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1338 {
1339 printf ("Error Invalid parameter list - %s.\n", argv[2]);
1340 return WERR_INVALID_PARAM;
1341 }
1342
1343 /* if printer driver version specified, override the default version
1344 * used by the architecture. This allows installation of Windows
1345 * 2000 (version 3) printer drivers. */
1346 if (argc == 4)
1347 {
1348 info3.version = atoi(argv[3]);
1349 }
1350
1351
1352 ctr.info3 = &info3;
1353 result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
1354
1355 if (W_ERROR_IS_OK(result)) {
1356 rpcstr_pull(driver_name, info3.name.buffer,
1357 sizeof(driver_name), -1, STR_TERMINATE);
1358 printf ("Printer Driver %s successfully installed.\n",
1359 driver_name);
1360 }
1361
1362 return result;
1363}
1364
1365
1366/****************************************************************************
1367****************************************************************************/
1368
1369static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1370 TALLOC_CTX *mem_ctx,
1371 int argc, const char **argv)
1372{
1373 WERROR result;
1374 uint32 level = 2;
1375 PRINTER_INFO_CTR ctr;
1376 PRINTER_INFO_2 info2;
1377 fstring servername;
1378
1379 /* parse the command arguments */
1380 if (argc != 5)
1381 {
1382 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1383 return WERR_OK;
1384 }
1385
1386 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1387 strupper_m(servername);
1388
1389 /* Fill in the DRIVER_INFO_2 struct */
1390 ZERO_STRUCT(info2);
1391
1392 init_unistr( &info2.printername, argv[1]);
1393 init_unistr( &info2.sharename, argv[2]);
1394 init_unistr( &info2.drivername, argv[3]);
1395 init_unistr( &info2.portname, argv[4]);
1396 init_unistr( &info2.comment, "Created by rpcclient");
1397 init_unistr( &info2.printprocessor, "winprint");
1398 init_unistr( &info2.datatype, "RAW");
1399 info2.devmode = NULL;
1400 info2.secdesc = NULL;
1401 info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1402 info2.priority = 0;
1403 info2.defaultpriority = 0;
1404 info2.starttime = 0;
1405 info2.untiltime = 0;
1406
1407 /* These three fields must not be used by AddPrinter()
1408 as defined in the MS Platform SDK documentation..
1409 --jerry
1410 info2.status = 0;
1411 info2.cjobs = 0;
1412 info2.averageppm = 0;
1413 */
1414
1415 ctr.printers_2 = &info2;
1416 result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
1417
1418 if (W_ERROR_IS_OK(result))
1419 printf ("Printer %s successfully installed.\n", argv[1]);
1420
1421 return result;
1422}
1423
1424/****************************************************************************
1425****************************************************************************/
1426
1427static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1428 TALLOC_CTX *mem_ctx,
1429 int argc, const char **argv)
1430{
1431 POLICY_HND pol;
1432 WERROR result;
1433 uint32 level = 2;
1434 bool opened_hnd = False;
1435 PRINTER_INFO_CTR ctr;
1436 PRINTER_INFO_2 info2;
1437 fstring servername,
1438 printername,
1439 user;
1440
1441 /* parse the command arguments */
1442 if (argc != 3)
1443 {
1444 printf ("Usage: %s <printer> <driver>\n", argv[0]);
1445 return WERR_OK;
1446 }
1447
1448 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1449 strupper_m(servername);
1450 slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
1451 fstrcpy(user, cli->auth->user_name);
1452
1453 /* Get a printer handle */
1454
1455 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1456 PRINTER_ALL_ACCESS,
1457 servername, user, &pol);
1458
1459 if (!W_ERROR_IS_OK(result))
1460 goto done;
1461
1462 opened_hnd = True;
1463
1464 /* Get printer info */
1465
1466 ZERO_STRUCT (info2);
1467 ctr.printers_2 = &info2;
1468
1469 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
1470
1471 if (!W_ERROR_IS_OK(result)) {
1472 printf ("Unable to retrieve printer information!\n");
1473 goto done;
1474 }
1475
1476 /* Set the printer driver */
1477
1478 init_unistr(&ctr.printers_2->drivername, argv[2]);
1479
1480 result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
1481
1482 if (!W_ERROR_IS_OK(result)) {
1483 printf("SetPrinter call failed!\n");
1484 goto done;;
1485 }
1486
1487 printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1488
1489done:
1490 /* Cleanup */
1491
1492 if (opened_hnd)
1493 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
1494
1495 return result;
1496}
1497
1498
1499/****************************************************************************
1500****************************************************************************/
1501
1502static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
1503 TALLOC_CTX *mem_ctx,
1504 int argc, const char **argv)
1505{
1506 WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
1507
1508 int i;
1509 int vers = -1;
1510
1511 const char *arch = NULL;
1512
1513 /* parse the command arguments */
1514 if (argc < 2 || argc > 4) {
1515 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
1516 return WERR_OK;
1517 }
1518
1519 if (argc >= 3)
1520 arch = argv[2];
1521 if (argc == 4)
1522 vers = atoi (argv[3]);
1523
1524
1525 /* delete the driver for all architectures */
1526 for (i=0; archi_table[i].long_archi; i++) {
1527
1528 if (arch && !strequal( archi_table[i].long_archi, arch))
1529 continue;
1530
1531 if (vers >= 0 && archi_table[i].version != vers)
1532 continue;
1533
1534 /* make the call to remove the driver */
1535 result = rpccli_spoolss_deleteprinterdriverex(
1536 cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
1537
1538 if ( !W_ERROR_IS_OK(result) )
1539 {
1540 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1541 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
1542 argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
1543 }
1544 }
1545 else
1546 {
1547 printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
1548 archi_table[i].long_archi, archi_table[i].version);
1549 ret = WERR_OK;
1550 }
1551 }
1552
1553 return ret;
1554}
1555
1556
1557/****************************************************************************
1558****************************************************************************/
1559
1560static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
1561 TALLOC_CTX *mem_ctx,
1562 int argc, const char **argv)
1563{
1564 WERROR result = WERR_OK;
1565 fstring servername;
1566 int i;
1567
1568 /* parse the command arguments */
1569 if (argc != 2) {
1570 printf ("Usage: %s <driver>\n", argv[0]);
1571 return WERR_OK;
1572 }
1573
1574 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
1575 strupper_m(servername);
1576
1577 /* delete the driver for all architectures */
1578 for (i=0; archi_table[i].long_archi; i++) {
1579 /* make the call to remove the driver */
1580 result = rpccli_spoolss_deleteprinterdriver(
1581 cli, mem_ctx, archi_table[i].long_archi, argv[1]);
1582
1583 if ( !W_ERROR_IS_OK(result) ) {
1584 if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
1585 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
1586 argv[1], archi_table[i].long_archi,
1587 W_ERROR_V(result));
1588 }
1589 } else {
1590 printf ("Driver %s removed for arch [%s].\n", argv[1],
1591 archi_table[i].long_archi);
1592 }
1593 }
1594
1595 return result;
1596}
1597
1598/****************************************************************************
1599****************************************************************************/
1600
1601static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
1602 TALLOC_CTX *mem_ctx,
1603 int argc, const char **argv)
1604{
1605 WERROR result;
1606 char *servername = NULL, *environment = NULL;
1607 fstring procdir;
1608
1609 /* parse the command arguments */
1610 if (argc > 2) {
1611 printf ("Usage: %s [environment]\n", argv[0]);
1612 return WERR_OK;
1613 }
1614
1615 if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
1616 return WERR_NOMEM;
1617 strupper_m(servername);
1618
1619 if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
1620 PRINTER_DRIVER_ARCHITECTURE) < 0) {
1621 SAFE_FREE(servername);
1622 return WERR_NOMEM;
1623 }
1624
1625 result = rpccli_spoolss_getprintprocessordirectory(
1626 cli, mem_ctx, servername, environment, procdir);
1627
1628 if (W_ERROR_IS_OK(result))
1629 printf("%s\n", procdir);
1630
1631 SAFE_FREE(servername);
1632 SAFE_FREE(environment);
1633
1634 return result;
1635}
1636
1637/****************************************************************************
1638****************************************************************************/
1639
1640static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1641 int argc, const char **argv)
1642{
1643 POLICY_HND handle;
1644 WERROR werror;
1645 char *servername = NULL, *printername = NULL;
1646 FORM form;
1647 bool got_handle = False;
1648
1649 /* Parse the command arguments */
1650
1651 if (argc != 3) {
1652 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1653 return WERR_OK;
1654 }
1655
1656 /* Get a printer handle */
1657
1658 if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
1659 return WERR_NOMEM;
1660 }
1661 strupper_m(servername);
1662 if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
1663 SAFE_FREE(servername);
1664 return WERR_NOMEM;
1665 }
1666
1667 werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
1668 PRINTER_ALL_ACCESS,
1669 servername, cli->auth->user_name,
1670 &handle);
1671
1672 if (!W_ERROR_IS_OK(werror))
1673 goto done;
1674
1675 got_handle = True;
1676
1677 /* Dummy up some values for the form data */
1678
1679 form.flags = FORM_USER;
1680 form.size_x = form.size_y = 100;
1681 form.left = 0;
1682 form.top = 10;
1683 form.right = 20;
1684 form.bottom = 30;
1685
1686 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1687
1688 /* Add the form */
1689
1690
1691 werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
1692
1693 done:
1694 if (got_handle)
1695 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1696
1697 SAFE_FREE(servername);
1698 SAFE_FREE(printername);
1699
1700 return werror;
1701}
1702
1703/****************************************************************************
1704****************************************************************************/
1705
1706static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1707 int argc, const char **argv)
1708{
1709 POLICY_HND handle;
1710 WERROR werror;
1711 char *servername = NULL, *printername = NULL;
1712 FORM form;
1713 bool got_handle = False;
1714
1715 /* Parse the command arguments */
1716
1717 if (argc != 3) {
1718 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1719 return WERR_OK;
1720 }
1721
1722 /* Get a printer handle */
1723
1724 if (asprintf(&servername, "\\\\%s", cli->desthost)) {
1725 return WERR_NOMEM;
1726 }
1727 strupper_m(servername);
1728 if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
1729 SAFE_FREE(servername);
1730 return WERR_NOMEM;
1731 }
1732
1733 werror = rpccli_spoolss_open_printer_ex(
1734 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1735 servername, cli->auth->user_name, &handle);
1736
1737 if (!W_ERROR_IS_OK(werror))
1738 goto done;
1739
1740 got_handle = True;
1741
1742 /* Dummy up some values for the form data */
1743
1744 form.flags = FORM_PRINTER;
1745 form.size_x = form.size_y = 100;
1746 form.left = 0;
1747 form.top = 1000;
1748 form.right = 2000;
1749 form.bottom = 3000;
1750
1751 init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
1752
1753 /* Set the form */
1754
1755 werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
1756
1757 done:
1758 if (got_handle)
1759 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1760
1761 SAFE_FREE(servername);
1762 SAFE_FREE(printername);
1763
1764 return werror;
1765}
1766
1767/****************************************************************************
1768****************************************************************************/
1769
1770static const char *get_form_flag(int form_flag)
1771{
1772 switch (form_flag) {
1773 case FORM_USER:
1774 return "FORM_USER";
1775 case FORM_BUILTIN:
1776 return "FORM_BUILTIN";
1777 case FORM_PRINTER:
1778 return "FORM_PRINTER";
1779 default:
1780 return "unknown";
1781 }
1782}
1783
1784/****************************************************************************
1785****************************************************************************/
1786
1787static void display_form(FORM_1 *form)
1788{
1789 fstring form_name = "";
1790
1791 if (form->name.buffer)
1792 rpcstr_pull(form_name, form->name.buffer,
1793 sizeof(form_name), -1, STR_TERMINATE);
1794
1795 printf("%s\n" \
1796 "\tflag: %s (%d)\n" \
1797 "\twidth: %d, length: %d\n" \
1798 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
1799 form_name, get_form_flag(form->flag), form->flag,
1800 form->width, form->length,
1801 form->left, form->right,
1802 form->top, form->bottom);
1803}
1804
1805/****************************************************************************
1806****************************************************************************/
1807
1808static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
1809 int argc, const char **argv)
1810{
1811 POLICY_HND handle;
1812 WERROR werror;
1813 char *servername = NULL, *printername = NULL;
1814 FORM_1 form;
1815 bool got_handle = False;
1816
1817 /* Parse the command arguments */
1818
1819 if (argc != 3) {
1820 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1821 return WERR_OK;
1822 }
1823
1824 /* Get a printer handle */
1825
1826 if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
1827 return WERR_NOMEM;
1828 }
1829 strupper_m(servername);
1830 if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
1831 SAFE_FREE(servername);
1832 return WERR_NOMEM;
1833 }
1834
1835 werror = rpccli_spoolss_open_printer_ex(
1836 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1837 servername, cli->auth->user_name, &handle);
1838
1839 if (!W_ERROR_IS_OK(werror))
1840 goto done;
1841
1842 got_handle = True;
1843
1844 /* Get the form */
1845
1846 werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
1847
1848 if (!W_ERROR_IS_OK(werror))
1849 goto done;
1850
1851 display_form(&form);
1852
1853 done:
1854 if (got_handle)
1855 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1856
1857 SAFE_FREE(servername);
1858 SAFE_FREE(printername);
1859
1860 return werror;
1861}
1862
1863/****************************************************************************
1864****************************************************************************/
1865
1866static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
1867 TALLOC_CTX *mem_ctx, int argc,
1868 const char **argv)
1869{
1870 POLICY_HND handle;
1871 WERROR werror;
1872 char *servername = NULL, *printername = NULL;
1873 bool got_handle = False;
1874
1875 /* Parse the command arguments */
1876
1877 if (argc != 3) {
1878 printf ("Usage: %s <printer> <formname>\n", argv[0]);
1879 return WERR_OK;
1880 }
1881
1882 /* Get a printer handle */
1883
1884 if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
1885 return WERR_NOMEM;
1886 }
1887 strupper_m(servername);
1888 if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
1889 SAFE_FREE(servername);
1890 return WERR_NOMEM;
1891 }
1892
1893 werror = rpccli_spoolss_open_printer_ex(
1894 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1895 servername, cli->auth->user_name, &handle);
1896
1897 if (!W_ERROR_IS_OK(werror))
1898 goto done;
1899
1900 got_handle = True;
1901
1902 /* Delete the form */
1903
1904 werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
1905
1906 done:
1907 if (got_handle)
1908 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1909
1910 SAFE_FREE(servername);
1911 SAFE_FREE(printername);
1912
1913 return werror;
1914}
1915
1916/****************************************************************************
1917****************************************************************************/
1918
1919static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
1920 TALLOC_CTX *mem_ctx, int argc,
1921 const char **argv)
1922{
1923 POLICY_HND handle;
1924 WERROR werror;
1925 char *servername = NULL, *printername = NULL;
1926 bool got_handle = False;
1927 uint32 num_forms, level = 1, i;
1928 FORM_1 *forms;
1929
1930 /* Parse the command arguments */
1931
1932 if (argc != 2) {
1933 printf ("Usage: %s <printer>\n", argv[0]);
1934 return WERR_OK;
1935 }
1936
1937 /* Get a printer handle */
1938
1939 if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
1940 return WERR_NOMEM;
1941 }
1942 strupper_m(servername);
1943 if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
1944 SAFE_FREE(servername);
1945 return WERR_NOMEM;
1946 }
1947
1948 werror = rpccli_spoolss_open_printer_ex(
1949 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
1950 servername, cli->auth->user_name, &handle);
1951
1952 if (!W_ERROR_IS_OK(werror))
1953 goto done;
1954
1955 got_handle = True;
1956
1957 /* Enumerate forms */
1958
1959 werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
1960
1961 if (!W_ERROR_IS_OK(werror))
1962 goto done;
1963
1964 /* Display output */
1965
1966 for (i = 0; i < num_forms; i++) {
1967
1968 display_form(&forms[i]);
1969
1970 }
1971
1972 done:
1973 if (got_handle)
1974 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
1975
1976 SAFE_FREE(servername);
1977 SAFE_FREE(printername);
1978
1979 return werror;
1980}
1981
1982/****************************************************************************
1983****************************************************************************/
1984
1985static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
1986 TALLOC_CTX *mem_ctx,
1987 int argc, const char **argv)
1988{
1989 WERROR result;
1990 fstring servername, printername, user;
1991 POLICY_HND pol;
1992 bool opened_hnd = False;
1993 PRINTER_INFO_CTR ctr;
1994 PRINTER_INFO_0 info;
1995 REGISTRY_VALUE value;
1996 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1997
1998 /* parse the command arguments */
1999 if (argc < 5) {
2000 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2001 " <value> <data>\n",
2002 argv[0]);
2003 result = WERR_INVALID_PARAM;
2004 goto done;
2005 }
2006
2007 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2008 strupper_m(servername);
2009 slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
2010 fstrcpy(user, cli->auth->user_name);
2011
2012 value.type = REG_NONE;
2013
2014 if (strequal(argv[2], "string")) {
2015 value.type = REG_SZ;
2016 }
2017
2018 if (strequal(argv[2], "binary")) {
2019 value.type = REG_BINARY;
2020 }
2021
2022 if (strequal(argv[2], "dword")) {
2023 value.type = REG_DWORD;
2024 }
2025
2026 if (strequal(argv[2], "multistring")) {
2027 value.type = REG_MULTI_SZ;
2028 }
2029
2030 if (value.type == REG_NONE) {
2031 printf("Unknown data type: %s\n", argv[2]);
2032 result = WERR_INVALID_PARAM;
2033 goto done;
2034 }
2035
2036 /* get a printer handle */
2037 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
2038 MAXIMUM_ALLOWED_ACCESS, servername,
2039 user, &pol);
2040 if (!W_ERROR_IS_OK(result))
2041 goto done;
2042
2043 opened_hnd = True;
2044
2045 ctr.printers_0 = &info;
2046
2047 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2048
2049 if (!W_ERROR_IS_OK(result))
2050 goto done;
2051
2052 printf("%s\n", current_timestring(tmp_ctx, True));
2053 printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
2054
2055 /* Set the printer data */
2056
2057 fstrcpy(value.valuename, argv[3]);
2058
2059 switch (value.type) {
2060 case REG_SZ: {
2061 UNISTR2 data;
2062 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
2063 value.size = data.uni_str_len * 2;
2064 if (value.size) {
2065 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
2066 value.size);
2067 } else {
2068 value.data_p = NULL;
2069 }
2070 break;
2071 }
2072 case REG_DWORD: {
2073 uint32 data = strtoul(argv[4], NULL, 10);
2074 value.size = sizeof(data);
2075 if (sizeof(data)) {
2076 value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
2077 sizeof(data));
2078 } else {
2079 value.data_p = NULL;
2080 }
2081 break;
2082 }
2083 case REG_BINARY: {
2084 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
2085 value.data_p = data.data;
2086 value.size = data.length;
2087 break;
2088 }
2089 case REG_MULTI_SZ: {
2090 int i;
2091 size_t len = 0;
2092 char *p;
2093
2094 for (i=4; i<argc; i++) {
2095 if (strcmp(argv[i], "NULL") == 0) {
2096 argv[i] = "";
2097 }
2098 len += strlen(argv[i])+1;
2099 }
2100
2101 value.size = len*2;
2102 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
2103 if (value.data_p == NULL) {
2104 result = WERR_NOMEM;
2105 goto done;
2106 }
2107
2108 p = (char *)value.data_p;
2109 len = value.size;
2110 for (i=4; i<argc; i++) {
2111 size_t l = (strlen(argv[i])+1)*2;
2112 rpcstr_push(p, argv[i], len, STR_TERMINATE);
2113 p += l;
2114 len -= l;
2115 }
2116 SMB_ASSERT(len == 0);
2117 break;
2118 }
2119 default:
2120 printf("Unknown data type: %s\n", argv[2]);
2121 result = WERR_INVALID_PARAM;
2122 goto done;
2123 }
2124
2125 result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
2126
2127 if (!W_ERROR_IS_OK(result)) {
2128 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2129 goto done;
2130 }
2131 printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2132
2133 result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
2134
2135 if (!W_ERROR_IS_OK(result))
2136 goto done;
2137
2138 printf("%s\n", current_timestring(tmp_ctx, True));
2139 printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
2140
2141done:
2142 /* cleanup */
2143 TALLOC_FREE(tmp_ctx);
2144 if (opened_hnd)
2145 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
2146
2147 return result;
2148}
2149
2150/****************************************************************************
2151****************************************************************************/
2152
2153static void display_job_info_1(JOB_INFO_1 *job)
2154{
2155 fstring username = "", document = "", text_status = "";
2156
2157 rpcstr_pull(username, job->username.buffer,
2158 sizeof(username), -1, STR_TERMINATE);
2159
2160 rpcstr_pull(document, job->document.buffer,
2161 sizeof(document), -1, STR_TERMINATE);
2162
2163 rpcstr_pull(text_status, job->text_status.buffer,
2164 sizeof(text_status), -1, STR_TERMINATE);
2165
2166 printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
2167 username, document, text_status, job->pagesprinted,
2168 job->totalpages);
2169}
2170
2171/****************************************************************************
2172****************************************************************************/
2173
2174static void display_job_info_2(JOB_INFO_2 *job)
2175{
2176 fstring username = "", document = "", text_status = "";
2177
2178 rpcstr_pull(username, job->username.buffer,
2179 sizeof(username), -1, STR_TERMINATE);
2180
2181 rpcstr_pull(document, job->document.buffer,
2182 sizeof(document), -1, STR_TERMINATE);
2183
2184 rpcstr_pull(text_status, job->text_status.buffer,
2185 sizeof(text_status), -1, STR_TERMINATE);
2186
2187 printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
2188 username, document, text_status, job->pagesprinted,
2189 job->totalpages, job->size);
2190}
2191
2192/****************************************************************************
2193****************************************************************************/
2194
2195static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2196 TALLOC_CTX *mem_ctx, int argc,
2197 const char **argv)
2198{
2199 WERROR result;
2200 uint32 level = 1, num_jobs, i;
2201 bool got_hnd = False;
2202 char *printername = NULL;
2203 fstring servername, user;
2204 POLICY_HND hnd;
2205 JOB_INFO_CTR ctr;
2206
2207 if (argc < 2 || argc > 3) {
2208 printf("Usage: %s printername [level]\n", argv[0]);
2209 return WERR_OK;
2210 }
2211
2212 if (argc == 3)
2213 level = atoi(argv[2]);
2214
2215 /* Open printer handle */
2216
2217 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2218 strupper_m(servername);
2219 fstrcpy(user, cli->auth->user_name);
2220 printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
2221 if (!printername) {
2222 return WERR_NOMEM;
2223 }
2224 strupper_m(printername);
2225 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2226 if (!printername) {
2227 return WERR_NOMEM;
2228 }
2229
2230 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2231 "", MAXIMUM_ALLOWED_ACCESS,
2232 servername, user, &hnd);
2233
2234 if (!W_ERROR_IS_OK(result))
2235 goto done;
2236
2237 got_hnd = True;
2238
2239 /* Enumerate ports */
2240
2241 result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
2242 &num_jobs, &ctr);
2243
2244 if (!W_ERROR_IS_OK(result))
2245 goto done;
2246
2247 for (i = 0; i < num_jobs; i++) {
2248 switch(level) {
2249 case 1:
2250 display_job_info_1(&ctr.job.job_info_1[i]);
2251 break;
2252 case 2:
2253 display_job_info_2(&ctr.job.job_info_2[i]);
2254 break;
2255 default:
2256 d_printf("unknown info level %d\n", level);
2257 break;
2258 }
2259 }
2260
2261done:
2262 if (got_hnd)
2263 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2264
2265 return result;
2266}
2267
2268/****************************************************************************
2269****************************************************************************/
2270
2271static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
2272 TALLOC_CTX *mem_ctx, int argc,
2273 const char **argv)
2274{
2275 WERROR result;
2276 uint32 i=0, val_needed, data_needed;
2277 bool got_hnd = False;
2278 char *printername = NULL;
2279 fstring servername, user;
2280 POLICY_HND hnd;
2281
2282 if (argc != 2) {
2283 printf("Usage: %s printername\n", argv[0]);
2284 return WERR_OK;
2285 }
2286
2287 /* Open printer handle */
2288
2289 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2290 strupper_m(servername);
2291 fstrcpy(user, cli->auth->user_name);
2292 printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
2293 if (!printername) {
2294 return WERR_NOMEM;
2295 }
2296 strupper_m(printername);
2297 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2298 if (!printername) {
2299 return WERR_NOMEM;
2300 }
2301
2302 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2303 "", MAXIMUM_ALLOWED_ACCESS,
2304 servername, user, &hnd);
2305
2306 if (!W_ERROR_IS_OK(result))
2307 goto done;
2308
2309 got_hnd = True;
2310
2311 /* Enumerate data */
2312
2313 result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
2314 &val_needed, &data_needed,
2315 NULL);
2316 while (W_ERROR_IS_OK(result)) {
2317 REGISTRY_VALUE value;
2318 result = rpccli_spoolss_enumprinterdata(
2319 cli, mem_ctx, &hnd, i++, val_needed,
2320 data_needed, 0, 0, &value);
2321 if (W_ERROR_IS_OK(result))
2322 display_reg_value(value);
2323 }
2324 if (W_ERROR_V(result) == ERRnomoreitems)
2325 result = W_ERROR(ERRsuccess);
2326
2327done:
2328 if (got_hnd)
2329 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2330
2331 return result;
2332}
2333
2334/****************************************************************************
2335****************************************************************************/
2336
2337static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
2338 TALLOC_CTX *mem_ctx, int argc,
2339 const char **argv)
2340{
2341 WERROR result;
2342 uint32 i;
2343 bool got_hnd = False;
2344 char *printername = NULL;
2345 fstring servername, user;
2346 const char *keyname = NULL;
2347 POLICY_HND hnd;
2348 REGVAL_CTR *ctr = NULL;
2349
2350 if (argc != 3) {
2351 printf("Usage: %s printername <keyname>\n", argv[0]);
2352 return WERR_OK;
2353 }
2354
2355 keyname = argv[2];
2356
2357 /* Open printer handle */
2358
2359 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2360 strupper_m(servername);
2361 fstrcpy(user, cli->auth->user_name);
2362
2363 printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
2364 if (!printername) {
2365 return WERR_NOMEM;
2366 }
2367 strupper_m(printername);
2368 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2369 if (!printername) {
2370 return WERR_NOMEM;
2371 }
2372
2373 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2374 "", MAXIMUM_ALLOWED_ACCESS,
2375 servername, user, &hnd);
2376
2377 if (!W_ERROR_IS_OK(result))
2378 goto done;
2379
2380 got_hnd = True;
2381
2382 /* Enumerate subkeys */
2383
2384 if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
2385 return WERR_NOMEM;
2386
2387 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
2388
2389 if (!W_ERROR_IS_OK(result))
2390 goto done;
2391
2392 for (i=0; i < ctr->num_values; i++) {
2393 display_reg_value(*(ctr->values[i]));
2394 }
2395
2396 TALLOC_FREE( ctr );
2397
2398done:
2399 if (got_hnd)
2400 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2401
2402 return result;
2403}
2404
2405/****************************************************************************
2406****************************************************************************/
2407
2408static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
2409 TALLOC_CTX *mem_ctx, int argc,
2410 const char **argv)
2411{
2412 WERROR result;
2413 bool got_hnd = False;
2414 char *printername = NULL;
2415 fstring servername, user;
2416 const char *keyname = NULL;
2417 POLICY_HND hnd;
2418 uint16 *keylist = NULL, *curkey;
2419
2420 if (argc < 2 || argc > 3) {
2421 printf("Usage: %s printername [keyname]\n", argv[0]);
2422 return WERR_OK;
2423 }
2424
2425 if (argc == 3)
2426 keyname = argv[2];
2427 else
2428 keyname = "";
2429
2430 /* Open printer handle */
2431
2432 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
2433 strupper_m(servername);
2434 fstrcpy(user, cli->auth->user_name);
2435
2436 printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
2437 if (!printername) {
2438 return WERR_NOMEM;
2439 }
2440 strupper_m(printername);
2441 printername = talloc_asprintf_append(printername, "%s", argv[1]);
2442 if (!printername) {
2443 return WERR_NOMEM;
2444 }
2445
2446
2447 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
2448 "", MAXIMUM_ALLOWED_ACCESS,
2449 servername, user, &hnd);
2450
2451 if (!W_ERROR_IS_OK(result))
2452 goto done;
2453
2454 got_hnd = True;
2455
2456 /* Enumerate subkeys */
2457
2458 result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
2459
2460 if (!W_ERROR_IS_OK(result))
2461 goto done;
2462
2463 curkey = keylist;
2464 while (*curkey != 0) {
2465 char *subkey = NULL;
2466 rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
2467 STR_TERMINATE);
2468 if (!subkey) {
2469 break;
2470 }
2471 printf("%s\n", subkey);
2472 curkey += strlen(subkey) + 1;
2473 }
2474
2475done:
2476
2477 SAFE_FREE(keylist);
2478
2479 if (got_hnd)
2480 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2481
2482 return result;
2483}
2484
2485/****************************************************************************
2486****************************************************************************/
2487
2488static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
2489 TALLOC_CTX *mem_ctx, int argc,
2490 const char **argv)
2491{
2492 fstring servername, printername;
2493 POLICY_HND hnd;
2494 bool got_hnd = False;
2495 WERROR result;
2496 SPOOL_NOTIFY_OPTION option;
2497
2498 if (argc != 2) {
2499 printf("Usage: %s printername\n", argv[0]);
2500 result = WERR_OK;
2501 goto done;
2502 }
2503
2504 /* Open printer */
2505
2506 slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
2507 strupper_m(servername);
2508
2509 slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s",
2510 cli->desthost, argv[1]);
2511 strupper_m(printername);
2512
2513 result = rpccli_spoolss_open_printer_ex(
2514 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
2515 servername, cli->auth->user_name, &hnd);
2516
2517 if (!W_ERROR_IS_OK(result)) {
2518 printf("Error opening %s\n", argv[1]);
2519 goto done;
2520 }
2521
2522 got_hnd = True;
2523
2524 /* Create spool options */
2525
2526 ZERO_STRUCT(option);
2527
2528 option.version = 2;
2529 option.option_type_ptr = 1;
2530 option.count = option.ctr.count = 2;
2531
2532 option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
2533 if (option.ctr.type == NULL) {
2534 result = WERR_NOMEM;
2535 goto done;
2536 }
2537
2538 ZERO_STRUCT(option.ctr.type[0]);
2539 option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
2540 option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
2541 option.ctr.type[0].fields_ptr = 1;
2542 option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
2543
2544 ZERO_STRUCT(option.ctr.type[1]);
2545 option.ctr.type[1].type = JOB_NOTIFY_TYPE;
2546 option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
2547 option.ctr.type[1].fields_ptr = 1;
2548 option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
2549
2550 /* Send rffpcnex */
2551
2552 slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
2553 strupper_m(servername);
2554
2555 result = rpccli_spoolss_rffpcnex(
2556 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
2557
2558 if (!W_ERROR_IS_OK(result)) {
2559 printf("Error rffpcnex %s\n", argv[1]);
2560 goto done;
2561 }
2562
2563done:
2564 if (got_hnd)
2565 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
2566
2567 return result;
2568}
2569
2570/****************************************************************************
2571****************************************************************************/
2572
2573static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2574 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2575{
2576 PRINTER_INFO_CTR ctr1, ctr2;
2577 WERROR werror;
2578 TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
2579
2580 printf("Retrieving printer propertiesfor %s...", cli1->desthost);
2581 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
2582 if ( !W_ERROR_IS_OK(werror) ) {
2583 printf("failed (%s)\n", dos_errstr(werror));
2584 talloc_destroy(mem_ctx);
2585 return False;
2586 }
2587 printf("ok\n");
2588
2589 printf("Retrieving printer properties for %s...", cli2->desthost);
2590 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
2591 if ( !W_ERROR_IS_OK(werror) ) {
2592 printf("failed (%s)\n", dos_errstr(werror));
2593 talloc_destroy(mem_ctx);
2594 return False;
2595 }
2596 printf("ok\n");
2597
2598 talloc_destroy(mem_ctx);
2599
2600 return True;
2601}
2602
2603/****************************************************************************
2604****************************************************************************/
2605
2606static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
2607 struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
2608{
2609 PRINTER_INFO_CTR ctr1, ctr2;
2610 WERROR werror;
2611 TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
2612 SEC_DESC *sd1, *sd2;
2613 bool result = True;
2614
2615
2616 printf("Retrieving printer security for %s...", cli1->desthost);
2617 werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
2618 if ( !W_ERROR_IS_OK(werror) ) {
2619 printf("failed (%s)\n", dos_errstr(werror));
2620 result = False;
2621 goto done;
2622 }
2623 printf("ok\n");
2624
2625 printf("Retrieving printer security for %s...", cli2->desthost);
2626 werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
2627 if ( !W_ERROR_IS_OK(werror) ) {
2628 printf("failed (%s)\n", dos_errstr(werror));
2629 result = False;
2630 goto done;
2631 }
2632 printf("ok\n");
2633
2634
2635 printf("++ ");
2636
2637 if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
2638 printf("NULL PRINTER_INFO_3!\n");
2639 result = False;
2640 goto done;
2641 }
2642
2643 sd1 = ctr1.printers_3->secdesc;
2644 sd2 = ctr2.printers_3->secdesc;
2645
2646 if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
2647 printf("NULL secdesc!\n");
2648 result = False;
2649 goto done;
2650 }
2651
2652 if (!sec_desc_equal( sd1, sd2 ) ) {
2653 printf("Security Descriptors *not* equal!\n");
2654 result = False;
2655 goto done;
2656 }
2657
2658 printf("Security descriptors match\n");
2659
2660done:
2661 talloc_destroy(mem_ctx);
2662 return result;
2663}
2664
2665
2666/****************************************************************************
2667****************************************************************************/
2668
2669static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
2670 TALLOC_CTX *mem_ctx, int argc,
2671 const char **argv)
2672{
2673 fstring printername, servername1, servername2;
2674 char *printername_path = NULL;
2675 struct cli_state *cli_server1 = rpc_pipe_np_smb_conn(cli);
2676 struct cli_state *cli_server2 = NULL;
2677 struct rpc_pipe_client *cli2 = NULL;
2678 POLICY_HND hPrinter1, hPrinter2;
2679 NTSTATUS nt_status;
2680 WERROR werror;
2681
2682 if ( argc != 3 ) {
2683 printf("Usage: %s <printer> <server>\n", argv[0]);
2684 return WERR_OK;
2685 }
2686
2687 fstrcpy( printername, argv[1] );
2688
2689 fstrcpy( servername1, cli->desthost );
2690 fstrcpy( servername2, argv[2] );
2691 strupper_m( servername1 );
2692 strupper_m( servername2 );
2693
2694 /* first get the connection to the remote server */
2695
2696 nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
2697 NULL, 0,
2698 "IPC$", "IPC",
2699 get_cmdline_auth_info_username(),
2700 lp_workgroup(),
2701 get_cmdline_auth_info_password(),
2702 get_cmdline_auth_info_use_kerberos() ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
2703 get_cmdline_auth_info_signing_state(), NULL);
2704
2705 if ( !NT_STATUS_IS_OK(nt_status) )
2706 return WERR_GENERAL_FAILURE;
2707
2708 nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
2709 &cli2);
2710 if (!NT_STATUS_IS_OK(nt_status)) {
2711 printf("failed to open spoolss pipe on server %s (%s)\n",
2712 servername2, nt_errstr(nt_status));
2713 return WERR_GENERAL_FAILURE;
2714 }
2715
2716 /* now open up both printers */
2717
2718 printername_path = talloc_asprintf(mem_ctx,
2719 "\\\\%s\\%s",
2720 servername1,
2721 printername);
2722 if (!printername_path) {
2723 return WERR_NOMEM;
2724 }
2725 printf("Opening %s...", printername_path);
2726 werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
2727 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
2728 if ( !W_ERROR_IS_OK(werror) ) {
2729 printf("failed (%s)\n", dos_errstr(werror));
2730 goto done;
2731 }
2732 printf("ok\n");
2733
2734 printername_path = talloc_asprintf(mem_ctx,
2735 "\\\\%s\\%s",
2736 servername2,
2737 printername);
2738 if (!printername_path) {
2739 return WERR_NOMEM;
2740 }
2741 printf("Opening %s...", printername_path);
2742 werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
2743 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
2744 if ( !W_ERROR_IS_OK(werror) ) {
2745 printf("failed (%s)\n", dos_errstr(werror));
2746 goto done;
2747 }
2748 printf("ok\n");
2749
2750 compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
2751 compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
2752#if 0
2753 compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
2754#endif
2755
2756
2757done:
2758 /* cleanup */
2759
2760 printf("Closing printers...");
2761 rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
2762 rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
2763 printf("ok\n");
2764
2765 /* close the second remote connection */
2766
2767 cli_shutdown( cli_server2 );
2768 return WERR_OK;
2769}
2770
2771/* List of commands exported by this module */
2772struct cmd_set spoolss_commands[] = {
2773
2774 { "SPOOLSS" },
2775
2776 { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
2777 { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
2778 { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
2779 { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
2780 { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
2781 { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
2782 { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
2783 { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
2784 { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
2785 { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
2786 { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
2787 { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
2788 { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
2789 { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
2790 { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
2791 { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
2792 { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
2793 { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
2794 { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
2795 { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
2796 { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
2797 { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
2798 { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
2799 { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
2800 { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
2801 { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
2802 { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
2803 { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
2804 { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },
2805
2806 { NULL }
2807};
Note: See TracBrowser for help on using the repository browser.