Line data Source code
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 : Copyright (C) Guenther Deschner 2009
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include "rpcclient.h"
27 : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
28 : #include "../librpc/gen_ndr/ndr_spoolss.h"
29 : #include "rpc_client/cli_spoolss.h"
30 : #include "rpc_client/init_spoolss.h"
31 : #include "nt_printing.h"
32 : #include "../libcli/security/display_sec.h"
33 : #include "../libcli/security/security_descriptor.h"
34 : #include "../libcli/registry/util_reg.h"
35 : #include "libsmb/libsmb.h"
36 : #include "lib/util/smb_strtox.h"
37 : #include "lib/util/string_wrappers.h"
38 : #include "lib/cmdline/cmdline.h"
39 :
40 : #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
41 : { \
42 : _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
43 : _cli->srv_name_slash, _arg); \
44 : W_ERROR_HAVE_NO_MEMORY(_printername); \
45 : }
46 :
47 :
48 : /**
49 : * @file
50 : *
51 : * rpcclient module for SPOOLSS rpc pipe.
52 : *
53 : * This generally just parses and checks command lines, and then calls
54 : * a cli_spoolss function.
55 : **/
56 :
57 : /****************************************************************************
58 : function to do the mapping between the long architecture name and
59 : the short one.
60 : ****************************************************************************/
61 :
62 0 : static const char *cmd_spoolss_get_short_archi(const char *long_archi)
63 : {
64 0 : int i=-1;
65 :
66 0 : DEBUG(107,("Getting architecture dependent directory\n"));
67 : do {
68 0 : i++;
69 0 : } while ( (archi_table[i].long_archi!=NULL ) &&
70 0 : strcasecmp_m(long_archi, archi_table[i].long_archi) );
71 :
72 0 : if (archi_table[i].long_archi==NULL) {
73 0 : DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
74 0 : return NULL;
75 : }
76 :
77 : /* this might be client code - but shouldn't this be an fstrcpy etc? */
78 :
79 :
80 0 : DEBUGADD(108,("index: [%d]\n", i));
81 0 : DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
82 0 : DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
83 :
84 0 : return archi_table[i].short_archi;
85 : }
86 :
87 : /****************************************************************************
88 : ****************************************************************************/
89 :
90 0 : static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
91 : TALLOC_CTX *mem_ctx,
92 : int argc, const char **argv)
93 : {
94 : WERROR werror;
95 : struct policy_handle hnd;
96 0 : uint32_t access_mask = PRINTER_ALL_ACCESS;
97 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
98 :
99 0 : if (argc < 2) {
100 0 : printf("Usage: %s <printername> [access_mask]\n", argv[0]);
101 0 : return WERR_OK;
102 : }
103 :
104 0 : if (argc >= 3) {
105 0 : sscanf(argv[2], "%x", &access_mask);
106 : }
107 :
108 : /* Open the printer handle */
109 :
110 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
111 0 : argv[1],
112 : access_mask,
113 : &hnd);
114 0 : if (W_ERROR_IS_OK(werror)) {
115 0 : printf("Printer %s opened successfully\n", argv[1]);
116 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
117 :
118 0 : if (!W_ERROR_IS_OK(werror)) {
119 0 : printf("Error closing printer handle! (%s)\n",
120 : get_dos_error_msg(werror));
121 : }
122 : }
123 :
124 0 : return werror;
125 : }
126 :
127 : /****************************************************************************
128 : ****************************************************************************/
129 :
130 0 : static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
131 : TALLOC_CTX *mem_ctx,
132 : int argc, const char **argv)
133 : {
134 : WERROR werror;
135 : struct policy_handle hnd;
136 0 : uint32_t access_mask = PRINTER_ALL_ACCESS;
137 : NTSTATUS status;
138 : struct spoolss_DevmodeContainer devmode_ctr;
139 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
140 :
141 0 : ZERO_STRUCT(devmode_ctr);
142 :
143 0 : if (argc < 2) {
144 0 : printf("Usage: %s <printername> [access_mask]\n", argv[0]);
145 0 : return WERR_OK;
146 : }
147 :
148 0 : if (argc >= 3) {
149 0 : sscanf(argv[2], "%x", &access_mask);
150 : }
151 :
152 : /* Open the printer handle */
153 :
154 0 : status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
155 0 : argv[1],
156 : NULL,
157 : devmode_ctr,
158 : access_mask,
159 : &hnd,
160 : &werror);
161 0 : if (!NT_STATUS_IS_OK(status)) {
162 0 : return ntstatus_to_werror(status);
163 : }
164 0 : if (W_ERROR_IS_OK(werror)) {
165 0 : printf("Printer %s opened successfully\n", argv[1]);
166 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
167 :
168 0 : if (!W_ERROR_IS_OK(werror)) {
169 0 : printf("Error closing printer handle! (%s)\n",
170 : get_dos_error_msg(werror));
171 : }
172 : }
173 :
174 0 : return werror;
175 : }
176 :
177 : /****************************************************************************
178 : ****************************************************************************/
179 :
180 0 : static void display_print_info0(struct spoolss_PrinterInfo0 *r)
181 : {
182 0 : if (!r)
183 0 : return;
184 :
185 0 : printf("\tprintername:[%s]\n", r->printername);
186 0 : printf("\tservername:[%s]\n", r->servername);
187 0 : printf("\tcjobs:[0x%x]\n", r->cjobs);
188 0 : printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
189 0 : printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
190 0 : printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
191 0 : r->time.day, r->time.day_of_week);
192 0 : printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
193 0 : r->time.second, r->time.millisecond);
194 :
195 0 : printf("\tglobal_counter:[0x%x]\n", r->global_counter);
196 0 : printf("\ttotal_pages:[0x%x]\n", r->total_pages);
197 :
198 0 : printf("\tversion:[0x%x]\n", r->version);
199 0 : printf("\tfree_build:[0x%x]\n", r->free_build);
200 0 : printf("\tspooling:[0x%x]\n", r->spooling);
201 0 : printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
202 0 : printf("\tsession_counter:[0x%x]\n", r->session_counter);
203 0 : printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
204 0 : printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
205 0 : printf("\tjob_error:[0x%x]\n", r->job_error);
206 0 : printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
207 0 : printf("\tprocessor_type:[0x%x]\n", r->processor_type);
208 0 : printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
209 0 : printf("\tchange_id:[0x%x]\n", r->change_id);
210 0 : printf("\tlast_error: %s\n", win_errstr(r->last_error));
211 0 : printf("\tstatus:[0x%x]\n", r->status);
212 0 : printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
213 0 : printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
214 0 : printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
215 0 : printf("\tprocessor_level:[0x%x]\n", r->processor_level);
216 0 : printf("\tref_ic:[0x%x]\n", r->ref_ic);
217 0 : printf("\treserved2:[0x%x]\n", r->reserved2);
218 0 : printf("\treserved3:[0x%x]\n", r->reserved3);
219 :
220 0 : printf("\n");
221 : }
222 :
223 : /****************************************************************************
224 : ****************************************************************************/
225 :
226 0 : static void display_print_info1(struct spoolss_PrinterInfo1 *r)
227 : {
228 0 : printf("\tflags:[0x%x]\n", r->flags);
229 0 : printf("\tname:[%s]\n", r->name);
230 0 : printf("\tdescription:[%s]\n", r->description);
231 0 : printf("\tcomment:[%s]\n", r->comment);
232 :
233 0 : printf("\n");
234 0 : }
235 :
236 : /****************************************************************************
237 : ****************************************************************************/
238 :
239 0 : static void display_print_info2(struct spoolss_PrinterInfo2 *r)
240 : {
241 0 : printf("\tservername:[%s]\n", r->servername);
242 0 : printf("\tprintername:[%s]\n", r->printername);
243 0 : printf("\tsharename:[%s]\n", r->sharename);
244 0 : printf("\tportname:[%s]\n", r->portname);
245 0 : printf("\tdrivername:[%s]\n", r->drivername);
246 0 : printf("\tcomment:[%s]\n", r->comment);
247 0 : printf("\tlocation:[%s]\n", r->location);
248 0 : printf("\tsepfile:[%s]\n", r->sepfile);
249 0 : printf("\tprintprocessor:[%s]\n", r->printprocessor);
250 0 : printf("\tdatatype:[%s]\n", r->datatype);
251 0 : printf("\tparameters:[%s]\n", r->parameters);
252 0 : printf("\tattributes:[0x%x]\n", r->attributes);
253 0 : printf("\tpriority:[0x%x]\n", r->priority);
254 0 : printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
255 0 : printf("\tstarttime:[0x%x]\n", r->starttime);
256 0 : printf("\tuntiltime:[0x%x]\n", r->untiltime);
257 0 : printf("\tstatus:[0x%x]\n", r->status);
258 0 : printf("\tcjobs:[0x%x]\n", r->cjobs);
259 0 : printf("\taverageppm:[0x%x]\n", r->averageppm);
260 :
261 0 : if (r->secdesc)
262 0 : display_sec_desc(r->secdesc);
263 :
264 0 : printf("\n");
265 0 : }
266 :
267 : /****************************************************************************
268 : ****************************************************************************/
269 :
270 0 : static void display_print_info3(struct spoolss_PrinterInfo3 *r)
271 : {
272 0 : display_sec_desc(r->secdesc);
273 :
274 0 : printf("\n");
275 0 : }
276 :
277 : /****************************************************************************
278 : ****************************************************************************/
279 :
280 0 : static void display_print_info4(struct spoolss_PrinterInfo4 *r)
281 : {
282 0 : printf("\tservername:[%s]\n", r->servername);
283 0 : printf("\tprintername:[%s]\n", r->printername);
284 0 : printf("\tattributes:[0x%x]\n", r->attributes);
285 0 : printf("\n");
286 0 : }
287 :
288 : /****************************************************************************
289 : ****************************************************************************/
290 :
291 0 : static void display_print_info5(struct spoolss_PrinterInfo5 *r)
292 : {
293 0 : printf("\tprintername:[%s]\n", r->printername);
294 0 : printf("\tportname:[%s]\n", r->portname);
295 0 : printf("\tattributes:[0x%x]\n", r->attributes);
296 0 : printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
297 0 : printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
298 0 : printf("\n");
299 0 : }
300 :
301 : /****************************************************************************
302 : ****************************************************************************/
303 :
304 0 : static void display_print_info6(struct spoolss_PrinterInfo6 *r)
305 : {
306 0 : printf("\tstatus:[0x%x]\n", r->status);
307 0 : printf("\n");
308 0 : }
309 :
310 : /****************************************************************************
311 : ****************************************************************************/
312 :
313 0 : static void display_print_info7(struct spoolss_PrinterInfo7 *r)
314 : {
315 0 : printf("\tguid:[%s]\n", r->guid);
316 0 : printf("\taction:[0x%x]\n", r->action);
317 0 : printf("\n");
318 0 : }
319 :
320 : /****************************************************************************
321 : ****************************************************************************/
322 :
323 0 : static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
324 : TALLOC_CTX *mem_ctx,
325 : int argc, const char **argv)
326 : {
327 : WERROR result;
328 0 : uint32_t level = 1;
329 : union spoolss_PrinterInfo *info;
330 : uint32_t i, count;
331 : const char *name;
332 0 : uint32_t flags = PRINTER_ENUM_LOCAL;
333 :
334 0 : if (argc > 4) {
335 0 : printf("Usage: %s [level] [name] [flags]\n", argv[0]);
336 0 : return WERR_OK;
337 : }
338 :
339 0 : if (argc >= 2) {
340 0 : level = atoi(argv[1]);
341 : }
342 :
343 0 : if (argc >= 3) {
344 0 : name = argv[2];
345 : } else {
346 0 : name = cli->srv_name_slash;
347 : }
348 :
349 0 : if (argc == 4) {
350 0 : flags = atoi(argv[3]);
351 : }
352 :
353 0 : result = rpccli_spoolss_enumprinters(cli, mem_ctx,
354 : flags,
355 : name,
356 : level,
357 : 0,
358 : &count,
359 : &info);
360 0 : if (W_ERROR_IS_OK(result)) {
361 :
362 0 : if (!count) {
363 0 : printf ("No printers returned.\n");
364 0 : goto done;
365 : }
366 :
367 0 : for (i = 0; i < count; i++) {
368 0 : switch (level) {
369 0 : case 0:
370 0 : display_print_info0(&info[i].info0);
371 0 : break;
372 0 : case 1:
373 0 : display_print_info1(&info[i].info1);
374 0 : break;
375 0 : case 2:
376 0 : display_print_info2(&info[i].info2);
377 0 : break;
378 0 : case 3:
379 0 : display_print_info3(&info[i].info3);
380 0 : break;
381 0 : case 4:
382 0 : display_print_info4(&info[i].info4);
383 0 : break;
384 0 : case 5:
385 0 : display_print_info5(&info[i].info5);
386 0 : break;
387 0 : case 6:
388 0 : display_print_info6(&info[i].info6);
389 0 : break;
390 0 : default:
391 0 : printf("unknown info level %d\n", level);
392 0 : goto done;
393 : }
394 : }
395 : }
396 0 : done:
397 :
398 0 : return result;
399 : }
400 :
401 : /****************************************************************************
402 : ****************************************************************************/
403 :
404 0 : static void display_port_info_1(struct spoolss_PortInfo1 *r)
405 : {
406 0 : printf("\tPort Name:\t[%s]\n", r->port_name);
407 0 : }
408 :
409 : /****************************************************************************
410 : ****************************************************************************/
411 :
412 0 : static void display_port_info_2(struct spoolss_PortInfo2 *r)
413 : {
414 0 : printf("\tPort Name:\t[%s]\n", r->port_name);
415 0 : printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
416 0 : printf("\tDescription:\t[%s]\n", r->description);
417 0 : printf("\tPort Type:\t" );
418 0 : if (r->port_type) {
419 0 : int comma = 0; /* hack */
420 0 : printf( "[" );
421 0 : if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
422 0 : printf( "Read" );
423 0 : comma = 1;
424 : }
425 0 : if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
426 0 : printf( "%sWrite", comma ? ", " : "" );
427 0 : comma = 1;
428 : }
429 : /* These two have slightly different interpretations
430 : on 95/98/ME but I'm disregarding that for now */
431 0 : if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
432 0 : printf( "%sRedirected", comma ? ", " : "" );
433 0 : comma = 1;
434 : }
435 0 : if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
436 0 : printf( "%sNet-Attached", comma ? ", " : "" );
437 : }
438 0 : printf( "]\n" );
439 : } else {
440 0 : printf( "[Unset]\n" );
441 : }
442 0 : printf("\tReserved:\t[%d]\n", r->reserved);
443 0 : printf("\n");
444 0 : }
445 :
446 : /****************************************************************************
447 : ****************************************************************************/
448 :
449 0 : static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
450 : TALLOC_CTX *mem_ctx, int argc,
451 : const char **argv)
452 : {
453 : WERROR result;
454 0 : uint32_t level = 1;
455 : uint32_t count;
456 : union spoolss_PortInfo *info;
457 :
458 0 : if (argc > 2) {
459 0 : printf("Usage: %s [level]\n", argv[0]);
460 0 : return WERR_OK;
461 : }
462 :
463 0 : if (argc == 2) {
464 0 : level = atoi(argv[1]);
465 : }
466 :
467 : /* Enumerate ports */
468 :
469 0 : result = rpccli_spoolss_enumports(cli, mem_ctx,
470 0 : cli->srv_name_slash,
471 : level,
472 : 0,
473 : &count,
474 : &info);
475 0 : if (W_ERROR_IS_OK(result)) {
476 : int i;
477 :
478 0 : for (i = 0; i < count; i++) {
479 0 : switch (level) {
480 0 : case 1:
481 0 : display_port_info_1(&info[i].info1);
482 0 : break;
483 0 : case 2:
484 0 : display_port_info_2(&info[i].info2);
485 0 : break;
486 0 : default:
487 0 : printf("unknown info level %d\n", level);
488 0 : break;
489 : }
490 : }
491 : }
492 :
493 0 : return result;
494 : }
495 :
496 : /****************************************************************************
497 : ****************************************************************************/
498 :
499 0 : static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
500 : TALLOC_CTX *mem_ctx,
501 : int argc, const char **argv)
502 : {
503 : struct policy_handle pol;
504 : WERROR result;
505 : NTSTATUS status;
506 0 : uint32_t info_level = 2;
507 : union spoolss_PrinterInfo info;
508 : struct spoolss_SetPrinterInfoCtr info_ctr;
509 : struct spoolss_SetPrinterInfo2 info2;
510 0 : const char *printername, *comment = NULL;
511 : struct spoolss_DevmodeContainer devmode_ctr;
512 : struct sec_desc_buf secdesc_ctr;
513 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
514 :
515 0 : if (argc == 1 || argc > 3) {
516 0 : printf("Usage: %s printername comment\n", argv[0]);
517 :
518 0 : return WERR_OK;
519 : }
520 :
521 : /* Open a printer handle */
522 0 : if (argc == 3) {
523 0 : comment = argv[2];
524 : }
525 :
526 0 : ZERO_STRUCT(devmode_ctr);
527 0 : ZERO_STRUCT(secdesc_ctr);
528 :
529 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
530 :
531 : /* get a printer handle */
532 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
533 : printername,
534 : PRINTER_ALL_ACCESS,
535 : &pol);
536 0 : if (!W_ERROR_IS_OK(result))
537 0 : goto done;
538 :
539 : /* Get printer info */
540 0 : result = rpccli_spoolss_getprinter(cli, mem_ctx,
541 : &pol,
542 : info_level,
543 : 0,
544 : &info);
545 0 : if (!W_ERROR_IS_OK(result))
546 0 : goto done;
547 :
548 :
549 : /* Modify the comment. */
550 0 : spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
551 0 : info2.comment = comment;
552 :
553 0 : info_ctr.level = 2;
554 0 : info_ctr.info.info2 = &info2;
555 :
556 0 : status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
557 : &pol,
558 : &info_ctr,
559 : &devmode_ctr,
560 : &secdesc_ctr,
561 : 0, /* command */
562 : &result);
563 0 : if (!NT_STATUS_IS_OK(status)) {
564 0 : result = ntstatus_to_werror(status);
565 0 : goto done;
566 : }
567 0 : if (W_ERROR_IS_OK(result))
568 0 : printf("Success in setting comment.\n");
569 :
570 0 : done:
571 0 : if (is_valid_policy_hnd(&pol)) {
572 : WERROR _result;
573 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
574 : }
575 :
576 0 : return result;
577 : }
578 :
579 : /****************************************************************************
580 : ****************************************************************************/
581 :
582 0 : static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
583 : TALLOC_CTX *mem_ctx,
584 : int argc, const char **argv)
585 : {
586 : struct policy_handle pol;
587 : WERROR result;
588 : NTSTATUS status;
589 0 : uint32_t info_level = 2;
590 : union spoolss_PrinterInfo info;
591 : const char *printername,
592 0 : *new_printername = NULL;
593 : struct spoolss_SetPrinterInfoCtr info_ctr;
594 : struct spoolss_SetPrinterInfo2 info2;
595 : struct spoolss_DevmodeContainer devmode_ctr;
596 : struct sec_desc_buf secdesc_ctr;
597 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
598 :
599 0 : ZERO_STRUCT(devmode_ctr);
600 0 : ZERO_STRUCT(secdesc_ctr);
601 :
602 0 : if (argc == 1 || argc > 3) {
603 0 : printf("Usage: %s printername new_printername\n", argv[0]);
604 :
605 0 : return WERR_OK;
606 : }
607 :
608 : /* Open a printer handle */
609 0 : if (argc == 3) {
610 0 : new_printername = argv[2];
611 : }
612 :
613 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
614 :
615 : /* get a printer handle */
616 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
617 : printername,
618 : PRINTER_ALL_ACCESS,
619 : &pol);
620 0 : if (!W_ERROR_IS_OK(result))
621 0 : goto done;
622 :
623 : /* Get printer info */
624 0 : result = rpccli_spoolss_getprinter(cli, mem_ctx,
625 : &pol,
626 : info_level,
627 : 0,
628 : &info);
629 0 : if (!W_ERROR_IS_OK(result))
630 0 : goto done;
631 :
632 : /* Modify the printername. */
633 0 : spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
634 0 : info2.printername = new_printername;
635 :
636 0 : info_ctr.level = 2;
637 0 : info_ctr.info.info2 = &info2;
638 :
639 0 : status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
640 : &pol,
641 : &info_ctr,
642 : &devmode_ctr,
643 : &secdesc_ctr,
644 : 0, /* command */
645 : &result);
646 0 : if (!NT_STATUS_IS_OK(status)) {
647 0 : result = ntstatus_to_werror(status);
648 0 : goto done;
649 : }
650 0 : if (W_ERROR_IS_OK(result))
651 0 : printf("Success in setting printername.\n");
652 :
653 0 : done:
654 0 : if (is_valid_policy_hnd(&pol)) {
655 : WERROR _result;
656 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
657 : }
658 :
659 0 : return result;
660 : }
661 :
662 : /****************************************************************************
663 : ****************************************************************************/
664 :
665 0 : static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
666 : TALLOC_CTX *mem_ctx,
667 : int argc, const char **argv)
668 : {
669 : struct policy_handle pol;
670 : WERROR result;
671 0 : uint32_t level = 1;
672 : const char *printername;
673 : union spoolss_PrinterInfo info;
674 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
675 :
676 0 : if (argc == 1 || argc > 3) {
677 0 : printf("Usage: %s <printername> [level]\n", argv[0]);
678 0 : return WERR_OK;
679 : }
680 :
681 : /* Open a printer handle */
682 0 : if (argc == 3) {
683 0 : level = atoi(argv[2]);
684 : }
685 :
686 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
687 :
688 : /* get a printer handle */
689 :
690 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
691 : printername,
692 : SEC_FLAG_MAXIMUM_ALLOWED,
693 : &pol);
694 0 : if (!W_ERROR_IS_OK(result)) {
695 0 : goto done;
696 : }
697 :
698 : /* Get printer info */
699 :
700 0 : result = rpccli_spoolss_getprinter(cli, mem_ctx,
701 : &pol,
702 : level,
703 : 0,
704 : &info);
705 0 : if (!W_ERROR_IS_OK(result)) {
706 0 : goto done;
707 : }
708 :
709 : /* Display printer info */
710 0 : switch (level) {
711 0 : case 0:
712 0 : display_print_info0(&info.info0);
713 0 : break;
714 0 : case 1:
715 0 : display_print_info1(&info.info1);
716 0 : break;
717 0 : case 2:
718 0 : display_print_info2(&info.info2);
719 0 : break;
720 0 : case 3:
721 0 : display_print_info3(&info.info3);
722 0 : break;
723 0 : case 4:
724 0 : display_print_info4(&info.info4);
725 0 : break;
726 0 : case 5:
727 0 : display_print_info5(&info.info5);
728 0 : break;
729 0 : case 6:
730 0 : display_print_info6(&info.info6);
731 0 : break;
732 0 : case 7:
733 0 : display_print_info7(&info.info7);
734 0 : break;
735 0 : default:
736 0 : printf("unknown info level %d\n", level);
737 0 : break;
738 : }
739 0 : done:
740 0 : if (is_valid_policy_hnd(&pol)) {
741 : WERROR _result;
742 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
743 : }
744 :
745 0 : return result;
746 : }
747 :
748 : /****************************************************************************
749 : ****************************************************************************/
750 :
751 0 : static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
752 : {
753 0 : const char *text = NULL;
754 :
755 0 : switch(type) {
756 0 : case REG_DWORD:
757 0 : if (blob.length >= sizeof(uint32_t)) {
758 0 : printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
759 : } else {
760 0 : printf("%s: REG_DWORD: <invalid>\n", name);
761 : }
762 0 : break;
763 0 : case REG_SZ:
764 0 : pull_reg_sz(talloc_tos(), &blob, &text);
765 0 : printf("%s: REG_SZ: %s\n", name, text ? text : "");
766 0 : break;
767 0 : case REG_BINARY: {
768 0 : char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
769 : size_t i, len;
770 0 : printf("%s: REG_BINARY:", name);
771 0 : len = strlen(hex);
772 0 : for (i=0; i<len; i++) {
773 0 : if (hex[i] == '\0') {
774 0 : break;
775 : }
776 0 : if (i%40 == 0) {
777 0 : putchar('\n');
778 : }
779 0 : putchar(hex[i]);
780 : }
781 0 : TALLOC_FREE(hex);
782 0 : putchar('\n');
783 0 : break;
784 : }
785 0 : case REG_MULTI_SZ: {
786 : uint32_t i;
787 : const char **values;
788 :
789 0 : if (!pull_reg_multi_sz(NULL, &blob, &values)) {
790 0 : d_printf("pull_reg_multi_sz failed\n");
791 0 : break;
792 : }
793 :
794 0 : printf("%s: REG_MULTI_SZ: \n", name);
795 0 : for (i=0; values[i] != NULL; i++) {
796 0 : d_printf("%s\n", values[i]);
797 : }
798 0 : TALLOC_FREE(values);
799 0 : break;
800 : }
801 0 : default:
802 0 : printf("%s: unknown type %d\n", name, type);
803 : }
804 :
805 0 : }
806 :
807 : /****************************************************************************
808 : ****************************************************************************/
809 :
810 0 : static void display_printer_data(const char *v,
811 : enum winreg_Type type,
812 : uint8_t *data,
813 : uint32_t length)
814 : {
815 : int i;
816 : union spoolss_PrinterData r;
817 0 : DATA_BLOB blob = data_blob_const(data, length);
818 : WERROR result;
819 : enum ndr_err_code ndr_err;
820 :
821 0 : result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
822 0 : if (!W_ERROR_IS_OK(result)) {
823 0 : return;
824 : }
825 :
826 0 : switch (type) {
827 0 : case REG_DWORD:
828 0 : printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
829 0 : break;
830 0 : case REG_SZ:
831 0 : printf("%s: REG_SZ: %s\n", v, r.string);
832 0 : break;
833 0 : case REG_BINARY: {
834 0 : char *hex = hex_encode_talloc(NULL,
835 0 : r.binary.data, r.binary.length);
836 : size_t len;
837 0 : printf("%s: REG_BINARY:", v);
838 0 : len = strlen(hex);
839 0 : for (i=0; i<len; i++) {
840 0 : if (hex[i] == '\0') {
841 0 : break;
842 : }
843 0 : if (i%40 == 0) {
844 0 : putchar('\n');
845 : }
846 0 : putchar(hex[i]);
847 : }
848 0 : TALLOC_FREE(hex);
849 0 : putchar('\n');
850 0 : putchar('\n');
851 :
852 0 : if (strequal(v, "OsVersion")) {
853 : struct spoolss_OSVersion os;
854 0 : ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
855 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
856 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
857 : // add output here;
858 0 : printf("OsMajor: %u\n", os.major);
859 0 : printf("OsMinor: %u\n", os.minor);
860 0 : printf("OsBuild: %u\n", os.build);
861 0 : NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
862 : }
863 : }
864 0 : if (strequal(v, "OsVersionEx")) {
865 : struct spoolss_OSVersionEx os;
866 0 : ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
867 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
868 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
869 0 : printf("OsMajor: %u\n", os.major);
870 0 : printf("OsMinor: %u\n", os.minor);
871 0 : printf("OsBuild: %u\n", os.build);
872 0 : printf("ServicePackMajor: %u\n", os.service_pack_major);
873 0 : printf("ServicePackMinor: %u\n", os.service_pack_minor);
874 0 : NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
875 : }
876 : }
877 0 : break;
878 : }
879 0 : case REG_MULTI_SZ:
880 0 : printf("%s: REG_MULTI_SZ: ", v);
881 0 : for (i=0; r.string_array[i] != NULL; i++) {
882 0 : printf("%s ", r.string_array[i]);
883 : }
884 0 : printf("\n");
885 0 : break;
886 0 : default:
887 0 : printf("%s: unknown type 0x%02x:\n", v, type);
888 0 : break;
889 : }
890 : }
891 :
892 : /****************************************************************************
893 : ****************************************************************************/
894 :
895 0 : static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
896 : TALLOC_CTX *mem_ctx,
897 : int argc, const char **argv)
898 : {
899 : struct policy_handle pol;
900 : WERROR result;
901 : fstring printername;
902 : const char *valuename;
903 : enum winreg_Type type;
904 : uint8_t *data;
905 : uint32_t needed;
906 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
907 :
908 0 : if (argc != 3) {
909 0 : printf("Usage: %s <printername> <valuename>\n", argv[0]);
910 0 : printf("<printername> of . queries print server\n");
911 0 : return WERR_OK;
912 : }
913 0 : valuename = argv[2];
914 :
915 : /* Open a printer handle */
916 :
917 0 : if (strncmp(argv[1], ".", sizeof(".")) == 0)
918 0 : fstrcpy(printername, cli->srv_name_slash);
919 : else
920 0 : slprintf(printername, sizeof(printername)-1, "%s\\%s",
921 0 : cli->srv_name_slash, argv[1]);
922 :
923 : /* get a printer handle */
924 :
925 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
926 : printername,
927 : SEC_FLAG_MAXIMUM_ALLOWED,
928 : &pol);
929 0 : if (!W_ERROR_IS_OK(result))
930 0 : goto done;
931 :
932 : /* Get printer info */
933 :
934 0 : result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
935 : &pol,
936 : valuename,
937 : 0,
938 : &type,
939 : &needed,
940 : &data);
941 0 : if (!W_ERROR_IS_OK(result))
942 0 : goto done;
943 :
944 : /* Display printer data */
945 :
946 0 : display_printer_data(valuename, type, data, needed);
947 :
948 0 : done:
949 0 : if (is_valid_policy_hnd(&pol)) {
950 : WERROR _result;
951 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
952 : }
953 :
954 0 : return result;
955 : }
956 :
957 : /****************************************************************************
958 : ****************************************************************************/
959 :
960 0 : static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
961 : TALLOC_CTX *mem_ctx,
962 : int argc, const char **argv)
963 : {
964 : struct policy_handle pol;
965 : WERROR result;
966 : NTSTATUS status;
967 : fstring printername;
968 : const char *valuename, *keyname;
969 :
970 : enum winreg_Type type;
971 0 : uint8_t *data = NULL;
972 0 : uint32_t offered = 0;
973 : uint32_t needed;
974 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
975 :
976 0 : if (argc != 4) {
977 0 : printf("Usage: %s <printername> <keyname> <valuename>\n",
978 : argv[0]);
979 0 : printf("<printername> of . queries print server\n");
980 0 : return WERR_OK;
981 : }
982 0 : valuename = argv[3];
983 0 : keyname = argv[2];
984 :
985 : /* Open a printer handle */
986 :
987 0 : if (strncmp(argv[1], ".", sizeof(".")) == 0)
988 0 : fstrcpy(printername, cli->srv_name_slash);
989 : else
990 0 : slprintf(printername, sizeof(printername)-1, "%s\\%s",
991 0 : cli->srv_name_slash, argv[1]);
992 :
993 : /* get a printer handle */
994 :
995 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
996 : printername,
997 : SEC_FLAG_MAXIMUM_ALLOWED,
998 : &pol);
999 0 : if (!W_ERROR_IS_OK(result))
1000 0 : goto done;
1001 :
1002 : /* Get printer info */
1003 :
1004 0 : data = talloc_zero_array(mem_ctx, uint8_t, offered);
1005 0 : if (!data) {
1006 0 : goto done;
1007 : }
1008 :
1009 0 : status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1010 : &pol,
1011 : keyname,
1012 : valuename,
1013 : &type,
1014 : data,
1015 : offered,
1016 : &needed,
1017 : &result);
1018 0 : if (!NT_STATUS_IS_OK(status)) {
1019 0 : result = ntstatus_to_werror(status);
1020 0 : goto done;
1021 : }
1022 0 : if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
1023 0 : offered = needed;
1024 0 : data = talloc_zero_array(mem_ctx, uint8_t, offered);
1025 0 : if (!data) {
1026 0 : goto done;
1027 : }
1028 0 : status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
1029 : &pol,
1030 : keyname,
1031 : valuename,
1032 : &type,
1033 : data,
1034 : offered,
1035 : &needed,
1036 : &result);
1037 : }
1038 :
1039 0 : if (!NT_STATUS_IS_OK(status)) {
1040 0 : result = ntstatus_to_werror(status);
1041 0 : goto done;
1042 : }
1043 :
1044 0 : if (!W_ERROR_IS_OK(result))
1045 0 : goto done;
1046 :
1047 : /* Display printer data */
1048 :
1049 0 : display_printer_data(valuename, type, data, needed);
1050 :
1051 :
1052 0 : done:
1053 0 : if (is_valid_policy_hnd(&pol)) {
1054 : WERROR _result;
1055 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1056 : }
1057 :
1058 0 : return result;
1059 : }
1060 :
1061 : /****************************************************************************
1062 : ****************************************************************************/
1063 :
1064 0 : static void display_print_driver1(struct spoolss_DriverInfo1 *r)
1065 : {
1066 0 : if (!r) {
1067 0 : return;
1068 : }
1069 :
1070 0 : printf("Printer Driver Info 1:\n");
1071 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1072 0 : printf("\n");
1073 : }
1074 :
1075 : /****************************************************************************
1076 : ****************************************************************************/
1077 :
1078 0 : static void display_print_driver2(struct spoolss_DriverInfo2 *r)
1079 : {
1080 0 : if (!r) {
1081 0 : return;
1082 : }
1083 :
1084 0 : printf("Printer Driver Info 2:\n");
1085 0 : printf("\tVersion: [%x]\n", r->version);
1086 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1087 0 : printf("\tArchitecture: [%s]\n", r->architecture);
1088 0 : printf("\tDriver Path: [%s]\n", r->driver_path);
1089 0 : printf("\tDatafile: [%s]\n", r->data_file);
1090 0 : printf("\tConfigfile: [%s]\n", r->config_file);
1091 0 : printf("\n");
1092 : }
1093 :
1094 : /****************************************************************************
1095 : ****************************************************************************/
1096 :
1097 0 : static void display_print_driver3(struct spoolss_DriverInfo3 *r)
1098 : {
1099 : int i;
1100 :
1101 0 : if (!r) {
1102 0 : return;
1103 : }
1104 :
1105 0 : printf("Printer Driver Info 3:\n");
1106 0 : printf("\tVersion: [%x]\n", r->version);
1107 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1108 0 : printf("\tArchitecture: [%s]\n", r->architecture);
1109 0 : printf("\tDriver Path: [%s]\n", r->driver_path);
1110 0 : printf("\tDatafile: [%s]\n", r->data_file);
1111 0 : printf("\tConfigfile: [%s]\n", r->config_file);
1112 0 : printf("\tHelpfile: [%s]\n", r->help_file);
1113 :
1114 0 : for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1115 0 : printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1116 : }
1117 :
1118 0 : printf("\tMonitorname: [%s]\n", r->monitor_name);
1119 0 : printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1120 0 : printf("\n");
1121 : }
1122 :
1123 : /****************************************************************************
1124 : ****************************************************************************/
1125 :
1126 0 : static void display_print_driver4(struct spoolss_DriverInfo4 *r)
1127 : {
1128 : int i;
1129 :
1130 0 : if (!r) {
1131 0 : return;
1132 : }
1133 :
1134 0 : printf("Printer Driver Info 4:\n");
1135 0 : printf("\tVersion: [%x]\n", r->version);
1136 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1137 0 : printf("\tArchitecture: [%s]\n", r->architecture);
1138 0 : printf("\tDriver Path: [%s]\n", r->driver_path);
1139 0 : printf("\tDatafile: [%s]\n", r->data_file);
1140 0 : printf("\tConfigfile: [%s]\n", r->config_file);
1141 0 : printf("\tHelpfile: [%s]\n", r->help_file);
1142 :
1143 0 : for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1144 0 : printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1145 : }
1146 :
1147 0 : printf("\tMonitorname: [%s]\n", r->monitor_name);
1148 0 : printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1149 :
1150 0 : for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1151 0 : printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1152 : }
1153 0 : printf("\n");
1154 : }
1155 :
1156 : /****************************************************************************
1157 : ****************************************************************************/
1158 :
1159 0 : static void display_print_driver5(struct spoolss_DriverInfo5 *r)
1160 : {
1161 0 : if (!r) {
1162 0 : return;
1163 : }
1164 :
1165 0 : printf("Printer Driver Info 5:\n");
1166 0 : printf("\tVersion: [%x]\n", r->version);
1167 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1168 0 : printf("\tArchitecture: [%s]\n", r->architecture);
1169 0 : printf("\tDriver Path: [%s]\n", r->driver_path);
1170 0 : printf("\tDatafile: [%s]\n", r->data_file);
1171 0 : printf("\tConfigfile: [%s]\n", r->config_file);
1172 0 : printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
1173 0 : printf("\tConfig Version: [0x%x]\n", r->config_version);
1174 0 : printf("\tDriver Version: [0x%x]\n", r->driver_version);
1175 0 : printf("\n");
1176 : }
1177 :
1178 : /****************************************************************************
1179 : ****************************************************************************/
1180 :
1181 0 : static void display_print_driver6(struct spoolss_DriverInfo6 *r)
1182 : {
1183 : int i;
1184 :
1185 0 : if (!r) {
1186 0 : return;
1187 : }
1188 :
1189 0 : printf("Printer Driver Info 6:\n");
1190 0 : printf("\tVersion: [%x]\n", r->version);
1191 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1192 0 : printf("\tArchitecture: [%s]\n", r->architecture);
1193 0 : printf("\tDriver Path: [%s]\n", r->driver_path);
1194 0 : printf("\tDatafile: [%s]\n", r->data_file);
1195 0 : printf("\tConfigfile: [%s]\n", r->config_file);
1196 0 : printf("\tHelpfile: [%s]\n", r->help_file);
1197 :
1198 0 : for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1199 0 : printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1200 : }
1201 :
1202 0 : printf("\tMonitorname: [%s]\n", r->monitor_name);
1203 0 : printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1204 :
1205 0 : for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1206 0 : printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1207 : }
1208 :
1209 0 : printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1210 0 : printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1211 0 : printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1212 0 : printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1213 0 : printf("\tHardware ID: [%s]\n", r->hardware_id);
1214 0 : printf("\tProvider: [%s]\n", r->provider);
1215 :
1216 0 : printf("\n");
1217 : }
1218 :
1219 : /****************************************************************************
1220 : ****************************************************************************/
1221 :
1222 0 : static void display_print_driver8(struct spoolss_DriverInfo8 *r)
1223 : {
1224 : int i;
1225 :
1226 0 : if (!r) {
1227 0 : return;
1228 : }
1229 :
1230 0 : printf("Printer Driver Info 8:\n");
1231 0 : printf("\tVersion: [%x]\n", r->version);
1232 0 : printf("\tDriver Name: [%s]\n", r->driver_name);
1233 0 : printf("\tArchitecture: [%s]\n", r->architecture);
1234 0 : printf("\tDriver Path: [%s]\n", r->driver_path);
1235 0 : printf("\tDatafile: [%s]\n", r->data_file);
1236 0 : printf("\tConfigfile: [%s]\n", r->config_file);
1237 0 : printf("\tHelpfile: [%s]\n", r->help_file);
1238 0 : printf("\tMonitorname: [%s]\n", r->monitor_name);
1239 0 : printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
1240 :
1241 0 : for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
1242 0 : printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
1243 : }
1244 :
1245 0 : for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
1246 0 : printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
1247 : }
1248 :
1249 0 : printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
1250 0 : printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
1251 0 : printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
1252 0 : printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
1253 0 : printf("\tHardware ID: [%s]\n", r->hardware_id);
1254 0 : printf("\tProvider: [%s]\n", r->provider);
1255 0 : printf("\tPrint Processor: [%s]\n", r->print_processor);
1256 0 : printf("\tVendor Setup: [%s]\n", r->vendor_setup);
1257 0 : for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
1258 0 : printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
1259 : }
1260 0 : printf("\tInf Path: [%s]\n", r->inf_path);
1261 0 : printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
1262 0 : for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
1263 0 : printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
1264 : }
1265 0 : printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
1266 0 : printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
1267 0 : (long long unsigned int)r->min_inbox_driver_ver_version);
1268 :
1269 0 : printf("\n");
1270 : }
1271 :
1272 : /****************************************************************************
1273 : ****************************************************************************/
1274 :
1275 0 : static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
1276 : TALLOC_CTX *mem_ctx,
1277 : int argc, const char **argv)
1278 : {
1279 : struct policy_handle pol;
1280 : WERROR werror;
1281 0 : uint32_t level = 3;
1282 : const char *printername;
1283 : uint32_t i;
1284 0 : bool success = false;
1285 : union spoolss_DriverInfo info;
1286 : uint32_t server_major_version;
1287 : uint32_t server_minor_version;
1288 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
1289 :
1290 0 : if ((argc == 1) || (argc > 3)) {
1291 0 : printf("Usage: %s <printername> [level]\n", argv[0]);
1292 0 : return WERR_OK;
1293 : }
1294 :
1295 : /* get the arguments need to open the printer handle */
1296 :
1297 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1298 :
1299 0 : if (argc == 3) {
1300 0 : level = atoi(argv[2]);
1301 : }
1302 :
1303 : /* Open a printer handle */
1304 :
1305 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1306 : printername,
1307 : PRINTER_ACCESS_USE,
1308 : &pol);
1309 0 : if (!W_ERROR_IS_OK(werror)) {
1310 0 : printf("Error opening printer handle for %s!\n", printername);
1311 0 : return werror;
1312 : }
1313 :
1314 : /* loop through and print driver info level for each architecture */
1315 :
1316 0 : for (i=0; archi_table[i].long_archi!=NULL; i++) {
1317 :
1318 0 : werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1319 : &pol,
1320 0 : archi_table[i].long_archi,
1321 : level,
1322 : 0, /* offered */
1323 0 : archi_table[i].version,
1324 : 2,
1325 : &info,
1326 : &server_major_version,
1327 : &server_minor_version);
1328 0 : if (!W_ERROR_IS_OK(werror)) {
1329 0 : continue;
1330 : }
1331 :
1332 : /* need at least one success */
1333 :
1334 0 : success = true;
1335 :
1336 0 : printf("\n[%s]\n", archi_table[i].long_archi);
1337 :
1338 0 : switch (level) {
1339 0 : case 1:
1340 0 : display_print_driver1(&info.info1);
1341 0 : break;
1342 0 : case 2:
1343 0 : display_print_driver2(&info.info2);
1344 0 : break;
1345 0 : case 3:
1346 0 : display_print_driver3(&info.info3);
1347 0 : break;
1348 0 : case 4:
1349 0 : display_print_driver4(&info.info4);
1350 0 : break;
1351 0 : case 5:
1352 0 : display_print_driver5(&info.info5);
1353 0 : break;
1354 0 : case 6:
1355 0 : display_print_driver6(&info.info6);
1356 0 : break;
1357 0 : case 8:
1358 0 : display_print_driver8(&info.info8);
1359 0 : break;
1360 0 : default:
1361 0 : printf("unknown info level %d\n", level);
1362 0 : break;
1363 : }
1364 : }
1365 :
1366 : /* Cleanup */
1367 :
1368 0 : if (is_valid_policy_hnd(&pol)) {
1369 : WERROR _result;
1370 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1371 : }
1372 :
1373 0 : if (success) {
1374 0 : werror = WERR_OK;
1375 : }
1376 :
1377 0 : return werror;
1378 : }
1379 :
1380 : /****************************************************************************
1381 : ****************************************************************************/
1382 :
1383 0 : static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
1384 : TALLOC_CTX *mem_ctx,
1385 : const char *architecture,
1386 : uint32_t level)
1387 : {
1388 : WERROR werror;
1389 0 : uint32_t count = 0;
1390 0 : union spoolss_DriverInfo *info = NULL;
1391 : uint32_t j;
1392 :
1393 0 : werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
1394 0 : cli->srv_name_slash,
1395 : architecture,
1396 : level,
1397 : 0,
1398 : &count,
1399 : &info);
1400 :
1401 0 : if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
1402 0 : printf("Server does not support environment [%s]\n",
1403 : architecture);
1404 0 : return WERR_OK;
1405 : }
1406 :
1407 0 : if (count == 0) {
1408 0 : return WERR_OK;
1409 : }
1410 :
1411 0 : if (!W_ERROR_IS_OK(werror)) {
1412 0 : printf("Error getting driver for environment [%s] - %s\n",
1413 : architecture, win_errstr(werror));
1414 0 : return werror;
1415 : }
1416 :
1417 0 : printf("\n[%s]\n", architecture);
1418 :
1419 0 : switch (level) {
1420 0 : case 1:
1421 0 : for (j=0; j < count; j++) {
1422 0 : display_print_driver1(&info[j].info1);
1423 : }
1424 0 : break;
1425 0 : case 2:
1426 0 : for (j=0; j < count; j++) {
1427 0 : display_print_driver2(&info[j].info2);
1428 : }
1429 0 : break;
1430 0 : case 3:
1431 0 : for (j=0; j < count; j++) {
1432 0 : display_print_driver3(&info[j].info3);
1433 : }
1434 0 : break;
1435 0 : case 4:
1436 0 : for (j=0; j < count; j++) {
1437 0 : display_print_driver4(&info[j].info4);
1438 : }
1439 0 : break;
1440 0 : case 5:
1441 0 : for (j=0; j < count; j++) {
1442 0 : display_print_driver5(&info[j].info5);
1443 : }
1444 0 : break;
1445 0 : case 6:
1446 0 : for (j=0; j < count; j++) {
1447 0 : display_print_driver6(&info[j].info6);
1448 : }
1449 0 : break;
1450 0 : case 8:
1451 0 : for (j=0; j < count; j++) {
1452 0 : display_print_driver8(&info[j].info8);
1453 : }
1454 0 : break;
1455 0 : default:
1456 0 : printf("unknown info level %d\n", level);
1457 0 : return WERR_INVALID_LEVEL;
1458 : }
1459 :
1460 0 : return werror;
1461 : }
1462 :
1463 0 : static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
1464 : TALLOC_CTX *mem_ctx,
1465 : int argc, const char **argv)
1466 : {
1467 0 : WERROR werror = WERR_OK;
1468 0 : uint32_t level = 1;
1469 : uint32_t i;
1470 0 : const char *architecture = NULL;
1471 :
1472 0 : if (argc > 3) {
1473 0 : printf("Usage: enumdrivers [level] [architecture]\n");
1474 0 : return WERR_OK;
1475 : }
1476 :
1477 0 : if (argc >= 2) {
1478 0 : level = atoi(argv[1]);
1479 : }
1480 :
1481 0 : if (argc == 3) {
1482 0 : architecture = argv[2];
1483 : }
1484 :
1485 0 : if (architecture) {
1486 0 : return enum_driver_by_architecture(cli, mem_ctx,
1487 : architecture,
1488 : level);
1489 : }
1490 :
1491 : /* loop through and print driver info level for each architecture */
1492 0 : for (i=0; archi_table[i].long_archi!=NULL; i++) {
1493 : /* check to see if we already asked for this architecture string */
1494 :
1495 0 : if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
1496 0 : continue;
1497 : }
1498 :
1499 0 : werror = enum_driver_by_architecture(cli, mem_ctx,
1500 0 : archi_table[i].long_archi,
1501 : level);
1502 0 : if (!W_ERROR_IS_OK(werror)) {
1503 0 : break;
1504 : }
1505 : }
1506 :
1507 0 : return werror;
1508 : }
1509 :
1510 : /****************************************************************************
1511 : ****************************************************************************/
1512 :
1513 0 : static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
1514 : {
1515 0 : printf("\tDirectory Name:[%s]\n", r->directory_name);
1516 0 : }
1517 :
1518 : /****************************************************************************
1519 : ****************************************************************************/
1520 :
1521 0 : static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
1522 : TALLOC_CTX *mem_ctx,
1523 : int argc, const char **argv)
1524 : {
1525 : WERROR result;
1526 : NTSTATUS status;
1527 0 : const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1528 : DATA_BLOB buffer;
1529 : uint32_t offered;
1530 : union spoolss_DriverDirectoryInfo info;
1531 : uint32_t needed;
1532 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
1533 :
1534 0 : if (argc > 2) {
1535 0 : printf("Usage: %s [environment]\n", argv[0]);
1536 0 : return WERR_OK;
1537 : }
1538 :
1539 : /* Get the arguments need to open the printer handle */
1540 :
1541 0 : if (argc == 2) {
1542 0 : env = argv[1];
1543 : }
1544 :
1545 : /* Get the directory. Only use Info level 1 */
1546 :
1547 0 : status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1548 0 : cli->srv_name_slash,
1549 : env,
1550 : 1,
1551 : NULL, /* buffer */
1552 : 0, /* offered */
1553 : NULL, /* info */
1554 : &needed,
1555 : &result);
1556 0 : if (!NT_STATUS_IS_OK(status)) {
1557 0 : return ntstatus_to_werror(status);
1558 : }
1559 0 : if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
1560 0 : offered = needed;
1561 0 : buffer = data_blob_talloc_zero(mem_ctx, needed);
1562 :
1563 0 : status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
1564 0 : cli->srv_name_slash,
1565 : env,
1566 : 1,
1567 : &buffer,
1568 : offered,
1569 : &info,
1570 : &needed,
1571 : &result);
1572 0 : if (!NT_STATUS_IS_OK(status)) {
1573 0 : return ntstatus_to_werror(status);
1574 : }
1575 : }
1576 :
1577 0 : if (W_ERROR_IS_OK(result)) {
1578 0 : display_printdriverdir_1(&info.info1);
1579 : }
1580 :
1581 0 : return result;
1582 : }
1583 :
1584 : /****************************************************************************
1585 : ****************************************************************************/
1586 :
1587 0 : static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
1588 : TALLOC_CTX *mem_ctx,
1589 : int argc, const char **argv)
1590 : {
1591 : HRESULT hresult;
1592 : NTSTATUS status;
1593 0 : const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
1594 : uint32_t offered;
1595 : uint32_t needed;
1596 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
1597 0 : const char *package_id = "";
1598 0 : const char *cab = NULL;
1599 :
1600 0 : if (argc > 4) {
1601 0 : printf("Usage: %s [environment] [package_id]\n", argv[0]);
1602 0 : return WERR_OK;
1603 : }
1604 :
1605 : /* Get the arguments need to open the printer handle */
1606 :
1607 0 : if (argc >= 2) {
1608 0 : env = argv[1];
1609 : }
1610 :
1611 0 : if (argc == 3) {
1612 0 : package_id = argv[2];
1613 : }
1614 :
1615 0 : offered = 1;
1616 0 : cab = talloc_zero_array(mem_ctx, char, offered);
1617 0 : if (cab == NULL) {
1618 0 : return WERR_NOT_ENOUGH_MEMORY;
1619 : }
1620 0 : status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1621 0 : cli->srv_name_slash,
1622 : env,
1623 : NULL,
1624 : package_id,
1625 : cab,
1626 : offered,
1627 : &needed,
1628 : &hresult);
1629 0 : if (!NT_STATUS_IS_OK(status)) {
1630 0 : return ntstatus_to_werror(status);
1631 : }
1632 :
1633 0 : if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
1634 0 : offered = needed;
1635 0 : cab = talloc_zero_array(mem_ctx, char, offered);
1636 0 : if (cab == NULL) {
1637 0 : return WERR_NOT_ENOUGH_MEMORY;
1638 : }
1639 0 : status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
1640 0 : cli->srv_name_slash,
1641 : env,
1642 : NULL,
1643 : package_id,
1644 : cab,
1645 : offered,
1646 : &needed,
1647 : &hresult);
1648 0 : if (!NT_STATUS_IS_OK(status)) {
1649 0 : return ntstatus_to_werror(status);
1650 : }
1651 : }
1652 :
1653 0 : return W_ERROR(WIN32_FROM_HRESULT(hresult));
1654 : }
1655 :
1656 :
1657 : /****************************************************************************
1658 : ****************************************************************************/
1659 :
1660 0 : static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
1661 : struct spoolss_AddDriverInfo3 *info,
1662 : const char *arch)
1663 : {
1664 :
1665 : int i;
1666 :
1667 0 : for (i=0; archi_table[i].long_archi != NULL; i++)
1668 : {
1669 0 : if (strcmp(arch, archi_table[i].short_archi) == 0)
1670 : {
1671 0 : info->version = archi_table[i].version;
1672 0 : info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
1673 0 : break;
1674 : }
1675 : }
1676 :
1677 0 : if (archi_table[i].long_archi == NULL)
1678 : {
1679 0 : DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
1680 : }
1681 :
1682 0 : return;
1683 : }
1684 :
1685 :
1686 : /**************************************************************************
1687 : wrapper for strtok to get the next parameter from a delimited list.
1688 : Needed to handle the empty parameter string denoted by "NULL"
1689 : *************************************************************************/
1690 :
1691 0 : static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
1692 : const char *delim, const char **dest,
1693 : char **saveptr)
1694 : {
1695 : char *ptr;
1696 :
1697 : /* get the next token */
1698 0 : ptr = strtok_r(str, delim, saveptr);
1699 :
1700 : /* a string of 'NULL' is used to represent an empty
1701 : parameter because two consecutive delimiters
1702 : will not return an empty string. See man strtok(3)
1703 : for details */
1704 0 : if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
1705 0 : ptr = NULL;
1706 : }
1707 :
1708 0 : if (dest != NULL) {
1709 0 : *dest = talloc_strdup(mem_ctx, ptr);
1710 : }
1711 :
1712 0 : return ptr;
1713 : }
1714 :
1715 : /********************************************************************************
1716 : fill in the members of a spoolss_AddDriverInfo3 struct using a character
1717 : string in the form of
1718 : <Long Driver Name>:<Driver File Name>:<Data File Name>:\
1719 : <Config File Name>:<Help File Name>:<Language Monitor Name>:\
1720 : <Default Data Type>:<Comma Separated list of Files>
1721 : *******************************************************************************/
1722 :
1723 0 : static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
1724 : char *args)
1725 : {
1726 : char *str, *str2;
1727 0 : size_t count = 0;
1728 0 : char *saveptr = NULL;
1729 : struct spoolss_StringArray *deps;
1730 0 : const char **file_array = NULL;
1731 : int i;
1732 :
1733 : /* fill in the UNISTR fields */
1734 0 : str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
1735 0 : str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
1736 0 : str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
1737 0 : str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
1738 0 : str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
1739 0 : str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
1740 0 : str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
1741 :
1742 : /* <Comma Separated List of Dependent Files> */
1743 : /* save the beginning of the string */
1744 0 : str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
1745 0 : str = str2;
1746 :
1747 : /* begin to strip out each filename */
1748 0 : str = strtok_r(str, ",", &saveptr);
1749 :
1750 : /* no dependent files, we are done */
1751 0 : if (!str) {
1752 0 : return true;
1753 : }
1754 :
1755 0 : deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
1756 0 : if (!deps) {
1757 0 : return false;
1758 : }
1759 :
1760 0 : while (str != NULL) {
1761 : bool ok;
1762 0 : ok = add_string_to_array(deps, str, &file_array, &count);
1763 0 : if (!ok) {
1764 0 : return false;
1765 : }
1766 0 : str = strtok_r(NULL, ",", &saveptr);
1767 : }
1768 :
1769 0 : deps->string = talloc_zero_array(deps, const char *, count + 1);
1770 0 : if (!deps->string) {
1771 0 : return false;
1772 : }
1773 :
1774 0 : for (i=0; i < count; i++) {
1775 0 : deps->string[i] = file_array[i];
1776 : }
1777 :
1778 0 : r->dependent_files = deps;
1779 :
1780 0 : return true;
1781 : }
1782 :
1783 : /****************************************************************************
1784 : ****************************************************************************/
1785 :
1786 0 : static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
1787 : TALLOC_CTX *mem_ctx,
1788 : int argc, const char **argv)
1789 : {
1790 : WERROR result;
1791 : NTSTATUS status;
1792 0 : uint32_t level = 3;
1793 : struct spoolss_AddDriverInfoCtr info_ctr;
1794 : struct spoolss_AddDriverInfo3 info3;
1795 : const char *arch;
1796 : char *driver_args;
1797 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
1798 :
1799 : /* parse the command arguments */
1800 0 : if (argc != 3 && argc != 4)
1801 : {
1802 0 : printf ("Usage: %s <Environment> \\\n", argv[0]);
1803 0 : printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
1804 0 : printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
1805 0 : printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
1806 0 : printf ("\t[version]\n");
1807 :
1808 0 : return WERR_OK;
1809 : }
1810 :
1811 : /* Fill in the spoolss_AddDriverInfo3 struct */
1812 0 : ZERO_STRUCT(info3);
1813 :
1814 0 : arch = cmd_spoolss_get_short_archi(argv[1]);
1815 0 : if (!arch) {
1816 0 : printf ("Error Unknown architecture [%s]\n", argv[1]);
1817 0 : return WERR_INVALID_PARAMETER;
1818 : }
1819 :
1820 0 : set_drv_info_3_env(mem_ctx, &info3, arch);
1821 :
1822 0 : driver_args = talloc_strdup( mem_ctx, argv[2] );
1823 0 : if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
1824 : {
1825 0 : printf ("Error Invalid parameter list - %s.\n", argv[2]);
1826 0 : return WERR_INVALID_PARAMETER;
1827 : }
1828 :
1829 : /* if printer driver version specified, override the default version
1830 : * used by the architecture. This allows installation of Windows
1831 : * 2000 (version 3) printer drivers. */
1832 0 : if (argc == 4)
1833 : {
1834 0 : info3.version = atoi(argv[3]);
1835 : }
1836 :
1837 :
1838 0 : info_ctr.level = level;
1839 0 : info_ctr.info.info3 = &info3;
1840 :
1841 0 : status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1842 0 : cli->srv_name_slash,
1843 : &info_ctr,
1844 : &result);
1845 0 : if (!NT_STATUS_IS_OK(status)) {
1846 0 : return ntstatus_to_werror(status);
1847 : }
1848 0 : if (W_ERROR_IS_OK(result)) {
1849 0 : printf ("Printer Driver %s successfully installed.\n",
1850 : info3.driver_name);
1851 : }
1852 :
1853 0 : return result;
1854 : }
1855 :
1856 :
1857 : /****************************************************************************
1858 : ****************************************************************************/
1859 :
1860 0 : static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
1861 : TALLOC_CTX *mem_ctx,
1862 : int argc, const char **argv)
1863 : {
1864 : WERROR result;
1865 : struct spoolss_SetPrinterInfoCtr info_ctr;
1866 : struct spoolss_SetPrinterInfo2 info2;
1867 :
1868 : /* parse the command arguments */
1869 0 : if (argc != 5)
1870 : {
1871 0 : printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
1872 0 : return WERR_OK;
1873 : }
1874 :
1875 : /* Fill in the DRIVER_INFO_2 struct */
1876 0 : ZERO_STRUCT(info2);
1877 :
1878 0 : info2.printername = argv[1];
1879 0 : info2.drivername = argv[3];
1880 0 : info2.sharename = argv[2];
1881 0 : info2.portname = argv[4];
1882 0 : info2.comment = "Created by rpcclient";
1883 0 : info2.printprocessor = "winprint";
1884 0 : info2.datatype = "RAW";
1885 0 : info2.devmode_ptr = 0;
1886 0 : info2.secdesc_ptr = 0;
1887 0 : info2.attributes = PRINTER_ATTRIBUTE_SHARED;
1888 0 : info2.priority = 0;
1889 0 : info2.defaultpriority = 0;
1890 0 : info2.starttime = 0;
1891 0 : info2.untiltime = 0;
1892 :
1893 : /* These three fields must not be used by AddPrinter()
1894 : as defined in the MS Platform SDK documentation..
1895 : --jerry
1896 : info2.status = 0;
1897 : info2.cjobs = 0;
1898 : info2.averageppm = 0;
1899 : */
1900 :
1901 0 : info_ctr.level = 2;
1902 0 : info_ctr.info.info2 = &info2;
1903 :
1904 0 : result = rpccli_spoolss_addprinterex(cli, mem_ctx,
1905 : &info_ctr);
1906 0 : if (W_ERROR_IS_OK(result))
1907 0 : printf ("Printer %s successfully installed.\n", argv[1]);
1908 :
1909 0 : return result;
1910 : }
1911 :
1912 : /****************************************************************************
1913 : ****************************************************************************/
1914 :
1915 0 : static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
1916 : TALLOC_CTX *mem_ctx,
1917 : int argc, const char **argv)
1918 : {
1919 : struct policy_handle pol;
1920 : WERROR result;
1921 : NTSTATUS status;
1922 0 : uint32_t level = 2;
1923 : const char *printername;
1924 : union spoolss_PrinterInfo info;
1925 : struct spoolss_SetPrinterInfoCtr info_ctr;
1926 : struct spoolss_SetPrinterInfo2 info2;
1927 : struct spoolss_DevmodeContainer devmode_ctr;
1928 : struct sec_desc_buf secdesc_ctr;
1929 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
1930 :
1931 0 : ZERO_STRUCT(devmode_ctr);
1932 0 : ZERO_STRUCT(secdesc_ctr);
1933 :
1934 : /* parse the command arguments */
1935 0 : if (argc != 3)
1936 : {
1937 0 : printf ("Usage: %s <printer> <driver>\n", argv[0]);
1938 0 : return WERR_OK;
1939 : }
1940 :
1941 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
1942 :
1943 : /* Get a printer handle */
1944 :
1945 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
1946 : printername,
1947 : PRINTER_ALL_ACCESS,
1948 : &pol);
1949 0 : if (!W_ERROR_IS_OK(result))
1950 0 : goto done;
1951 :
1952 : /* Get printer info */
1953 :
1954 0 : result = rpccli_spoolss_getprinter(cli, mem_ctx,
1955 : &pol,
1956 : level,
1957 : 0,
1958 : &info);
1959 0 : if (!W_ERROR_IS_OK(result)) {
1960 0 : printf ("Unable to retrieve printer information!\n");
1961 0 : goto done;
1962 : }
1963 :
1964 : /* Set the printer driver */
1965 :
1966 0 : spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
1967 0 : info2.drivername = argv[2];
1968 :
1969 0 : info_ctr.level = 2;
1970 0 : info_ctr.info.info2 = &info2;
1971 :
1972 0 : status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1973 : &pol,
1974 : &info_ctr,
1975 : &devmode_ctr,
1976 : &secdesc_ctr,
1977 : 0, /* command */
1978 : &result);
1979 0 : if (!NT_STATUS_IS_OK(status)) {
1980 0 : result = ntstatus_to_werror(status);
1981 0 : goto done;
1982 : }
1983 0 : if (!W_ERROR_IS_OK(result)) {
1984 0 : printf("SetPrinter call failed!\n");
1985 0 : goto done;
1986 : }
1987 :
1988 0 : printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
1989 :
1990 0 : done:
1991 : /* Cleanup */
1992 :
1993 0 : if (is_valid_policy_hnd(&pol)) {
1994 : WERROR _result;
1995 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
1996 : }
1997 :
1998 0 : return result;
1999 : }
2000 :
2001 :
2002 : /****************************************************************************
2003 : ****************************************************************************/
2004 :
2005 0 : static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
2006 : TALLOC_CTX *mem_ctx,
2007 : int argc, const char **argv)
2008 : {
2009 0 : WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
2010 : NTSTATUS status;
2011 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2012 :
2013 : int i;
2014 0 : int vers = -1;
2015 :
2016 0 : const char *arch = NULL;
2017 0 : uint32_t delete_flags = 0;
2018 :
2019 : /* parse the command arguments */
2020 0 : if (argc < 2 || argc > 5) {
2021 0 : printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
2022 0 : return WERR_OK;
2023 : }
2024 :
2025 0 : if (argc >= 3)
2026 0 : arch = argv[2];
2027 0 : if (argc >= 4) {
2028 0 : vers = atoi(argv[3]);
2029 0 : delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
2030 : }
2031 0 : if (argc == 5)
2032 0 : delete_flags = atoi(argv[4]);
2033 :
2034 : /* delete the driver for all architectures */
2035 0 : for (i=0; archi_table[i].long_archi; i++) {
2036 :
2037 0 : if (arch && !strequal(archi_table[i].long_archi, arch))
2038 0 : continue;
2039 :
2040 0 : if (vers >= 0 && archi_table[i].version != vers)
2041 0 : continue;
2042 :
2043 : /* make the call to remove the driver */
2044 0 : status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
2045 0 : cli->srv_name_slash,
2046 0 : archi_table[i].long_archi,
2047 0 : argv[1],
2048 : delete_flags,
2049 0 : archi_table[i].version,
2050 : &result);
2051 0 : if (!NT_STATUS_IS_OK(status)) {
2052 0 : return ntstatus_to_werror(status);
2053 : }
2054 0 : if ( !W_ERROR_IS_OK(result) )
2055 : {
2056 0 : if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2057 0 : printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
2058 0 : argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
2059 : }
2060 : }
2061 : else
2062 : {
2063 0 : printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
2064 0 : archi_table[i].long_archi, archi_table[i].version);
2065 0 : ret = WERR_OK;
2066 : }
2067 : }
2068 :
2069 0 : return ret;
2070 : }
2071 :
2072 :
2073 : /****************************************************************************
2074 : ****************************************************************************/
2075 :
2076 0 : static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
2077 : TALLOC_CTX *mem_ctx,
2078 : int argc, const char **argv)
2079 : {
2080 0 : WERROR result = WERR_OK;
2081 : NTSTATUS status;
2082 : int i;
2083 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2084 :
2085 : /* parse the command arguments */
2086 0 : if (argc != 2) {
2087 0 : printf ("Usage: %s <driver>\n", argv[0]);
2088 0 : return WERR_OK;
2089 : }
2090 :
2091 : /* delete the driver for all architectures */
2092 0 : for (i=0; archi_table[i].long_archi; i++) {
2093 0 : result = WERR_OK;
2094 :
2095 : /* make the call to remove the driver */
2096 0 : status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
2097 0 : cli->srv_name_slash,
2098 0 : archi_table[i].long_archi,
2099 0 : argv[1],
2100 : &result);
2101 0 : if (!NT_STATUS_IS_OK(status)) {
2102 0 : result = ntstatus_to_werror(status);
2103 0 : continue;
2104 : }
2105 0 : if ( !W_ERROR_IS_OK(result) ) {
2106 0 : if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
2107 0 : printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
2108 0 : argv[1], archi_table[i].long_archi,
2109 : win_errstr(result));
2110 : }
2111 : } else {
2112 0 : printf ("Driver %s removed for arch [%s].\n", argv[1],
2113 0 : archi_table[i].long_archi);
2114 : }
2115 : }
2116 :
2117 0 : return result;
2118 : }
2119 :
2120 : /****************************************************************************
2121 : ****************************************************************************/
2122 :
2123 0 : static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
2124 : TALLOC_CTX *mem_ctx,
2125 : int argc, const char **argv)
2126 : {
2127 : WERROR result;
2128 : NTSTATUS status;
2129 0 : const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
2130 : DATA_BLOB buffer;
2131 : uint32_t offered;
2132 0 : union spoolss_PrintProcessorDirectoryInfo info = {};
2133 : uint32_t needed;
2134 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2135 :
2136 : /* parse the command arguments */
2137 0 : if (argc > 2) {
2138 0 : printf ("Usage: %s [environment]\n", argv[0]);
2139 0 : return WERR_OK;
2140 : }
2141 :
2142 0 : if (argc == 2) {
2143 0 : environment = argv[1];
2144 : }
2145 :
2146 0 : status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2147 0 : cli->srv_name_slash,
2148 : environment,
2149 : 1,
2150 : NULL, /* buffer */
2151 : 0, /* offered */
2152 : NULL, /* info */
2153 : &needed,
2154 : &result);
2155 0 : if (!NT_STATUS_IS_OK(status)) {
2156 0 : return ntstatus_to_werror(status);
2157 : }
2158 0 : if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
2159 0 : offered = needed;
2160 0 : buffer = data_blob_talloc_zero(mem_ctx, needed);
2161 :
2162 0 : status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
2163 0 : cli->srv_name_slash,
2164 : environment,
2165 : 1,
2166 : &buffer,
2167 : offered,
2168 : &info,
2169 : &needed,
2170 : &result);
2171 0 : if (!NT_STATUS_IS_OK(status)) {
2172 0 : return ntstatus_to_werror(status);
2173 : }
2174 : }
2175 :
2176 0 : if (W_ERROR_IS_OK(result) && info.info1.directory_name != NULL) {
2177 0 : printf("%s\n", info.info1.directory_name);
2178 : }
2179 :
2180 0 : return result;
2181 : }
2182 :
2183 : /****************************************************************************
2184 : ****************************************************************************/
2185 :
2186 0 : static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2187 : int argc, const char **argv)
2188 : {
2189 : struct policy_handle handle;
2190 : WERROR werror;
2191 : NTSTATUS status;
2192 : const char *printername;
2193 : struct spoolss_AddFormInfoCtr info_ctr;
2194 : struct spoolss_AddFormInfo1 info1;
2195 : struct spoolss_AddFormInfo2 info2;
2196 0 : uint32_t level = 1;
2197 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2198 :
2199 : /* Parse the command arguments */
2200 :
2201 0 : if (argc < 3 || argc > 5) {
2202 0 : printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2203 0 : return WERR_OK;
2204 : }
2205 :
2206 : /* Get a printer handle */
2207 :
2208 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2209 :
2210 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2211 : printername,
2212 : PRINTER_ALL_ACCESS,
2213 : &handle);
2214 0 : if (!W_ERROR_IS_OK(werror))
2215 0 : goto done;
2216 :
2217 : /* Dummy up some values for the form data */
2218 :
2219 0 : if (argc == 4) {
2220 0 : level = atoi(argv[3]);
2221 : }
2222 :
2223 0 : switch (level) {
2224 0 : case 1:
2225 0 : info1.flags = SPOOLSS_FORM_USER;
2226 0 : info1.form_name = argv[2];
2227 0 : info1.size.width = 100;
2228 0 : info1.size.height = 100;
2229 0 : info1.area.left = 0;
2230 0 : info1.area.top = 10;
2231 0 : info1.area.right = 20;
2232 0 : info1.area.bottom = 30;
2233 :
2234 0 : info_ctr.level = 1;
2235 0 : info_ctr.info.info1 = &info1;
2236 :
2237 0 : break;
2238 0 : case 2:
2239 0 : info2.flags = SPOOLSS_FORM_USER;
2240 0 : info2.form_name = argv[2];
2241 0 : info2.size.width = 100;
2242 0 : info2.size.height = 100;
2243 0 : info2.area.left = 0;
2244 0 : info2.area.top = 10;
2245 0 : info2.area.right = 20;
2246 0 : info2.area.bottom = 30;
2247 0 : info2.keyword = argv[2];
2248 0 : info2.string_type = SPOOLSS_FORM_STRING_TYPE_NONE;
2249 0 : info2.mui_dll = NULL;
2250 0 : info2.ressource_id = 0;
2251 0 : info2.display_name = argv[2];
2252 0 : info2.lang_id = 0;
2253 :
2254 0 : info_ctr.level = 2;
2255 0 : info_ctr.info.info2 = &info2;
2256 :
2257 0 : break;
2258 0 : default:
2259 0 : werror = WERR_INVALID_PARAMETER;
2260 0 : goto done;
2261 : }
2262 :
2263 : /* Add the form */
2264 :
2265 0 : status = dcerpc_spoolss_AddForm(b, mem_ctx,
2266 : &handle,
2267 : &info_ctr,
2268 : &werror);
2269 0 : if (!NT_STATUS_IS_OK(status)) {
2270 0 : werror = ntstatus_to_werror(status);
2271 0 : goto done;
2272 : }
2273 0 : done:
2274 0 : if (is_valid_policy_hnd(&handle)) {
2275 : WERROR _result;
2276 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2277 : }
2278 :
2279 0 : return werror;
2280 : }
2281 :
2282 : /****************************************************************************
2283 : ****************************************************************************/
2284 :
2285 0 : static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2286 : int argc, const char **argv)
2287 : {
2288 : struct policy_handle handle;
2289 : WERROR werror;
2290 : NTSTATUS status;
2291 : const char *printername;
2292 : struct spoolss_AddFormInfoCtr info_ctr;
2293 : struct spoolss_AddFormInfo1 info1;
2294 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2295 :
2296 : /* Parse the command arguments */
2297 :
2298 0 : if (argc != 3) {
2299 0 : printf ("Usage: %s <printer> <formname>\n", argv[0]);
2300 0 : return WERR_OK;
2301 : }
2302 :
2303 : /* Get a printer handle */
2304 :
2305 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2306 :
2307 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2308 : printername,
2309 : SEC_FLAG_MAXIMUM_ALLOWED,
2310 : &handle);
2311 0 : if (!W_ERROR_IS_OK(werror))
2312 0 : goto done;
2313 :
2314 : /* Dummy up some values for the form data */
2315 :
2316 0 : info1.flags = SPOOLSS_FORM_PRINTER;
2317 0 : info1.size.width = 100;
2318 0 : info1.size.height = 100;
2319 0 : info1.area.left = 0;
2320 0 : info1.area.top = 1000;
2321 0 : info1.area.right = 2000;
2322 0 : info1.area.bottom = 3000;
2323 0 : info1.form_name = argv[2];
2324 :
2325 0 : info_ctr.info.info1 = &info1;
2326 0 : info_ctr.level = 1;
2327 :
2328 : /* Set the form */
2329 :
2330 0 : status = dcerpc_spoolss_SetForm(b, mem_ctx,
2331 : &handle,
2332 0 : argv[2],
2333 : &info_ctr,
2334 : &werror);
2335 0 : if (!NT_STATUS_IS_OK(status)) {
2336 0 : werror = ntstatus_to_werror(status);
2337 0 : goto done;
2338 : }
2339 0 : done:
2340 0 : if (is_valid_policy_hnd(&handle)) {
2341 : WERROR _result;
2342 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2343 : }
2344 :
2345 0 : return werror;
2346 : }
2347 :
2348 : /****************************************************************************
2349 : ****************************************************************************/
2350 :
2351 0 : static const char *get_form_flag(int form_flag)
2352 : {
2353 0 : switch (form_flag) {
2354 0 : case SPOOLSS_FORM_USER:
2355 0 : return "FORM_USER";
2356 0 : case SPOOLSS_FORM_BUILTIN:
2357 0 : return "FORM_BUILTIN";
2358 0 : case SPOOLSS_FORM_PRINTER:
2359 0 : return "FORM_PRINTER";
2360 0 : default:
2361 0 : return "unknown";
2362 : }
2363 : }
2364 :
2365 : /****************************************************************************
2366 : ****************************************************************************/
2367 :
2368 0 : static void display_form_info1(struct spoolss_FormInfo1 *r)
2369 : {
2370 0 : printf("%s\n" \
2371 : "\tflag: %s (%d)\n" \
2372 : "\twidth: %d, length: %d\n" \
2373 : "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
2374 0 : r->form_name, get_form_flag(r->flags), r->flags,
2375 : r->size.width, r->size.height,
2376 : r->area.left, r->area.right,
2377 : r->area.top, r->area.bottom);
2378 0 : }
2379 :
2380 : /****************************************************************************
2381 : ****************************************************************************/
2382 :
2383 0 : static void display_form_info2(struct spoolss_FormInfo2 *r)
2384 : {
2385 0 : printf("%s\n" \
2386 : "\tflag: %s (%d)\n" \
2387 : "\twidth: %d, length: %d\n" \
2388 : "\tleft: %d, right: %d, top: %d, bottom: %d\n",
2389 0 : r->form_name, get_form_flag(r->flags), r->flags,
2390 : r->size.width, r->size.height,
2391 : r->area.left, r->area.right,
2392 : r->area.top, r->area.bottom);
2393 0 : printf("\tkeyword: %s\n", r->keyword);
2394 0 : printf("\tstring_type: 0x%08x\n", r->string_type);
2395 0 : printf("\tmui_dll: %s\n", r->mui_dll);
2396 0 : printf("\tressource_id: 0x%08x\n", r->ressource_id);
2397 0 : printf("\tdisplay_name: %s\n", r->display_name);
2398 0 : printf("\tlang_id: %d\n", r->lang_id);
2399 0 : printf("\n");
2400 0 : }
2401 :
2402 : /****************************************************************************
2403 : ****************************************************************************/
2404 :
2405 0 : static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
2406 : int argc, const char **argv)
2407 : {
2408 : struct policy_handle handle;
2409 : WERROR werror;
2410 : NTSTATUS status;
2411 : const char *printername;
2412 : DATA_BLOB buffer;
2413 0 : uint32_t offered = 0;
2414 : union spoolss_FormInfo info;
2415 : uint32_t needed;
2416 0 : uint32_t level = 1;
2417 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2418 :
2419 : /* Parse the command arguments */
2420 :
2421 0 : if (argc < 3 || argc > 5) {
2422 0 : printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
2423 0 : return WERR_OK;
2424 : }
2425 :
2426 : /* Get a printer handle */
2427 :
2428 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2429 :
2430 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2431 : printername,
2432 : SEC_FLAG_MAXIMUM_ALLOWED,
2433 : &handle);
2434 0 : if (!W_ERROR_IS_OK(werror))
2435 0 : goto done;
2436 :
2437 0 : if (argc == 4) {
2438 0 : level = atoi(argv[3]);
2439 : }
2440 :
2441 : /* Get the form */
2442 :
2443 0 : status = dcerpc_spoolss_GetForm(b, mem_ctx,
2444 : &handle,
2445 0 : argv[2],
2446 : level,
2447 : NULL,
2448 : offered,
2449 : &info,
2450 : &needed,
2451 : &werror);
2452 0 : if (!NT_STATUS_IS_OK(status)) {
2453 0 : werror = ntstatus_to_werror(status);
2454 0 : goto done;
2455 : }
2456 0 : if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
2457 0 : buffer = data_blob_talloc_zero(mem_ctx, needed);
2458 0 : offered = needed;
2459 0 : status = dcerpc_spoolss_GetForm(b, mem_ctx,
2460 : &handle,
2461 0 : argv[2],
2462 : level,
2463 : &buffer,
2464 : offered,
2465 : &info,
2466 : &needed,
2467 : &werror);
2468 0 : if (!NT_STATUS_IS_OK(status)) {
2469 0 : werror = ntstatus_to_werror(status);
2470 0 : goto done;
2471 : }
2472 : }
2473 :
2474 0 : if (!W_ERROR_IS_OK(werror)) {
2475 0 : goto done;
2476 : }
2477 :
2478 0 : switch (level) {
2479 0 : case 1:
2480 0 : display_form_info1(&info.info1);
2481 0 : break;
2482 0 : case 2:
2483 0 : display_form_info2(&info.info2);
2484 0 : break;
2485 : }
2486 :
2487 0 : done:
2488 0 : if (is_valid_policy_hnd(&handle)) {
2489 : WERROR _result;
2490 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2491 : }
2492 :
2493 0 : return werror;
2494 : }
2495 :
2496 : /****************************************************************************
2497 : ****************************************************************************/
2498 :
2499 0 : static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
2500 : TALLOC_CTX *mem_ctx, int argc,
2501 : const char **argv)
2502 : {
2503 : struct policy_handle handle;
2504 : WERROR werror;
2505 : NTSTATUS status;
2506 : const char *printername;
2507 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2508 :
2509 : /* Parse the command arguments */
2510 :
2511 0 : if (argc != 3) {
2512 0 : printf ("Usage: %s <printer> <formname>\n", argv[0]);
2513 0 : return WERR_OK;
2514 : }
2515 :
2516 : /* Get a printer handle */
2517 :
2518 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2519 :
2520 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2521 : printername,
2522 : SEC_FLAG_MAXIMUM_ALLOWED,
2523 : &handle);
2524 0 : if (!W_ERROR_IS_OK(werror))
2525 0 : goto done;
2526 :
2527 : /* Delete the form */
2528 :
2529 0 : status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
2530 : &handle,
2531 0 : argv[2],
2532 : &werror);
2533 0 : if (!NT_STATUS_IS_OK(status)) {
2534 0 : werror = ntstatus_to_werror(status);
2535 0 : goto done;
2536 : }
2537 :
2538 0 : done:
2539 0 : if (is_valid_policy_hnd(&handle)) {
2540 : WERROR _result;
2541 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2542 : }
2543 :
2544 0 : return werror;
2545 : }
2546 :
2547 : /****************************************************************************
2548 : ****************************************************************************/
2549 :
2550 0 : static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
2551 : TALLOC_CTX *mem_ctx, int argc,
2552 : const char **argv)
2553 : {
2554 : struct policy_handle handle;
2555 : WERROR werror;
2556 : const char *printername;
2557 0 : uint32_t num_forms, level = 1, i;
2558 : union spoolss_FormInfo *forms;
2559 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2560 :
2561 : /* Parse the command arguments */
2562 :
2563 0 : if (argc < 2 || argc > 4) {
2564 0 : printf ("Usage: %s <printer> [level]\n", argv[0]);
2565 0 : return WERR_OK;
2566 : }
2567 :
2568 : /* Get a printer handle */
2569 :
2570 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2571 :
2572 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2573 : printername,
2574 : SEC_FLAG_MAXIMUM_ALLOWED,
2575 : &handle);
2576 0 : if (!W_ERROR_IS_OK(werror))
2577 0 : goto done;
2578 :
2579 0 : if (argc == 3) {
2580 0 : level = atoi(argv[2]);
2581 : }
2582 :
2583 : /* Enumerate forms */
2584 :
2585 0 : werror = rpccli_spoolss_enumforms(cli, mem_ctx,
2586 : &handle,
2587 : level,
2588 : 0,
2589 : &num_forms,
2590 : &forms);
2591 :
2592 0 : if (!W_ERROR_IS_OK(werror))
2593 0 : goto done;
2594 :
2595 : /* Display output */
2596 :
2597 0 : for (i = 0; i < num_forms; i++) {
2598 0 : switch (level) {
2599 0 : case 1:
2600 0 : display_form_info1(&forms[i].info1);
2601 0 : break;
2602 0 : case 2:
2603 0 : display_form_info2(&forms[i].info2);
2604 0 : break;
2605 : }
2606 : }
2607 :
2608 0 : done:
2609 0 : if (is_valid_policy_hnd(&handle)) {
2610 : WERROR _result;
2611 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
2612 : }
2613 :
2614 0 : return werror;
2615 : }
2616 :
2617 : /****************************************************************************
2618 : ****************************************************************************/
2619 :
2620 0 : static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
2621 : TALLOC_CTX *mem_ctx,
2622 : int argc, const char **argv)
2623 : {
2624 : WERROR result;
2625 : NTSTATUS status;
2626 : const char *printername;
2627 0 : struct policy_handle pol = { 0, };
2628 : union spoolss_PrinterInfo info;
2629 : enum winreg_Type type;
2630 : union spoolss_PrinterData data;
2631 : DATA_BLOB blob;
2632 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2633 0 : int error = 0;
2634 :
2635 : /* parse the command arguments */
2636 0 : if (argc < 5) {
2637 0 : printf ("Usage: %s <printer> <string|binary|dword|multistring>"
2638 : " <value> <data>\n",
2639 : argv[0]);
2640 0 : return WERR_OK;
2641 : }
2642 :
2643 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2644 :
2645 0 : type = REG_NONE;
2646 :
2647 0 : if (strequal(argv[2], "string")) {
2648 0 : type = REG_SZ;
2649 : }
2650 :
2651 0 : if (strequal(argv[2], "binary")) {
2652 0 : type = REG_BINARY;
2653 : }
2654 :
2655 0 : if (strequal(argv[2], "dword")) {
2656 0 : type = REG_DWORD;
2657 : }
2658 :
2659 0 : if (strequal(argv[2], "multistring")) {
2660 0 : type = REG_MULTI_SZ;
2661 : }
2662 :
2663 0 : if (type == REG_NONE) {
2664 0 : printf("Unknown data type: %s\n", argv[2]);
2665 0 : result = WERR_INVALID_PARAMETER;
2666 0 : goto done;
2667 : }
2668 :
2669 : /* get a printer handle */
2670 :
2671 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2672 : printername,
2673 : SEC_FLAG_MAXIMUM_ALLOWED,
2674 : &pol);
2675 0 : if (!W_ERROR_IS_OK(result)) {
2676 0 : goto done;
2677 : }
2678 :
2679 0 : result = rpccli_spoolss_getprinter(cli, mem_ctx,
2680 : &pol,
2681 : 0,
2682 : 0,
2683 : &info);
2684 0 : if (!W_ERROR_IS_OK(result)) {
2685 0 : goto done;
2686 : }
2687 :
2688 0 : printf("%s\n", current_timestring(mem_ctx, true));
2689 0 : printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
2690 :
2691 : /* Set the printer data */
2692 :
2693 0 : switch (type) {
2694 0 : case REG_SZ:
2695 0 : data.string = talloc_strdup(mem_ctx, argv[4]);
2696 0 : W_ERROR_HAVE_NO_MEMORY(data.string);
2697 0 : break;
2698 0 : case REG_DWORD:
2699 0 : data.value = smb_strtoul(argv[4],
2700 : NULL,
2701 : 10,
2702 : &error,
2703 : SMB_STR_STANDARD);
2704 0 : if (error != 0) {
2705 0 : result = WERR_INVALID_PARAMETER;
2706 0 : goto done;
2707 : }
2708 :
2709 0 : break;
2710 0 : case REG_BINARY:
2711 0 : data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
2712 0 : break;
2713 0 : case REG_MULTI_SZ: {
2714 : int i;
2715 : size_t num_strings;
2716 0 : const char **strings = NULL;
2717 :
2718 0 : num_strings = 0;
2719 :
2720 0 : for (i=4; i<argc; i++) {
2721 0 : if (strcmp(argv[i], "NULL") == 0) {
2722 0 : argv[i] = "";
2723 : }
2724 0 : if (!add_string_to_array(mem_ctx, argv[i],
2725 : &strings,
2726 : &num_strings)) {
2727 0 : result = WERR_NOT_ENOUGH_MEMORY;
2728 0 : goto done;
2729 : }
2730 : }
2731 0 : data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
2732 0 : if (!data.string_array) {
2733 0 : result = WERR_NOT_ENOUGH_MEMORY;
2734 0 : goto done;
2735 : }
2736 0 : for (i=0; i < num_strings; i++) {
2737 0 : data.string_array[i] = strings[i];
2738 : }
2739 0 : break;
2740 : }
2741 0 : default:
2742 0 : printf("Unknown data type: %s\n", argv[2]);
2743 0 : result = WERR_INVALID_PARAMETER;
2744 0 : goto done;
2745 : }
2746 :
2747 0 : result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
2748 0 : if (!W_ERROR_IS_OK(result)) {
2749 0 : goto done;
2750 : }
2751 :
2752 0 : status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
2753 : &pol,
2754 0 : argv[3], /* value_name */
2755 : type,
2756 : blob.data,
2757 0 : blob.length,
2758 : &result);
2759 0 : if (!NT_STATUS_IS_OK(status)) {
2760 0 : printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2761 0 : result = ntstatus_to_werror(status);
2762 0 : goto done;
2763 : }
2764 0 : if (!W_ERROR_IS_OK(result)) {
2765 0 : printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
2766 0 : goto done;
2767 : }
2768 0 : printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
2769 :
2770 0 : result = rpccli_spoolss_getprinter(cli, mem_ctx,
2771 : &pol,
2772 : 0,
2773 : 0,
2774 : &info);
2775 0 : if (!W_ERROR_IS_OK(result)) {
2776 0 : goto done;
2777 : }
2778 :
2779 0 : printf("%s\n", current_timestring(mem_ctx, true));
2780 0 : printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
2781 :
2782 0 : done:
2783 : /* cleanup */
2784 0 : if (is_valid_policy_hnd(&pol)) {
2785 : WERROR _result;
2786 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
2787 : }
2788 :
2789 0 : return result;
2790 : }
2791 :
2792 : /****************************************************************************
2793 : ****************************************************************************/
2794 :
2795 0 : static void display_job_info1(struct spoolss_JobInfo1 *r)
2796 : {
2797 0 : printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
2798 : r->user_name, r->document_name, r->text_status, r->pages_printed,
2799 : r->total_pages);
2800 0 : }
2801 :
2802 : /****************************************************************************
2803 : ****************************************************************************/
2804 :
2805 4 : static void display_job_info2(struct spoolss_JobInfo2 *r)
2806 : {
2807 4 : printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
2808 : r->position, r->job_id,
2809 : r->user_name, r->document_name, r->text_status, r->pages_printed,
2810 : r->total_pages, r->size);
2811 4 : }
2812 :
2813 : /****************************************************************************
2814 : ****************************************************************************/
2815 :
2816 0 : static void display_job_info3(struct spoolss_JobInfo3 *r)
2817 : {
2818 0 : printf("jobid[%d], next_jobid[%d]\n",
2819 : r->job_id, r->next_job_id);
2820 0 : }
2821 :
2822 : /****************************************************************************
2823 : ****************************************************************************/
2824 :
2825 0 : static void display_job_info4(struct spoolss_JobInfo4 *r)
2826 : {
2827 0 : printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
2828 : r->position, r->job_id,
2829 : r->user_name, r->document_name, r->text_status, r->pages_printed,
2830 : r->total_pages, r->size, r->size_high);
2831 0 : }
2832 :
2833 : /****************************************************************************
2834 : ****************************************************************************/
2835 :
2836 6 : static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
2837 : TALLOC_CTX *mem_ctx, int argc,
2838 : const char **argv)
2839 : {
2840 : WERROR result;
2841 6 : uint32_t level = 1, count, i;
2842 : const char *printername;
2843 : struct policy_handle hnd;
2844 : union spoolss_JobInfo *info;
2845 6 : struct dcerpc_binding_handle *b = cli->binding_handle;
2846 :
2847 6 : if (argc < 2 || argc > 3) {
2848 0 : printf("Usage: %s printername [level]\n", argv[0]);
2849 0 : return WERR_OK;
2850 : }
2851 :
2852 6 : if (argc == 3) {
2853 6 : level = atoi(argv[2]);
2854 : }
2855 :
2856 : /* Open printer handle */
2857 :
2858 6 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2859 :
2860 6 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2861 : printername,
2862 : SEC_FLAG_MAXIMUM_ALLOWED,
2863 : &hnd);
2864 6 : if (!W_ERROR_IS_OK(result))
2865 0 : goto done;
2866 :
2867 : /* Enumerate ports */
2868 :
2869 6 : result = rpccli_spoolss_enumjobs(cli, mem_ctx,
2870 : &hnd,
2871 : 0, /* firstjob */
2872 : 1000, /* numjobs */
2873 : level,
2874 : 0,
2875 : &count,
2876 : &info);
2877 6 : if (!W_ERROR_IS_OK(result)) {
2878 0 : goto done;
2879 : }
2880 :
2881 10 : for (i = 0; i < count; i++) {
2882 4 : switch (level) {
2883 0 : case 1:
2884 0 : display_job_info1(&info[i].info1);
2885 0 : break;
2886 4 : case 2:
2887 4 : display_job_info2(&info[i].info2);
2888 4 : break;
2889 0 : default:
2890 0 : d_printf("unknown info level %d\n", level);
2891 0 : break;
2892 : }
2893 : }
2894 :
2895 6 : done:
2896 6 : if (is_valid_policy_hnd(&hnd)) {
2897 : WERROR _result;
2898 6 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2899 : }
2900 :
2901 6 : return result;
2902 : }
2903 :
2904 : /****************************************************************************
2905 : ****************************************************************************/
2906 :
2907 0 : static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
2908 : TALLOC_CTX *mem_ctx, int argc,
2909 : const char **argv)
2910 : {
2911 : WERROR result;
2912 : const char *printername;
2913 : struct policy_handle hnd;
2914 : uint32_t job_id;
2915 0 : uint32_t level = 1;
2916 : union spoolss_JobInfo info;
2917 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
2918 :
2919 0 : if (argc < 3 || argc > 4) {
2920 0 : printf("Usage: %s printername job_id [level]\n", argv[0]);
2921 0 : return WERR_OK;
2922 : }
2923 :
2924 0 : job_id = atoi(argv[2]);
2925 :
2926 0 : if (argc == 4) {
2927 0 : level = atoi(argv[3]);
2928 : }
2929 :
2930 : /* Open printer handle */
2931 :
2932 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
2933 :
2934 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
2935 : printername,
2936 : SEC_FLAG_MAXIMUM_ALLOWED,
2937 : &hnd);
2938 0 : if (!W_ERROR_IS_OK(result)) {
2939 0 : goto done;
2940 : }
2941 :
2942 : /* Enumerate ports */
2943 :
2944 0 : result = rpccli_spoolss_getjob(cli, mem_ctx,
2945 : &hnd,
2946 : job_id,
2947 : level,
2948 : 0,
2949 : &info);
2950 :
2951 0 : if (!W_ERROR_IS_OK(result)) {
2952 0 : goto done;
2953 : }
2954 :
2955 0 : switch (level) {
2956 0 : case 1:
2957 0 : display_job_info1(&info.info1);
2958 0 : break;
2959 0 : case 2:
2960 0 : display_job_info2(&info.info2);
2961 0 : break;
2962 0 : case 3:
2963 0 : display_job_info3(&info.info3);
2964 0 : break;
2965 0 : case 4:
2966 0 : display_job_info4(&info.info4);
2967 0 : break;
2968 0 : default:
2969 0 : d_printf("unknown info level %d\n", level);
2970 0 : break;
2971 : }
2972 :
2973 0 : done:
2974 0 : if (is_valid_policy_hnd(&hnd)) {
2975 : WERROR _result;
2976 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
2977 : }
2978 :
2979 0 : return result;
2980 : }
2981 :
2982 : /****************************************************************************
2983 : ****************************************************************************/
2984 :
2985 : static struct {
2986 : const char *name;
2987 : enum spoolss_JobControl val;
2988 : } cmdvals[] = {
2989 : {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
2990 : {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
2991 : {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
2992 : {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
2993 : {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
2994 : {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
2995 : {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
2996 : {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
2997 : {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
2998 : };
2999 :
3000 0 : static enum spoolss_JobControl parse_setjob_command(const char *cmd)
3001 : {
3002 : int i;
3003 :
3004 0 : for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
3005 0 : if (strequal(cmdvals[i].name, cmd)) {
3006 0 : return cmdvals[i].val;
3007 : }
3008 : }
3009 0 : return (enum spoolss_JobControl)atoi(cmd);
3010 : }
3011 :
3012 0 : static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
3013 : TALLOC_CTX *mem_ctx, int argc,
3014 : const char **argv)
3015 : {
3016 : WERROR result;
3017 : NTSTATUS status;
3018 : const char *printername;
3019 : struct policy_handle hnd;
3020 : uint32_t job_id;
3021 : enum spoolss_JobControl command;
3022 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3023 :
3024 0 : if (argc != 4) {
3025 0 : printf("Usage: %s printername job_id command\n", argv[0]);
3026 0 : printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
3027 : "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
3028 0 : return WERR_OK;
3029 : }
3030 :
3031 0 : job_id = atoi(argv[2]);
3032 0 : command = parse_setjob_command(argv[3]);
3033 :
3034 : /* Open printer handle */
3035 :
3036 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3037 :
3038 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3039 : printername,
3040 : SEC_FLAG_MAXIMUM_ALLOWED,
3041 : &hnd);
3042 0 : if (!W_ERROR_IS_OK(result)) {
3043 0 : goto done;
3044 : }
3045 :
3046 : /* Set Job */
3047 :
3048 0 : status = dcerpc_spoolss_SetJob(b, mem_ctx,
3049 : &hnd,
3050 : job_id,
3051 : NULL,
3052 : command,
3053 : &result);
3054 0 : if (!NT_STATUS_IS_OK(status)) {
3055 0 : result = ntstatus_to_werror(status);
3056 0 : goto done;
3057 : }
3058 0 : if (!W_ERROR_IS_OK(result)) {
3059 0 : goto done;
3060 : }
3061 :
3062 0 : done:
3063 0 : if (is_valid_policy_hnd(&hnd)) {
3064 : WERROR _result;
3065 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3066 : }
3067 :
3068 0 : return result;
3069 : }
3070 :
3071 : /****************************************************************************
3072 : ****************************************************************************/
3073 :
3074 0 : static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
3075 : TALLOC_CTX *mem_ctx, int argc,
3076 : const char **argv)
3077 : {
3078 : WERROR result;
3079 : NTSTATUS status;
3080 : const char *printername;
3081 : struct policy_handle hnd;
3082 : uint32_t value_needed;
3083 : enum winreg_Type type;
3084 : uint32_t data_needed;
3085 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3086 : struct spoolss_EnumPrinterData r;
3087 :
3088 0 : if (argc != 2) {
3089 0 : printf("Usage: %s printername\n", argv[0]);
3090 0 : return WERR_OK;
3091 : }
3092 :
3093 : /* Open printer handle */
3094 :
3095 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3096 :
3097 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3098 : printername,
3099 : SEC_FLAG_MAXIMUM_ALLOWED,
3100 : &hnd);
3101 0 : if (!W_ERROR_IS_OK(result)) {
3102 0 : goto done;
3103 : }
3104 :
3105 : /* Enumerate data */
3106 :
3107 0 : r.in.handle = &hnd;
3108 0 : r.in.enum_index = 0;
3109 0 : r.in.value_offered = 0;
3110 0 : r.in.data_offered = 0;
3111 0 : r.out.value_name = NULL;
3112 0 : r.out.value_needed = &value_needed;
3113 0 : r.out.type = &type;
3114 0 : r.out.data = NULL;
3115 0 : r.out.data_needed = &data_needed;
3116 :
3117 0 : status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3118 0 : if (!NT_STATUS_IS_OK(status)) {
3119 0 : result = ntstatus_to_werror(status);
3120 0 : goto done;
3121 : }
3122 :
3123 0 : if (!W_ERROR_IS_OK(r.out.result)) {
3124 0 : result = r.out.result;
3125 0 : goto done;
3126 : }
3127 :
3128 0 : r.in.data_offered = *r.out.data_needed;
3129 0 : r.in.value_offered = *r.out.value_needed;
3130 0 : r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
3131 0 : r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
3132 :
3133 : do {
3134 :
3135 0 : status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
3136 0 : if (!NT_STATUS_IS_OK(status)) {
3137 0 : result = ntstatus_to_werror(status);
3138 0 : goto done;
3139 : }
3140 :
3141 0 : if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3142 0 : result = WERR_OK;
3143 0 : break;
3144 : }
3145 :
3146 0 : r.in.enum_index++;
3147 :
3148 0 : display_reg_value(r.out.value_name, *r.out.type,
3149 0 : data_blob_const(r.out.data, r.in.data_offered));
3150 :
3151 0 : } while (W_ERROR_IS_OK(r.out.result));
3152 :
3153 0 : done:
3154 0 : if (is_valid_policy_hnd(&hnd)) {
3155 : WERROR _result;
3156 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3157 : }
3158 :
3159 0 : return result;
3160 : }
3161 :
3162 : /****************************************************************************
3163 : ****************************************************************************/
3164 :
3165 0 : static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
3166 : TALLOC_CTX *mem_ctx, int argc,
3167 : const char **argv)
3168 : {
3169 : WERROR result;
3170 : uint32_t i;
3171 : const char *printername;
3172 : struct policy_handle hnd;
3173 : uint32_t count;
3174 : struct spoolss_PrinterEnumValues *info;
3175 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3176 :
3177 0 : if (argc != 3) {
3178 0 : printf("Usage: %s printername <keyname>\n", argv[0]);
3179 0 : return WERR_OK;
3180 : }
3181 :
3182 : /* Open printer handle */
3183 :
3184 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3185 :
3186 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3187 : printername,
3188 : SEC_FLAG_MAXIMUM_ALLOWED,
3189 : &hnd);
3190 0 : if (!W_ERROR_IS_OK(result)) {
3191 0 : goto done;
3192 : }
3193 :
3194 : /* Enumerate subkeys */
3195 :
3196 0 : result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
3197 : &hnd,
3198 0 : argv[2],
3199 : 0,
3200 : &count,
3201 : &info);
3202 0 : if (!W_ERROR_IS_OK(result)) {
3203 0 : goto done;
3204 : }
3205 :
3206 0 : for (i=0; i < count; i++) {
3207 0 : display_printer_data(info[i].value_name,
3208 0 : info[i].type,
3209 0 : info[i].data->data,
3210 0 : info[i].data->length);
3211 : }
3212 :
3213 0 : done:
3214 0 : if (is_valid_policy_hnd(&hnd)) {
3215 : WERROR _result;
3216 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3217 : }
3218 :
3219 0 : return result;
3220 : }
3221 :
3222 : /****************************************************************************
3223 : ****************************************************************************/
3224 :
3225 0 : static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
3226 : TALLOC_CTX *mem_ctx, int argc,
3227 : const char **argv)
3228 : {
3229 : WERROR result;
3230 : const char *printername;
3231 0 : const char *keyname = NULL;
3232 : struct policy_handle hnd;
3233 0 : const char **key_buffer = NULL;
3234 : int i;
3235 0 : uint32_t offered = 0;
3236 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3237 :
3238 0 : if (argc < 2 || argc > 4) {
3239 0 : printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
3240 0 : return WERR_OK;
3241 : }
3242 :
3243 0 : if (argc >= 3) {
3244 0 : keyname = argv[2];
3245 : } else {
3246 0 : keyname = "";
3247 : }
3248 :
3249 0 : if (argc == 4) {
3250 0 : offered = atoi(argv[3]);
3251 : }
3252 :
3253 : /* Open printer handle */
3254 :
3255 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3256 :
3257 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3258 : printername,
3259 : SEC_FLAG_MAXIMUM_ALLOWED,
3260 : &hnd);
3261 0 : if (!W_ERROR_IS_OK(result)) {
3262 0 : goto done;
3263 : }
3264 :
3265 : /* Enumerate subkeys */
3266 :
3267 0 : result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
3268 : &hnd,
3269 : keyname,
3270 : &key_buffer,
3271 : offered);
3272 :
3273 0 : if (!W_ERROR_IS_OK(result)) {
3274 0 : goto done;
3275 : }
3276 :
3277 0 : for (i=0; key_buffer && key_buffer[i]; i++) {
3278 0 : printf("%s\n", key_buffer[i]);
3279 : }
3280 :
3281 0 : done:
3282 :
3283 0 : if (is_valid_policy_hnd(&hnd)) {
3284 : WERROR _result;
3285 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3286 : }
3287 :
3288 0 : return result;
3289 : }
3290 :
3291 : /****************************************************************************
3292 : ****************************************************************************/
3293 :
3294 0 : static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
3295 : TALLOC_CTX *mem_ctx, int argc,
3296 : const char **argv)
3297 : {
3298 : const char *printername;
3299 : const char *clientname;
3300 0 : struct policy_handle hnd = { 0, };
3301 : WERROR result;
3302 : NTSTATUS status;
3303 : struct spoolss_NotifyOption option;
3304 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3305 :
3306 0 : if (argc != 2) {
3307 0 : printf("Usage: %s printername\n", argv[0]);
3308 0 : result = WERR_OK;
3309 0 : goto done;
3310 : }
3311 :
3312 : /* Open printer */
3313 :
3314 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3315 :
3316 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3317 : printername,
3318 : SEC_FLAG_MAXIMUM_ALLOWED,
3319 : &hnd);
3320 0 : if (!W_ERROR_IS_OK(result)) {
3321 0 : printf("Error opening %s\n", argv[1]);
3322 0 : goto done;
3323 : }
3324 :
3325 : /* Create spool options */
3326 :
3327 0 : option.version = 2;
3328 0 : option.count = 2;
3329 :
3330 0 : option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
3331 0 : if (option.types == NULL) {
3332 0 : result = WERR_NOT_ENOUGH_MEMORY;
3333 0 : goto done;
3334 : }
3335 :
3336 0 : option.types[0].type = PRINTER_NOTIFY_TYPE;
3337 0 : option.types[0].count = 1;
3338 0 : option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3339 0 : if (option.types[0].fields == NULL) {
3340 0 : result = WERR_NOT_ENOUGH_MEMORY;
3341 0 : goto done;
3342 : }
3343 0 : option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
3344 :
3345 0 : option.types[1].type = JOB_NOTIFY_TYPE;
3346 0 : option.types[1].count = 1;
3347 0 : option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
3348 0 : if (option.types[1].fields == NULL) {
3349 0 : result = WERR_NOT_ENOUGH_MEMORY;
3350 0 : goto done;
3351 : }
3352 0 : option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
3353 :
3354 0 : clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
3355 0 : if (!clientname) {
3356 0 : result = WERR_NOT_ENOUGH_MEMORY;
3357 0 : goto done;
3358 : }
3359 :
3360 : /* Send rffpcnex */
3361 :
3362 0 : status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
3363 : &hnd,
3364 : 0,
3365 : 0,
3366 : clientname,
3367 : 123,
3368 : &option,
3369 : &result);
3370 0 : if (!NT_STATUS_IS_OK(status)) {
3371 0 : result = ntstatus_to_werror(status);
3372 0 : goto done;
3373 : }
3374 0 : if (!W_ERROR_IS_OK(result)) {
3375 0 : printf("Error rffpcnex %s\n", argv[1]);
3376 0 : goto done;
3377 : }
3378 :
3379 0 : done:
3380 0 : if (is_valid_policy_hnd(&hnd)) {
3381 : WERROR _result;
3382 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
3383 : }
3384 :
3385 0 : return result;
3386 : }
3387 :
3388 : /****************************************************************************
3389 : ****************************************************************************/
3390 :
3391 0 : static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3392 : struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3393 : {
3394 : union spoolss_PrinterInfo info1, info2;
3395 : WERROR werror;
3396 0 : TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
3397 :
3398 0 : printf("Retrieving printer propertiesfor %s...", cli1->desthost);
3399 0 : werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3400 : hnd1,
3401 : 2,
3402 : 0,
3403 : &info1);
3404 0 : if ( !W_ERROR_IS_OK(werror) ) {
3405 0 : printf("failed (%s)\n", win_errstr(werror));
3406 0 : talloc_destroy(mem_ctx);
3407 0 : return false;
3408 : }
3409 0 : printf("ok\n");
3410 :
3411 0 : printf("Retrieving printer properties for %s...", cli2->desthost);
3412 0 : werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3413 : hnd2,
3414 : 2,
3415 : 0,
3416 : &info2);
3417 0 : if ( !W_ERROR_IS_OK(werror) ) {
3418 0 : printf("failed (%s)\n", win_errstr(werror));
3419 0 : talloc_destroy(mem_ctx);
3420 0 : return false;
3421 : }
3422 0 : printf("ok\n");
3423 :
3424 0 : talloc_destroy(mem_ctx);
3425 :
3426 0 : return true;
3427 : }
3428 :
3429 : /****************************************************************************
3430 : ****************************************************************************/
3431 :
3432 0 : static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
3433 : struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
3434 : {
3435 : union spoolss_PrinterInfo info1, info2;
3436 : WERROR werror;
3437 0 : TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
3438 : struct security_descriptor *sd1, *sd2;
3439 0 : bool result = true;
3440 :
3441 :
3442 0 : printf("Retrieving printer security for %s...", cli1->desthost);
3443 0 : werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
3444 : hnd1,
3445 : 3,
3446 : 0,
3447 : &info1);
3448 0 : if ( !W_ERROR_IS_OK(werror) ) {
3449 0 : printf("failed (%s)\n", win_errstr(werror));
3450 0 : result = false;
3451 0 : goto done;
3452 : }
3453 0 : printf("ok\n");
3454 :
3455 0 : printf("Retrieving printer security for %s...", cli2->desthost);
3456 0 : werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
3457 : hnd2,
3458 : 3,
3459 : 0,
3460 : &info2);
3461 0 : if ( !W_ERROR_IS_OK(werror) ) {
3462 0 : printf("failed (%s)\n", win_errstr(werror));
3463 0 : result = false;
3464 0 : goto done;
3465 : }
3466 0 : printf("ok\n");
3467 :
3468 :
3469 0 : printf("++ ");
3470 :
3471 0 : sd1 = info1.info3.secdesc;
3472 0 : sd2 = info2.info3.secdesc;
3473 :
3474 0 : if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
3475 0 : printf("NULL secdesc!\n");
3476 0 : result = false;
3477 0 : goto done;
3478 : }
3479 :
3480 0 : if (!security_descriptor_equal( sd1, sd2 ) ) {
3481 0 : printf("Security Descriptors *not* equal!\n");
3482 0 : result = false;
3483 0 : goto done;
3484 : }
3485 :
3486 0 : printf("Security descriptors match\n");
3487 :
3488 0 : done:
3489 0 : talloc_destroy(mem_ctx);
3490 0 : return result;
3491 : }
3492 :
3493 :
3494 : /****************************************************************************
3495 : ****************************************************************************/
3496 :
3497 0 : static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
3498 : TALLOC_CTX *mem_ctx, int argc,
3499 : const char **argv)
3500 : {
3501 : const char *printername;
3502 0 : char *printername_path = NULL;
3503 0 : struct cli_state *cli_server2 = NULL;
3504 0 : struct rpc_pipe_client *cli2 = NULL;
3505 : struct policy_handle hPrinter1, hPrinter2;
3506 : NTSTATUS nt_status;
3507 : WERROR werror;
3508 0 : struct cli_credentials *creds = samba_cmdline_get_creds();
3509 :
3510 0 : if ( argc != 3 ) {
3511 0 : printf("Usage: %s <printer> <server>\n", argv[0]);
3512 0 : return WERR_OK;
3513 : }
3514 :
3515 0 : printername = argv[1];
3516 :
3517 : /* first get the connection to the remote server */
3518 :
3519 0 : nt_status = cli_full_connection_creds(&cli_server2, lp_netbios_name(), argv[2],
3520 : NULL, 0,
3521 : "IPC$", "IPC",
3522 : creds,
3523 : CLI_FULL_CONNECTION_IPC);
3524 0 : if ( !NT_STATUS_IS_OK(nt_status) )
3525 0 : return WERR_GEN_FAILURE;
3526 :
3527 0 : nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
3528 : &cli2);
3529 0 : if (!NT_STATUS_IS_OK(nt_status)) {
3530 0 : printf("failed to open spoolss pipe on server %s (%s)\n",
3531 0 : argv[2], nt_errstr(nt_status));
3532 0 : return WERR_GEN_FAILURE;
3533 : }
3534 :
3535 : /* now open up both printers */
3536 :
3537 0 : RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
3538 :
3539 0 : printf("Opening %s...", printername_path);
3540 :
3541 0 : werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3542 : printername_path,
3543 : PRINTER_ALL_ACCESS,
3544 : &hPrinter1);
3545 0 : if ( !W_ERROR_IS_OK(werror) ) {
3546 0 : printf("failed (%s)\n", win_errstr(werror));
3547 0 : goto done;
3548 : }
3549 0 : printf("ok\n");
3550 :
3551 0 : RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
3552 :
3553 0 : printf("Opening %s...", printername_path);
3554 0 : werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
3555 : printername_path,
3556 : PRINTER_ALL_ACCESS,
3557 : &hPrinter2);
3558 0 : if ( !W_ERROR_IS_OK(werror) ) {
3559 0 : printf("failed (%s)\n", win_errstr(werror));
3560 0 : goto done;
3561 : }
3562 0 : printf("ok\n");
3563 :
3564 0 : compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
3565 0 : compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
3566 : #if 0
3567 : compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
3568 : #endif
3569 :
3570 :
3571 0 : done:
3572 : /* cleanup */
3573 :
3574 0 : printf("Closing printers...");
3575 : {
3576 : WERROR _result;
3577 0 : dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
3578 0 : dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
3579 : }
3580 0 : printf("ok\n");
3581 :
3582 : /* close the second remote connection */
3583 :
3584 0 : cli_shutdown( cli_server2 );
3585 0 : return WERR_OK;
3586 : }
3587 :
3588 0 : static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
3589 : {
3590 0 : printf("print_processor_name: %s\n", r->print_processor_name);
3591 0 : }
3592 :
3593 0 : static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
3594 : TALLOC_CTX *mem_ctx, int argc,
3595 : const char **argv)
3596 : {
3597 : WERROR werror;
3598 0 : const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
3599 0 : uint32_t num_procs, level = 1, i;
3600 : union spoolss_PrintProcessorInfo *procs;
3601 :
3602 : /* Parse the command arguments */
3603 :
3604 0 : if (argc < 1 || argc > 4) {
3605 0 : printf ("Usage: %s [environment] [level]\n", argv[0]);
3606 0 : return WERR_OK;
3607 : }
3608 :
3609 0 : if (argc >= 2) {
3610 0 : environment = argv[1];
3611 : }
3612 :
3613 0 : if (argc == 3) {
3614 0 : level = atoi(argv[2]);
3615 : }
3616 :
3617 : /* Enumerate Print Processors */
3618 :
3619 0 : werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
3620 0 : cli->srv_name_slash,
3621 : environment,
3622 : level,
3623 : 0,
3624 : &num_procs,
3625 : &procs);
3626 0 : if (!W_ERROR_IS_OK(werror))
3627 0 : goto done;
3628 :
3629 : /* Display output */
3630 :
3631 0 : for (i = 0; i < num_procs; i++) {
3632 0 : switch (level) {
3633 0 : case 1:
3634 0 : display_proc_info1(&procs[i].info1);
3635 0 : break;
3636 : }
3637 : }
3638 :
3639 0 : done:
3640 0 : return werror;
3641 : }
3642 :
3643 0 : static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
3644 : {
3645 0 : printf("name_array: %s\n", r->name_array);
3646 0 : }
3647 :
3648 0 : static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
3649 : TALLOC_CTX *mem_ctx, int argc,
3650 : const char **argv)
3651 : {
3652 : WERROR werror;
3653 0 : const char *print_processor_name = "winprint";
3654 0 : uint32_t num_procs, level = 1, i;
3655 : union spoolss_PrintProcDataTypesInfo *procs;
3656 :
3657 : /* Parse the command arguments */
3658 :
3659 0 : if (argc < 1 || argc > 4) {
3660 0 : printf ("Usage: %s [environment] [level]\n", argv[0]);
3661 0 : return WERR_OK;
3662 : }
3663 :
3664 0 : if (argc >= 2) {
3665 0 : print_processor_name = argv[1];
3666 : }
3667 :
3668 0 : if (argc == 3) {
3669 0 : level = atoi(argv[2]);
3670 : }
3671 :
3672 : /* Enumerate Print Processor Data Types */
3673 :
3674 0 : werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
3675 0 : cli->srv_name_slash,
3676 : print_processor_name,
3677 : level,
3678 : 0,
3679 : &num_procs,
3680 : &procs);
3681 0 : if (!W_ERROR_IS_OK(werror))
3682 0 : goto done;
3683 :
3684 : /* Display output */
3685 :
3686 0 : for (i = 0; i < num_procs; i++) {
3687 0 : switch (level) {
3688 0 : case 1:
3689 0 : display_proc_data_types_info1(&procs[i].info1);
3690 0 : break;
3691 : }
3692 : }
3693 :
3694 0 : done:
3695 0 : return werror;
3696 : }
3697 :
3698 0 : static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
3699 : {
3700 0 : printf("monitor_name: %s\n", r->monitor_name);
3701 0 : }
3702 :
3703 0 : static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
3704 : {
3705 0 : printf("monitor_name: %s\n", r->monitor_name);
3706 0 : printf("environment: %s\n", r->environment);
3707 0 : printf("dll_name: %s\n", r->dll_name);
3708 0 : }
3709 :
3710 0 : static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
3711 : TALLOC_CTX *mem_ctx, int argc,
3712 : const char **argv)
3713 : {
3714 : WERROR werror;
3715 0 : uint32_t count, level = 1, i;
3716 : union spoolss_MonitorInfo *info;
3717 :
3718 : /* Parse the command arguments */
3719 :
3720 0 : if (argc > 2) {
3721 0 : printf("Usage: %s [level]\n", argv[0]);
3722 0 : return WERR_OK;
3723 : }
3724 :
3725 0 : if (argc == 2) {
3726 0 : level = atoi(argv[1]);
3727 : }
3728 :
3729 : /* Enumerate Print Monitors */
3730 :
3731 0 : werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
3732 0 : cli->srv_name_slash,
3733 : level,
3734 : 0,
3735 : &count,
3736 : &info);
3737 0 : if (!W_ERROR_IS_OK(werror)) {
3738 0 : goto done;
3739 : }
3740 :
3741 : /* Display output */
3742 :
3743 0 : for (i = 0; i < count; i++) {
3744 0 : switch (level) {
3745 0 : case 1:
3746 0 : display_monitor1(&info[i].info1);
3747 0 : break;
3748 0 : case 2:
3749 0 : display_monitor2(&info[i].info2);
3750 0 : break;
3751 : }
3752 : }
3753 :
3754 0 : done:
3755 0 : return werror;
3756 : }
3757 :
3758 0 : static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
3759 : TALLOC_CTX *mem_ctx, int argc,
3760 : const char **argv)
3761 : {
3762 : WERROR result;
3763 : NTSTATUS status;
3764 : struct policy_handle handle, gdi_handle;
3765 : const char *printername;
3766 : struct spoolss_DevmodeContainer devmode_ctr;
3767 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3768 :
3769 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3770 :
3771 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3772 : printername,
3773 : SEC_FLAG_MAXIMUM_ALLOWED,
3774 : &handle);
3775 0 : if (!W_ERROR_IS_OK(result)) {
3776 0 : return result;
3777 : }
3778 :
3779 0 : ZERO_STRUCT(devmode_ctr);
3780 :
3781 0 : status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3782 : &handle,
3783 : &gdi_handle,
3784 : &devmode_ctr,
3785 : &result);
3786 0 : if (!NT_STATUS_IS_OK(status)) {
3787 0 : result = ntstatus_to_werror(status);
3788 0 : goto done;
3789 : }
3790 0 : if (!W_ERROR_IS_OK(result)) {
3791 0 : goto done;
3792 : }
3793 :
3794 0 : done:
3795 0 : if (is_valid_policy_hnd(&gdi_handle)) {
3796 : WERROR _result;
3797 0 : dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3798 : }
3799 0 : if (is_valid_policy_hnd(&handle)) {
3800 : WERROR _result;
3801 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3802 : }
3803 :
3804 0 : return result;
3805 : }
3806 :
3807 0 : static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
3808 : TALLOC_CTX *mem_ctx, int argc,
3809 : const char **argv)
3810 : {
3811 : WERROR result;
3812 : NTSTATUS status;
3813 : struct policy_handle handle, gdi_handle;
3814 : const char *printername;
3815 : struct spoolss_DevmodeContainer devmode_ctr;
3816 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3817 : DATA_BLOB in,out;
3818 0 : uint32_t count = 0;
3819 :
3820 0 : RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
3821 :
3822 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
3823 : printername,
3824 : SEC_FLAG_MAXIMUM_ALLOWED,
3825 : &handle);
3826 0 : if (!W_ERROR_IS_OK(result)) {
3827 0 : return result;
3828 : }
3829 :
3830 0 : ZERO_STRUCT(devmode_ctr);
3831 :
3832 0 : status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
3833 : &handle,
3834 : &gdi_handle,
3835 : &devmode_ctr,
3836 : &result);
3837 0 : if (!NT_STATUS_IS_OK(status)) {
3838 0 : result = ntstatus_to_werror(status);
3839 0 : goto done;
3840 : }
3841 0 : if (!W_ERROR_IS_OK(result)) {
3842 0 : goto done;
3843 : }
3844 :
3845 0 : in = data_blob_string_const("");
3846 0 : out = data_blob_talloc_zero(mem_ctx, 4);
3847 :
3848 0 : status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3849 : &gdi_handle,
3850 : in.data,
3851 0 : in.length,
3852 : out.data,
3853 0 : out.length,
3854 : 0, /* ul */
3855 : &result);
3856 0 : if (!NT_STATUS_IS_OK(status)) {
3857 0 : result = ntstatus_to_werror(status);
3858 0 : goto done;
3859 : }
3860 0 : if (!W_ERROR_IS_OK(result)) {
3861 0 : goto done;
3862 : }
3863 :
3864 0 : count = IVAL(out.data, 0);
3865 :
3866 0 : out = data_blob_talloc_zero(mem_ctx,
3867 0 : count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
3868 :
3869 0 : status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
3870 : &gdi_handle,
3871 : in.data,
3872 0 : in.length,
3873 : out.data,
3874 0 : out.length,
3875 : 0, /* ul */
3876 : &result);
3877 0 : if (!NT_STATUS_IS_OK(status)) {
3878 0 : result = ntstatus_to_werror(status);
3879 0 : goto done;
3880 : }
3881 0 : if (!W_ERROR_IS_OK(result)) {
3882 0 : goto done;
3883 : }
3884 :
3885 : {
3886 : enum ndr_err_code ndr_err;
3887 : struct UNIVERSAL_FONT_ID_ctr r;
3888 :
3889 0 : ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
3890 : (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
3891 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3892 0 : NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
3893 : }
3894 : }
3895 :
3896 0 : done:
3897 0 : if (is_valid_policy_hnd(&gdi_handle)) {
3898 : WERROR _result;
3899 0 : dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
3900 : }
3901 0 : if (is_valid_policy_hnd(&handle)) {
3902 : WERROR _result;
3903 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
3904 : }
3905 :
3906 0 : return result;
3907 : }
3908 :
3909 0 : static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
3910 : TALLOC_CTX *mem_ctx, int argc,
3911 : const char **argv)
3912 : {
3913 : NTSTATUS status;
3914 : HRESULT result;
3915 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3916 0 : const char *architecture = SPOOLSS_ARCHITECTURE_x64;
3917 : struct spoolss_CorePrinterDriver core_printer_drivers;
3918 : DATA_BLOB blob;
3919 : bool ok;
3920 : int i;
3921 : uint32_t count;
3922 : const char **array;
3923 :
3924 0 : if (argc == 1) {
3925 0 : count = 1;
3926 0 : array = talloc_zero_array(mem_ctx, const char *, count + 1);
3927 0 : if (array == NULL) {
3928 0 : return WERR_NOT_ENOUGH_MEMORY;
3929 : }
3930 0 : array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
3931 0 : if (array[0] == NULL) {
3932 0 : return WERR_NOT_ENOUGH_MEMORY;
3933 : }
3934 : } else {
3935 0 : count = argc -1;
3936 0 : array = talloc_zero_array(mem_ctx, const char *, count + 1);
3937 0 : if (array == NULL) {
3938 0 : return WERR_NOT_ENOUGH_MEMORY;
3939 : }
3940 0 : for (i = 0; i < argc - 1; i++) {
3941 0 : array[i] = talloc_strdup(array, argv[i + 1]);
3942 0 : if (array[i] == NULL) {
3943 0 : return WERR_NOT_ENOUGH_MEMORY;
3944 : }
3945 : }
3946 : }
3947 :
3948 0 : ok = push_reg_multi_sz(mem_ctx, &blob, array);
3949 0 : if (!ok) {
3950 0 : return WERR_NOT_ENOUGH_MEMORY;
3951 : }
3952 :
3953 0 : status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
3954 0 : cli->srv_name_slash,
3955 : architecture,
3956 0 : blob.length/2,
3957 0 : (uint16_t *)blob.data,
3958 : count,
3959 : &core_printer_drivers,
3960 : &result);
3961 0 : if (!NT_STATUS_IS_OK(status)) {
3962 0 : return ntstatus_to_werror(status);
3963 : }
3964 :
3965 0 : if (!HRES_IS_OK(result)) {
3966 0 : return W_ERROR(WIN32_FROM_HRESULT(result));
3967 : }
3968 :
3969 0 : return WERR_OK;
3970 : }
3971 :
3972 0 : static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
3973 : TALLOC_CTX *mem_ctx, int argc,
3974 : const char **argv)
3975 : {
3976 : NTSTATUS status;
3977 : WERROR result;
3978 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
3979 0 : const char *servername = cli->srv_name_slash;
3980 0 : DATA_BLOB in = data_blob_null;
3981 : struct spoolss_PrinterInfo4 *info;
3982 : uint32_t needed, count;
3983 :
3984 0 : if (argc > 2) {
3985 0 : printf("usage: %s [servername]\n", argv[0]);
3986 0 : return WERR_OK;
3987 : }
3988 :
3989 0 : if (argc > 1) {
3990 0 : servername = argv[1];
3991 : }
3992 :
3993 0 : status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
3994 : servername,
3995 : &in,
3996 0 : in.length,
3997 : &count,
3998 : &info,
3999 : &needed,
4000 : &result);
4001 0 : if (!NT_STATUS_IS_OK(status)) {
4002 0 : return ntstatus_to_werror(status);
4003 : }
4004 :
4005 0 : if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
4006 0 : in = data_blob_talloc_zero(mem_ctx, needed);
4007 0 : status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
4008 : servername,
4009 : &in,
4010 0 : in.length,
4011 : &count,
4012 : &info,
4013 : &needed,
4014 : &result);
4015 0 : if (!NT_STATUS_IS_OK(status)) {
4016 0 : return ntstatus_to_werror(status);
4017 : }
4018 : }
4019 :
4020 0 : return result;
4021 : }
4022 :
4023 0 : static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
4024 : TALLOC_CTX *mem_ctx, int argc,
4025 : const char **argv)
4026 : {
4027 : NTSTATUS status;
4028 : WERROR result;
4029 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
4030 0 : const char *servername = cli->srv_name_slash;
4031 0 : const char *printername = "Microsoft Print to PDF";
4032 0 : const char *printserver = "samba.org";
4033 0 : const char *provider = ""; /* refers to Win32spl.dll then */
4034 : const char *composed_printername;
4035 :
4036 0 : if (argc > 5) {
4037 0 : printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
4038 0 : return WERR_OK;
4039 : }
4040 :
4041 0 : if (argc > 1) {
4042 0 : servername = argv[1];
4043 : }
4044 0 : if (argc > 2) {
4045 0 : printername = argv[2];
4046 : }
4047 0 : if (argc > 3) {
4048 0 : printserver = argv[3];
4049 : }
4050 0 : if (argc > 4) {
4051 0 : provider = argv[4];
4052 : }
4053 :
4054 0 : composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4055 : printername);
4056 0 : if (composed_printername == NULL) {
4057 0 : return WERR_NOT_ENOUGH_MEMORY;
4058 : }
4059 0 : status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
4060 : servername,
4061 : composed_printername,
4062 : printserver,
4063 : provider,
4064 : &result);
4065 0 : if (!NT_STATUS_IS_OK(status)) {
4066 0 : return ntstatus_to_werror(status);
4067 : }
4068 :
4069 0 : return result;
4070 : }
4071 :
4072 0 : static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
4073 : TALLOC_CTX *mem_ctx, int argc,
4074 : const char **argv)
4075 : {
4076 : NTSTATUS status;
4077 : WERROR result;
4078 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
4079 0 : const char *servername = cli->srv_name_slash;
4080 0 : const char *printername = "Microsoft Print to PDF";
4081 : const char *composed_printername;
4082 :
4083 0 : if (argc > 3) {
4084 0 : printf("usage: %s [servername] [printername]\n", argv[0]);
4085 0 : return WERR_OK;
4086 : }
4087 :
4088 0 : if (argc > 1) {
4089 0 : servername = argv[1];
4090 : }
4091 0 : if (argc > 2) {
4092 0 : printername = argv[2];
4093 : }
4094 :
4095 0 : composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
4096 : printername);
4097 0 : if (composed_printername == NULL) {
4098 0 : return WERR_NOT_ENOUGH_MEMORY;
4099 : }
4100 :
4101 0 : status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
4102 : servername,
4103 : composed_printername,
4104 : &result);
4105 0 : if (!NT_STATUS_IS_OK(status)) {
4106 0 : return ntstatus_to_werror(status);
4107 : }
4108 :
4109 0 : return result;
4110 : }
4111 :
4112 : /* List of commands exported by this module */
4113 : struct cmd_set spoolss_commands[] = {
4114 :
4115 : {
4116 : .name = "SPOOLSS",
4117 : },
4118 :
4119 : {
4120 : .name = "adddriver",
4121 : .returntype = RPC_RTYPE_WERROR,
4122 : .ntfn = NULL,
4123 : .wfn = cmd_spoolss_addprinterdriver,
4124 : .table = &ndr_table_spoolss,
4125 : .rpc_pipe = NULL,
4126 : .description = "Add a print driver",
4127 : .usage = "",
4128 : .use_netlogon_creds = false,
4129 : },
4130 : {
4131 : .name = "addprinter",
4132 : .returntype = RPC_RTYPE_WERROR,
4133 : .ntfn = NULL,
4134 : .wfn = cmd_spoolss_addprinterex,
4135 : .table = &ndr_table_spoolss,
4136 : .rpc_pipe = NULL,
4137 : .description = "Add a printer",
4138 : .usage = "",
4139 : },
4140 : {
4141 : .name = "deldriver",
4142 : .returntype = RPC_RTYPE_WERROR,
4143 : .ntfn = NULL,
4144 : .wfn = cmd_spoolss_deletedriver,
4145 : .table = &ndr_table_spoolss,
4146 : .rpc_pipe = NULL,
4147 : .description = "Delete a printer driver",
4148 : .usage = "",
4149 : },
4150 : {
4151 : .name = "deldriverex",
4152 : .returntype = RPC_RTYPE_WERROR,
4153 : .ntfn = NULL,
4154 : .wfn = cmd_spoolss_deletedriverex,
4155 : .table = &ndr_table_spoolss,
4156 : .rpc_pipe = NULL,
4157 : .description = "Delete a printer driver with files",
4158 : .usage = "",
4159 : },
4160 : {
4161 : .name = "enumdata",
4162 : .returntype = RPC_RTYPE_WERROR,
4163 : .ntfn = NULL,
4164 : .wfn = cmd_spoolss_enum_data,
4165 : .table = &ndr_table_spoolss,
4166 : .rpc_pipe = NULL,
4167 : .description = "Enumerate printer data",
4168 : .usage = "",
4169 : },
4170 : {
4171 : .name = "enumdataex",
4172 : .returntype = RPC_RTYPE_WERROR,
4173 : .ntfn = NULL,
4174 : .wfn = cmd_spoolss_enum_data_ex,
4175 : .table = &ndr_table_spoolss,
4176 : .rpc_pipe = NULL,
4177 : .description = "Enumerate printer data for a key",
4178 : .usage = "",
4179 : },
4180 : {
4181 : .name = "enumkey",
4182 : .returntype = RPC_RTYPE_WERROR,
4183 : .ntfn = NULL,
4184 : .wfn = cmd_spoolss_enum_printerkey,
4185 : .table = &ndr_table_spoolss,
4186 : .rpc_pipe = NULL,
4187 : .description = "Enumerate printer keys",
4188 : .usage = "",
4189 : },
4190 : {
4191 : .name = "enumjobs",
4192 : .returntype = RPC_RTYPE_WERROR,
4193 : .ntfn = NULL,
4194 : .wfn = cmd_spoolss_enum_jobs,
4195 : .table = &ndr_table_spoolss,
4196 : .rpc_pipe = NULL,
4197 : .description = "Enumerate print jobs",
4198 : .usage = "",
4199 : },
4200 : {
4201 : .name = "getjob",
4202 : .returntype = RPC_RTYPE_WERROR,
4203 : .ntfn = NULL,
4204 : .wfn = cmd_spoolss_get_job,
4205 : .table = &ndr_table_spoolss,
4206 : .rpc_pipe = NULL,
4207 : .description = "Get print job",
4208 : .usage = "",
4209 : },
4210 : {
4211 : .name = "setjob",
4212 : .returntype = RPC_RTYPE_WERROR,
4213 : .ntfn = NULL,
4214 : .wfn = cmd_spoolss_set_job,
4215 : .table = &ndr_table_spoolss,
4216 : .rpc_pipe = NULL,
4217 : .description = "Set print job",
4218 : .usage = "",
4219 : },
4220 : {
4221 : .name = "enumports",
4222 : .returntype = RPC_RTYPE_WERROR,
4223 : .ntfn = NULL,
4224 : .wfn = cmd_spoolss_enum_ports,
4225 : .table = &ndr_table_spoolss,
4226 : .rpc_pipe = NULL,
4227 : .description = "Enumerate printer ports",
4228 : .usage = "",
4229 : },
4230 : {
4231 : .name = "enumdrivers",
4232 : .returntype = RPC_RTYPE_WERROR,
4233 : .ntfn = NULL,
4234 : .wfn = cmd_spoolss_enum_drivers,
4235 : .table = &ndr_table_spoolss,
4236 : .rpc_pipe = NULL,
4237 : .description = "Enumerate installed printer drivers",
4238 : .usage = "",
4239 : },
4240 : {
4241 : .name = "enumprinters",
4242 : .returntype = RPC_RTYPE_WERROR,
4243 : .ntfn = NULL,
4244 : .wfn = cmd_spoolss_enum_printers,
4245 : .table = &ndr_table_spoolss,
4246 : .rpc_pipe = NULL,
4247 : .description = "Enumerate printers",
4248 : .usage = "",
4249 : },
4250 : {
4251 : .name = "getdata",
4252 : .returntype = RPC_RTYPE_WERROR,
4253 : .ntfn = NULL,
4254 : .wfn = cmd_spoolss_getprinterdata,
4255 : .table = &ndr_table_spoolss,
4256 : .rpc_pipe = NULL,
4257 : .description = "Get print driver data",
4258 : .usage = "",
4259 : },
4260 : {
4261 : .name = "getdataex",
4262 : .returntype = RPC_RTYPE_WERROR,
4263 : .ntfn = NULL,
4264 : .wfn = cmd_spoolss_getprinterdataex,
4265 : .table = &ndr_table_spoolss,
4266 : .rpc_pipe = NULL,
4267 : .description = "Get printer driver data with keyname",
4268 : .usage = "",
4269 : },
4270 : {
4271 : .name = "getdriver",
4272 : .returntype = RPC_RTYPE_WERROR,
4273 : .ntfn = NULL,
4274 : .wfn = cmd_spoolss_getdriver,
4275 : .table = &ndr_table_spoolss,
4276 : .rpc_pipe = NULL,
4277 : .description = "Get print driver information",
4278 : .usage = "",
4279 : },
4280 : {
4281 : .name = "getdriverdir",
4282 : .returntype = RPC_RTYPE_WERROR,
4283 : .ntfn = NULL,
4284 : .wfn = cmd_spoolss_getdriverdir,
4285 : .table = &ndr_table_spoolss,
4286 : .rpc_pipe = NULL,
4287 : .description = "Get print driver upload directory",
4288 : .usage = "",
4289 : },
4290 : {
4291 : .name = "getdriverpackagepath",
4292 : .returntype = RPC_RTYPE_WERROR,
4293 : .ntfn = NULL,
4294 : .wfn = cmd_spoolss_getdriverpackagepath,
4295 : .table = &ndr_table_spoolss,
4296 : .rpc_pipe = NULL,
4297 : .description = "Get print driver package download directory",
4298 : .usage = "",
4299 : },
4300 : {
4301 : .name = "getprinter",
4302 : .returntype = RPC_RTYPE_WERROR,
4303 : .ntfn = NULL,
4304 : .wfn = cmd_spoolss_getprinter,
4305 : .table = &ndr_table_spoolss,
4306 : .rpc_pipe = NULL,
4307 : .description = "Get printer info",
4308 : .usage = "",
4309 : },
4310 : {
4311 : .name = "openprinter",
4312 : .returntype = RPC_RTYPE_WERROR,
4313 : .ntfn = NULL,
4314 : .wfn = cmd_spoolss_open_printer,
4315 : .table = &ndr_table_spoolss,
4316 : .rpc_pipe = NULL,
4317 : .description = "Open printer handle",
4318 : .usage = "",
4319 : },
4320 : {
4321 : .name = "openprinter_ex",
4322 : .returntype = RPC_RTYPE_WERROR,
4323 : .ntfn = NULL,
4324 : .wfn = cmd_spoolss_open_printer_ex,
4325 : .table = &ndr_table_spoolss,
4326 : .rpc_pipe = NULL,
4327 : .description = "Open printer handle",
4328 : .usage = "",
4329 : },
4330 : {
4331 : .name = "setdriver",
4332 : .returntype = RPC_RTYPE_WERROR,
4333 : .ntfn = NULL,
4334 : .wfn = cmd_spoolss_setdriver,
4335 : .table = &ndr_table_spoolss,
4336 : .rpc_pipe = NULL,
4337 : .description = "Set printer driver",
4338 : .usage = "",
4339 : },
4340 : {
4341 : .name = "getprintprocdir",
4342 : .returntype = RPC_RTYPE_WERROR,
4343 : .ntfn = NULL,
4344 : .wfn = cmd_spoolss_getprintprocdir,
4345 : .table = &ndr_table_spoolss,
4346 : .rpc_pipe = NULL,
4347 : .description = "Get print processor directory",
4348 : .usage = "",
4349 : },
4350 : {
4351 : .name = "addform",
4352 : .returntype = RPC_RTYPE_WERROR,
4353 : .ntfn = NULL,
4354 : .wfn = cmd_spoolss_addform,
4355 : .table = &ndr_table_spoolss,
4356 : .rpc_pipe = NULL,
4357 : .description = "Add form",
4358 : .usage = "",
4359 : },
4360 : {
4361 : .name = "setform",
4362 : .returntype = RPC_RTYPE_WERROR,
4363 : .ntfn = NULL,
4364 : .wfn = cmd_spoolss_setform,
4365 : .table = &ndr_table_spoolss,
4366 : .rpc_pipe = NULL,
4367 : .description = "Set form",
4368 : .usage = "",
4369 : },
4370 : {
4371 : .name = "getform",
4372 : .returntype = RPC_RTYPE_WERROR,
4373 : .ntfn = NULL,
4374 : .wfn = cmd_spoolss_getform,
4375 : .table = &ndr_table_spoolss,
4376 : .rpc_pipe = NULL,
4377 : .description = "Get form",
4378 : .usage = "",
4379 : },
4380 : {
4381 : .name = "deleteform",
4382 : .returntype = RPC_RTYPE_WERROR,
4383 : .ntfn = NULL,
4384 : .wfn = cmd_spoolss_deleteform,
4385 : .table = &ndr_table_spoolss,
4386 : .rpc_pipe = NULL,
4387 : .description = "Delete form",
4388 : .usage = "",
4389 : },
4390 : {
4391 : .name = "enumforms",
4392 : .returntype = RPC_RTYPE_WERROR,
4393 : .ntfn = NULL,
4394 : .wfn = cmd_spoolss_enum_forms,
4395 : .table = &ndr_table_spoolss,
4396 : .rpc_pipe = NULL,
4397 : .description = "Enumerate forms",
4398 : .usage = "",
4399 : },
4400 : {
4401 : .name = "setprinter",
4402 : .returntype = RPC_RTYPE_WERROR,
4403 : .ntfn = NULL,
4404 : .wfn = cmd_spoolss_setprinter,
4405 : .table = &ndr_table_spoolss,
4406 : .rpc_pipe = NULL,
4407 : .description = "Set printer comment",
4408 : .usage = "",
4409 : },
4410 : {
4411 : .name = "setprintername",
4412 : .returntype = RPC_RTYPE_WERROR,
4413 : .ntfn = NULL,
4414 : .wfn = cmd_spoolss_setprintername,
4415 : .table = &ndr_table_spoolss,
4416 : .rpc_pipe = NULL,
4417 : .description = "Set printername",
4418 : .usage = "",
4419 : },
4420 : {
4421 : .name = "setprinterdata",
4422 : .returntype = RPC_RTYPE_WERROR,
4423 : .ntfn = NULL,
4424 : .wfn = cmd_spoolss_setprinterdata,
4425 : .table = &ndr_table_spoolss,
4426 : .rpc_pipe = NULL,
4427 : .description = "Set REG_SZ printer data",
4428 : .usage = "",
4429 : },
4430 : {
4431 : .name = "rffpcnex",
4432 : .returntype = RPC_RTYPE_WERROR,
4433 : .ntfn = NULL,
4434 : .wfn = cmd_spoolss_rffpcnex,
4435 : .table = &ndr_table_spoolss,
4436 : .rpc_pipe = NULL,
4437 : .description = "Rffpcnex test",
4438 : .usage = "",
4439 : },
4440 : {
4441 : .name = "printercmp",
4442 : .returntype = RPC_RTYPE_WERROR,
4443 : .ntfn = NULL,
4444 : .wfn = cmd_spoolss_printercmp,
4445 : .table = &ndr_table_spoolss,
4446 : .rpc_pipe = NULL,
4447 : .description = "Printer comparison test",
4448 : .usage = "",
4449 : },
4450 : {
4451 : .name = "enumprocs",
4452 : .returntype = RPC_RTYPE_WERROR,
4453 : .ntfn = NULL,
4454 : .wfn = cmd_spoolss_enum_procs,
4455 : .table = &ndr_table_spoolss,
4456 : .rpc_pipe = NULL,
4457 : .description = "Enumerate Print Processors",
4458 : .usage = "",
4459 : },
4460 : {
4461 : .name = "enumprocdatatypes",
4462 : .returntype = RPC_RTYPE_WERROR,
4463 : .ntfn = NULL,
4464 : .wfn = cmd_spoolss_enum_proc_data_types,
4465 : .table = &ndr_table_spoolss,
4466 : .rpc_pipe = NULL,
4467 : .description = "Enumerate Print Processor Data Types",
4468 : .usage = "",
4469 : },
4470 : {
4471 : .name = "enummonitors",
4472 : .returntype = RPC_RTYPE_WERROR,
4473 : .ntfn = NULL,
4474 : .wfn = cmd_spoolss_enum_monitors,
4475 : .table = &ndr_table_spoolss,
4476 : .rpc_pipe = NULL,
4477 : .description = "Enumerate Print Monitors",
4478 : .usage = "",
4479 : },
4480 : {
4481 : .name = "createprinteric",
4482 : .returntype = RPC_RTYPE_WERROR,
4483 : .ntfn = NULL,
4484 : .wfn = cmd_spoolss_create_printer_ic,
4485 : .table = &ndr_table_spoolss,
4486 : .rpc_pipe = NULL,
4487 : .description = "Create Printer IC",
4488 : .usage = "",
4489 : },
4490 : {
4491 : .name = "playgdiscriptonprinteric",
4492 : .returntype = RPC_RTYPE_WERROR,
4493 : .ntfn = NULL,
4494 : .wfn = cmd_spoolss_play_gdi_script_on_printer_ic,
4495 : .table = &ndr_table_spoolss,
4496 : .rpc_pipe = NULL,
4497 : .description = "Create Printer IC",
4498 : .usage = "",
4499 : },
4500 : {
4501 : .name = "getcoreprinterdrivers",
4502 : .returntype = RPC_RTYPE_WERROR,
4503 : .ntfn = NULL,
4504 : .wfn = cmd_spoolss_get_core_printer_drivers,
4505 : .table = &ndr_table_spoolss,
4506 : .rpc_pipe = NULL,
4507 : .description = "Get CorePrinterDriver",
4508 : .usage = "",
4509 : },
4510 : {
4511 : .name = "enumpermachineconnections",
4512 : .returntype = RPC_RTYPE_WERROR,
4513 : .ntfn = NULL,
4514 : .wfn = cmd_spoolss_enum_permachineconnections,
4515 : .table = &ndr_table_spoolss,
4516 : .rpc_pipe = NULL,
4517 : .description = "Enumerate Per Machine Connections",
4518 : .usage = "",
4519 : },
4520 : {
4521 : .name = "addpermachineconnection",
4522 : .returntype = RPC_RTYPE_WERROR,
4523 : .ntfn = NULL,
4524 : .wfn = cmd_spoolss_add_permachineconnection,
4525 : .table = &ndr_table_spoolss,
4526 : .rpc_pipe = NULL,
4527 : .description = "Add Per Machine Connection",
4528 : .usage = "",
4529 : },
4530 : {
4531 : .name = "delpermachineconnection",
4532 : .returntype = RPC_RTYPE_WERROR,
4533 : .ntfn = NULL,
4534 : .wfn = cmd_spoolss_del_permachineconnection,
4535 : .table = &ndr_table_spoolss,
4536 : .rpc_pipe = NULL,
4537 : .description = "Delete Per Machine Connection",
4538 : .usage = "",
4539 : },
4540 : {
4541 : .name = NULL,
4542 : },
4543 : };
|